diff options
32 files changed, 154 insertions, 134 deletions
| diff --git a/examples/stub.py b/examples/stub.py index e5b4a39a..4f5061e2 100644 --- a/examples/stub.py +++ b/examples/stub.py @@ -11,7 +11,7 @@ def start():      mitmproxy.ctx.log("start") -def configure(options): +def configure(options, updated):      """          Called once on script startup before any other events, and whenever options changes.      """ diff --git a/mitmproxy/addons.py b/mitmproxy/addons.py index c779aaf8..a4bea9fa 100644 --- a/mitmproxy/addons.py +++ b/mitmproxy/addons.py @@ -13,16 +13,23 @@ class Addons(object):          self.master = master          master.options.changed.connect(self.options_update) -    def options_update(self, options): +    def options_update(self, options, updated):          for i in self.chain:              with self.master.handlecontext(): -                i.configure(options) +                i.configure(options, updated) -    def add(self, *addons): +    def add(self, options, *addons): +        if not addons: +            raise ValueError("No adons specified.")          self.chain.extend(addons)          for i in addons:              self.invoke_with_context(i, "start") -            self.invoke_with_context(i, "configure", self.master.options) +            self.invoke_with_context( +                i, +                "configure", +                self.master.options, +                self.master.options.keys() +            )      def remove(self, addon):          self.chain = [i for i in self.chain if i is not addon] diff --git a/mitmproxy/builtins/anticache.py b/mitmproxy/builtins/anticache.py index f208e2fb..41a5ed95 100644 --- a/mitmproxy/builtins/anticache.py +++ b/mitmproxy/builtins/anticache.py @@ -5,7 +5,7 @@ class AntiCache:      def __init__(self):          self.enabled = False -    def configure(self, options): +    def configure(self, options, updated):          self.enabled = options.anticache      def request(self, flow): diff --git a/mitmproxy/builtins/anticomp.py b/mitmproxy/builtins/anticomp.py index 50bd1b73..823e960c 100644 --- a/mitmproxy/builtins/anticomp.py +++ b/mitmproxy/builtins/anticomp.py @@ -5,7 +5,7 @@ class AntiComp:      def __init__(self):          self.enabled = False -    def configure(self, options): +    def configure(self, options, updated):          self.enabled = options.anticomp      def request(self, flow): diff --git a/mitmproxy/builtins/dumper.py b/mitmproxy/builtins/dumper.py index 239630fb..34d3632e 100644 --- a/mitmproxy/builtins/dumper.py +++ b/mitmproxy/builtins/dumper.py @@ -217,7 +217,7 @@ class Dumper():              return True          return False -    def configure(self, options): +    def configure(self, options, updated):          if options.filtstr:              self.filt = filt.parse(options.filtstr)              if not self.filt: diff --git a/mitmproxy/builtins/filestreamer.py b/mitmproxy/builtins/filestreamer.py index 97ddc7c4..ffa565ac 100644 --- a/mitmproxy/builtins/filestreamer.py +++ b/mitmproxy/builtins/filestreamer.py @@ -19,7 +19,7 @@ class FileStreamer:          self.stream = io.FilteredFlowWriter(f, filt)          self.active_flows = set() -    def configure(self, options): +    def configure(self, options, updated):          # We're already streaming - stop the previous stream and restart          if self.stream:              self.done() diff --git a/mitmproxy/builtins/replace.py b/mitmproxy/builtins/replace.py index 83b96cee..74d30c05 100644 --- a/mitmproxy/builtins/replace.py +++ b/mitmproxy/builtins/replace.py @@ -8,7 +8,7 @@ class Replace:      def __init__(self):          self.lst = [] -    def configure(self, options): +    def configure(self, options, updated):          """              .replacements is a list of tuples (fpat, rex, s): diff --git a/mitmproxy/builtins/script.py b/mitmproxy/builtins/script.py index ed5f2ecd..c960dd1c 100644 --- a/mitmproxy/builtins/script.py +++ b/mitmproxy/builtins/script.py @@ -159,15 +159,16 @@ class Script:          if self.should_reload.is_set():              self.should_reload.clear()              ctx.log.info("Reloading script: %s" % self.name) -            self.load_script() -            self.configure(self.last_options) +            self.ns = load_script(self.path, self.args) +            self.start() +            self.configure(self.last_options, self.last_options.keys())          else:              self.run("tick")      def start(self):          self.load_script() -    def configure(self, options): +    def configure(self, options, updated):          self.last_options = options          if not self.observer:              self.observer = polling.PollingObserver() @@ -177,7 +178,7 @@ class Script:                  os.path.dirname(self.path) or "."              )              self.observer.start() -        self.run("configure", options) +        self.run("configure", options, updated)      def done(self):          self.run("done") @@ -188,26 +189,27 @@ class ScriptLoader():      """          An addon that manages loading scripts from options.      """ -    def configure(self, options): -        for s in options.scripts: -            if options.scripts.count(s) > 1: -                raise exceptions.OptionsError("Duplicate script: %s" % s) - -        for a in ctx.master.addons.chain[:]: -            if isinstance(a, Script) and a.name not in options.scripts: -                    ctx.log.info("Un-loading script: %s" % a.name) -                    ctx.master.addons.remove(a) - -        current = {} -        for a in ctx.master.addons.chain[:]: -            if isinstance(a, Script): -                current[a.name] = a -                ctx.master.addons.chain.remove(a) - -        for s in options.scripts: -            if s in current: -                ctx.master.addons.chain.append(current[s]) -            else: -                ctx.log.info("Loading script: %s" % s) -                sc = Script(s) -                ctx.master.addons.add(sc) +    def configure(self, options, updated): +        if "scripts" in updated: +            for s in options.scripts: +                if options.scripts.count(s) > 1: +                    raise exceptions.OptionsError("Duplicate script: %s" % s) + +            for a in ctx.master.addons.chain[:]: +                if isinstance(a, Script) and a.name not in options.scripts: +                        ctx.log.info("Un-loading script: %s" % a.name) +                        ctx.master.addons.remove(a) + +            current = {} +            for a in ctx.master.addons.chain[:]: +                if isinstance(a, Script): +                    current[a.name] = a +                    ctx.master.addons.chain.remove(a) + +            for s in options.scripts: +                if s in current: +                    ctx.master.addons.chain.append(current[s]) +                else: +                    ctx.log.info("Loading script: %s" % s) +                    sc = Script(s) +                    ctx.master.addons.add(options, sc) diff --git a/mitmproxy/builtins/setheaders.py b/mitmproxy/builtins/setheaders.py index 6bda3f55..4a784a1d 100644 --- a/mitmproxy/builtins/setheaders.py +++ b/mitmproxy/builtins/setheaders.py @@ -6,7 +6,7 @@ class SetHeaders:      def __init__(self):          self.lst = [] -    def configure(self, options): +    def configure(self, options, updated):          """              options.setheaders is a tuple of (fpatt, header, value) diff --git a/mitmproxy/builtins/stickyauth.py b/mitmproxy/builtins/stickyauth.py index 1309911c..98fb65ed 100644 --- a/mitmproxy/builtins/stickyauth.py +++ b/mitmproxy/builtins/stickyauth.py @@ -10,7 +10,7 @@ class StickyAuth:          self.flt = None          self.hosts = {} -    def configure(self, options): +    def configure(self, options, updated):          if options.stickyauth:              flt = filt.parse(options.stickyauth)              if not flt: diff --git a/mitmproxy/builtins/stickycookie.py b/mitmproxy/builtins/stickycookie.py index dc699bb4..88333d5c 100644 --- a/mitmproxy/builtins/stickycookie.py +++ b/mitmproxy/builtins/stickycookie.py @@ -32,7 +32,7 @@ class StickyCookie:          self.jar = collections.defaultdict(dict)          self.flt = None -    def configure(self, options): +    def configure(self, options, updated):          if options.stickycookie:              flt = filt.parse(options.stickycookie)              if not flt: diff --git a/mitmproxy/console/master.py b/mitmproxy/console/master.py index f4617f62..fad4c375 100644 --- a/mitmproxy/console/master.py +++ b/mitmproxy/console/master.py @@ -242,7 +242,7 @@ class ConsoleMaster(flow.FlowMaster):          signals.pop_view_state.connect(self.sig_pop_view_state)          signals.push_view_state.connect(self.sig_push_view_state)          signals.sig_add_log.connect(self.sig_add_log) -        self.addons.add(*builtins.default_addons()) +        self.addons.add(options, *builtins.default_addons())      def __setattr__(self, name, value):          self.__dict__[name] = value diff --git a/mitmproxy/dump.py b/mitmproxy/dump.py index 4f34ab95..83f44d87 100644 --- a/mitmproxy/dump.py +++ b/mitmproxy/dump.py @@ -42,8 +42,8 @@ class DumpMaster(flow.FlowMaster):      def __init__(self, server, options):          flow.FlowMaster.__init__(self, options, server, flow.State())          self.has_errored = False -        self.addons.add(*builtins.default_addons()) -        self.addons.add(dumper.Dumper()) +        self.addons.add(options, *builtins.default_addons()) +        self.addons.add(options, dumper.Dumper())          # This line is just for type hinting          self.options = self.options  # type: Options          self.replay_ignore_params = options.replay_ignore_params diff --git a/mitmproxy/optmanager.py b/mitmproxy/optmanager.py index e94ef51d..140c7ca8 100644 --- a/mitmproxy/optmanager.py +++ b/mitmproxy/optmanager.py @@ -35,7 +35,7 @@ class OptManager(object):          self.__dict__["_initialized"] = True      @contextlib.contextmanager -    def rollback(self): +    def rollback(self, updated):          old = self._opts.copy()          try:              yield @@ -44,7 +44,7 @@ class OptManager(object):              self.errored.send(self, exc=e)              # Rollback              self.__dict__["_opts"] = old -            self.changed.send(self) +            self.changed.send(self, updated=updated)      def __eq__(self, other):          return self._opts == other._opts @@ -62,22 +62,22 @@ class OptManager(object):          if not self._initialized:              self._opts[attr] = value              return -        if attr not in self._opts: -            raise KeyError("No such option: %s" % attr) -        with self.rollback(): -            self._opts[attr] = value -            self.changed.send(self) +        self.update(**{attr: value}) + +    def keys(self): +        return set(self._opts.keys())      def get(self, k, d=None):          return self._opts.get(k, d)      def update(self, **kwargs): +        updated = set(kwargs.keys())          for k in kwargs:              if k not in self._opts:                  raise KeyError("No such option: %s" % k) -        with self.rollback(): +        with self.rollback(updated):              self._opts.update(kwargs) -            self.changed.send(self) +            self.changed.send(self, updated=updated)      def setter(self, attr):          """ diff --git a/mitmproxy/proxy/config.py b/mitmproxy/proxy/config.py index 7aa4c736..a74ba7e2 100644 --- a/mitmproxy/proxy/config.py +++ b/mitmproxy/proxy/config.py @@ -79,10 +79,10 @@ class ProxyConfig:          self.certstore = None          self.clientcerts = None          self.openssl_verification_mode_server = None -        self.configure(options) +        self.configure(options, set(options.keys()))          options.changed.connect(self.configure) -    def configure(self, options): +    def configure(self, options, updated):          conflict = all(              [                  options.add_upstream_certs_to_client_chain, diff --git a/mitmproxy/web/master.py b/mitmproxy/web/master.py index 3d384612..9ddb61d4 100644 --- a/mitmproxy/web/master.py +++ b/mitmproxy/web/master.py @@ -136,7 +136,7 @@ class WebMaster(flow.FlowMaster):      def __init__(self, server, options):          super(WebMaster, self).__init__(options, server, WebState()) -        self.addons.add(*builtins.default_addons()) +        self.addons.add(options, *builtins.default_addons())          self.app = app.Application(              self, self.options.wdebug, self.options.wauthenticator          ) diff --git a/test/mitmproxy/builtins/test_anticache.py b/test/mitmproxy/builtins/test_anticache.py index 5a00af03..ac321e26 100644 --- a/test/mitmproxy/builtins/test_anticache.py +++ b/test/mitmproxy/builtins/test_anticache.py @@ -8,9 +8,10 @@ from mitmproxy import options  class TestAntiCache(mastertest.MasterTest):      def test_simple(self):          s = state.State() -        m = master.FlowMaster(options.Options(anticache = True), None, s) +        o = options.Options(anticache = True) +        m = master.FlowMaster(o, None, s)          sa = anticache.AntiCache() -        m.addons.add(sa) +        m.addons.add(o, sa)          f = tutils.tflow(resp=True)          self.invoke(m, "request", f) diff --git a/test/mitmproxy/builtins/test_anticomp.py b/test/mitmproxy/builtins/test_anticomp.py index 6bfd54bb..a5f5a270 100644 --- a/test/mitmproxy/builtins/test_anticomp.py +++ b/test/mitmproxy/builtins/test_anticomp.py @@ -8,9 +8,10 @@ from mitmproxy import options  class TestAntiComp(mastertest.MasterTest):      def test_simple(self):          s = state.State() -        m = master.FlowMaster(options.Options(anticomp = True), None, s) +        o = options.Options(anticomp = True) +        m = master.FlowMaster(o, None, s)          sa = anticomp.AntiComp() -        m.addons.add(sa) +        m.addons.add(o, sa)          f = tutils.tflow(resp=True)          self.invoke(m, "request", f) diff --git a/test/mitmproxy/builtins/test_dumper.py b/test/mitmproxy/builtins/test_dumper.py index 57e3d036..6287fe86 100644 --- a/test/mitmproxy/builtins/test_dumper.py +++ b/test/mitmproxy/builtins/test_dumper.py @@ -15,26 +15,27 @@ class TestDumper(mastertest.MasterTest):          d = dumper.Dumper()          sio = StringIO() -        d.configure(dump.Options(tfile = sio, flow_detail = 0)) +        updated = set(["tfile", "flow_detail"]) +        d.configure(dump.Options(tfile = sio, flow_detail = 0), updated)          d.response(tutils.tflow())          assert not sio.getvalue() -        d.configure(dump.Options(tfile = sio, flow_detail = 4)) +        d.configure(dump.Options(tfile = sio, flow_detail = 4), updated)          d.response(tutils.tflow())          assert sio.getvalue()          sio = StringIO() -        d.configure(dump.Options(tfile = sio, flow_detail = 4)) +        d.configure(dump.Options(tfile = sio, flow_detail = 4), updated)          d.response(tutils.tflow(resp=True))          assert "<<" in sio.getvalue()          sio = StringIO() -        d.configure(dump.Options(tfile = sio, flow_detail = 4)) +        d.configure(dump.Options(tfile = sio, flow_detail = 4), updated)          d.response(tutils.tflow(err=True))          assert "<<" in sio.getvalue()          sio = StringIO() -        d.configure(dump.Options(tfile = sio, flow_detail = 4)) +        d.configure(dump.Options(tfile = sio, flow_detail = 4), updated)          flow = tutils.tflow()          flow.request = netlib.tutils.treq()          flow.request.stickycookie = True @@ -47,7 +48,7 @@ class TestDumper(mastertest.MasterTest):          assert sio.getvalue()          sio = StringIO() -        d.configure(dump.Options(tfile = sio, flow_detail = 4)) +        d.configure(dump.Options(tfile = sio, flow_detail = 4), updated)          flow = tutils.tflow(resp=netlib.tutils.tresp(content=b"{"))          flow.response.headers["content-type"] = "application/json"          flow.response.status_code = 400 @@ -55,7 +56,7 @@ class TestDumper(mastertest.MasterTest):          assert sio.getvalue()          sio = StringIO() -        d.configure(dump.Options(tfile = sio)) +        d.configure(dump.Options(tfile = sio), updated)          flow = tutils.tflow()          flow.request.content = None          flow.response = models.HTTPResponse.wrap(netlib.tutils.tresp()) @@ -72,15 +73,13 @@ class TestContentView(mastertest.MasterTest):          s = state.State()          sio = StringIO() -        m = mastertest.RecordingMaster( -            dump.Options( -                flow_detail=4, -                verbosity=3, -                tfile=sio, -            ), -            None, s +        o = dump.Options( +            flow_detail=4, +            verbosity=3, +            tfile=sio,          ) +        m = mastertest.RecordingMaster(o, None, s)          d = dumper.Dumper() -        m.addons.add(d) +        m.addons.add(o, d)          self.invoke(m, "response", tutils.tflow())          assert "Content viewer failed" in m.event_log[0][1] diff --git a/test/mitmproxy/builtins/test_filestreamer.py b/test/mitmproxy/builtins/test_filestreamer.py index c1d5947f..0e69b340 100644 --- a/test/mitmproxy/builtins/test_filestreamer.py +++ b/test/mitmproxy/builtins/test_filestreamer.py @@ -20,16 +20,13 @@ class TestStream(mastertest.MasterTest):                  return list(r.stream())              s = state.State() -            m = master.FlowMaster( -                options.Options( -                    outfile = (p, "wb") -                ), -                None, -                s +            o = options.Options( +                outfile = (p, "wb")              ) +            m = master.FlowMaster(o, None, s)              sa = filestreamer.FileStreamer() -            m.addons.add(sa) +            m.addons.add(o, sa)              f = tutils.tflow(resp=True)              self.invoke(m, "request", f)              self.invoke(m, "response", f) @@ -39,7 +36,7 @@ class TestStream(mastertest.MasterTest):              m.options.outfile = (p, "ab") -            m.addons.add(sa) +            m.addons.add(o, sa)              f = tutils.tflow()              self.invoke(m, "request", f)              m.addons.remove(sa) diff --git a/test/mitmproxy/builtins/test_replace.py b/test/mitmproxy/builtins/test_replace.py index a0b4b722..5e70ce56 100644 --- a/test/mitmproxy/builtins/test_replace.py +++ b/test/mitmproxy/builtins/test_replace.py @@ -8,38 +8,38 @@ from mitmproxy import options  class TestReplace(mastertest.MasterTest):      def test_configure(self):          r = replace.Replace() +        updated = set(["replacements"])          r.configure(options.Options(              replacements=[("one", "two", "three")] -        )) +        ), updated)          tutils.raises(              "invalid filter pattern",              r.configure,              options.Options(                  replacements=[("~b", "two", "three")] -            ) +            ), +            updated          )          tutils.raises(              "invalid regular expression",              r.configure,              options.Options(                  replacements=[("foo", "+", "three")] -            ) +            ), +            updated          )      def test_simple(self):          s = state.State() -        m = master.FlowMaster( -            options.Options( -                replacements = [ -                    ("~q", "foo", "bar"), -                    ("~s", "foo", "bar"), -                ] -            ), -            None, -            s +        o = options.Options( +            replacements = [ +                ("~q", "foo", "bar"), +                ("~s", "foo", "bar"), +            ]          ) +        m = master.FlowMaster(o, None, s)          sa = replace.Replace() -        m.addons.add(sa) +        m.addons.add(o, sa)          f = tutils.tflow()          f.request.content = b"foo" diff --git a/test/mitmproxy/builtins/test_script.py b/test/mitmproxy/builtins/test_script.py index 826d2a91..2870fd17 100644 --- a/test/mitmproxy/builtins/test_script.py +++ b/test/mitmproxy/builtins/test_script.py @@ -54,16 +54,17 @@ def test_load_script():  class TestScript(mastertest.MasterTest):      def test_simple(self):          s = state.State() -        m = master.FlowMaster(options.Options(), None, s) +        o = options.Options() +        m = master.FlowMaster(o, None, s)          sc = script.Script(              tutils.test_data.path(                  "data/addonscripts/recorder.py"              )          ) -        m.addons.add(sc) +        m.addons.add(o, sc)          assert sc.ns.call_log == [              ("solo", "start", (), {}), -            ("solo", "configure", (options.Options(),), {}) +            ("solo", "configure", (o, o.keys()), {})          ]          sc.ns.call_log = [] @@ -75,12 +76,13 @@ class TestScript(mastertest.MasterTest):      def test_reload(self):          s = state.State() -        m = mastertest.RecordingMaster(options.Options(), None, s) +        o = options.Options() +        m = mastertest.RecordingMaster(o, None, s)          with tutils.tmpdir():              with open("foo.py", "w"):                  pass              sc = script.Script("foo.py") -            m.addons.add(sc) +            m.addons.add(o, sc)              for _ in range(100):                  with open("foo.py", "a") as f: @@ -93,19 +95,22 @@ class TestScript(mastertest.MasterTest):      def test_exception(self):          s = state.State() -        m = mastertest.RecordingMaster(options.Options(), None, s) +        o = options.Options() +        m = mastertest.RecordingMaster(o, None, s)          sc = script.Script(              tutils.test_data.path("data/addonscripts/error.py")          ) -        m.addons.add(sc) +        m.addons.add(o, sc)          f = tutils.tflow(resp=True)          self.invoke(m, "request", f)          assert m.event_log[0][0] == "error"      def test_duplicate_flow(self):          s = state.State() -        fm = master.FlowMaster(None, None, s) +        o = options.Options() +        fm = master.FlowMaster(o, None, s)          fm.addons.add( +            o,              script.Script(                  tutils.test_data.path("data/addonscripts/duplicate_flow.py")              ) @@ -118,13 +123,14 @@ class TestScript(mastertest.MasterTest):      def test_addon(self):          s = state.State() -        m = master.FlowMaster(options.Options(), None, s) +        o = options.Options() +        m = master.FlowMaster(o, None, s)          sc = script.Script(              tutils.test_data.path(                  "data/addonscripts/addon.py"              )          ) -        m.addons.add(sc) +        m.addons.add(o, sc)          assert sc.ns.event_log == [              'scriptstart', 'addonstart', 'addonconfigure'          ] @@ -136,7 +142,7 @@ class TestScriptLoader(mastertest.MasterTest):          o = options.Options(scripts=[])          m = master.FlowMaster(o, None, s)          sc = script.ScriptLoader() -        m.addons.add(sc) +        m.addons.add(o, sc)          assert len(m.addons) == 1          o.update(              scripts = [ @@ -152,7 +158,7 @@ class TestScriptLoader(mastertest.MasterTest):          o = options.Options(scripts=["one", "one"])          m = master.FlowMaster(o, None, s)          sc = script.ScriptLoader() -        tutils.raises(exceptions.OptionsError, m.addons.add, sc) +        tutils.raises(exceptions.OptionsError, m.addons.add, o, sc)      def test_order(self):          rec = tutils.test_data.path("data/addonscripts/recorder.py") @@ -167,7 +173,7 @@ class TestScriptLoader(mastertest.MasterTest):          )          m = mastertest.RecordingMaster(o, None, s)          sc = script.ScriptLoader() -        m.addons.add(sc) +        m.addons.add(o, sc)          debug = [(i[0], i[1]) for i in m.event_log if i[0] == "debug"]          assert debug == [ diff --git a/test/mitmproxy/builtins/test_setheaders.py b/test/mitmproxy/builtins/test_setheaders.py index 4465719d..41c18360 100644 --- a/test/mitmproxy/builtins/test_setheaders.py +++ b/test/mitmproxy/builtins/test_setheaders.py @@ -8,19 +8,20 @@ from mitmproxy import options  class TestSetHeaders(mastertest.MasterTest):      def mkmaster(self, **opts):          s = state.State() -        m = mastertest.RecordingMaster(options.Options(**opts), None, s) +        o = options.Options(**opts) +        m = mastertest.RecordingMaster(o, None, s)          sh = setheaders.SetHeaders() -        m.addons.add(sh) +        m.addons.add(o, sh)          return m, sh      def test_configure(self):          sh = setheaders.SetHeaders() +        o = options.Options( +            setheaders = [("~b", "one", "two")] +        )          tutils.raises(              "invalid setheader filter pattern", -            sh.configure, -            options.Options( -                setheaders = [("~b", "one", "two")] -            ) +            sh.configure, o, o.keys()          )      def test_setheaders(self): diff --git a/test/mitmproxy/builtins/test_stickyauth.py b/test/mitmproxy/builtins/test_stickyauth.py index 9233f435..5757fb2d 100644 --- a/test/mitmproxy/builtins/test_stickyauth.py +++ b/test/mitmproxy/builtins/test_stickyauth.py @@ -8,9 +8,10 @@ from mitmproxy import options  class TestStickyAuth(mastertest.MasterTest):      def test_simple(self):          s = state.State() -        m = master.FlowMaster(options.Options(stickyauth = ".*"), None, s) +        o = options.Options(stickyauth = ".*") +        m = master.FlowMaster(o, None, s)          sa = stickyauth.StickyAuth() -        m.addons.add(sa) +        m.addons.add(o, sa)          f = tutils.tflow(resp=True)          f.request.headers["authorization"] = "foo" diff --git a/test/mitmproxy/builtins/test_stickycookie.py b/test/mitmproxy/builtins/test_stickycookie.py index 81b540db..e9d92c83 100644 --- a/test/mitmproxy/builtins/test_stickycookie.py +++ b/test/mitmproxy/builtins/test_stickycookie.py @@ -14,22 +14,23 @@ def test_domain_match():  class TestStickyCookie(mastertest.MasterTest):      def mk(self):          s = state.State() -        m = master.FlowMaster(options.Options(stickycookie = ".*"), None, s) +        o = options.Options(stickycookie = ".*") +        m = master.FlowMaster(o, None, s)          sc = stickycookie.StickyCookie() -        m.addons.add(sc) +        m.addons.add(o, sc)          return s, m, sc      def test_config(self):          sc = stickycookie.StickyCookie() +        o = options.Options(stickycookie = "~b")          tutils.raises(              "invalid filter", -            sc.configure, -            options.Options(stickycookie = "~b") +            sc.configure, o, o.keys()          )      def test_simple(self):          s, m, sc = self.mk() -        m.addons.add(sc) +        m.addons.add(m.options, sc)          f = tutils.tflow(resp=True)          f.response.headers["set-cookie"] = "foo=bar" diff --git a/test/mitmproxy/data/addonscripts/addon.py b/test/mitmproxy/data/addonscripts/addon.py index 3b09d231..84173cb6 100644 --- a/test/mitmproxy/data/addonscripts/addon.py +++ b/test/mitmproxy/data/addonscripts/addon.py @@ -9,11 +9,11 @@ class Addon:      def start(self):          event_log.append("addonstart") -    def configure(self, options): +    def configure(self, options, updated):          event_log.append("addonconfigure") -def configure(options): +def configure(options, updated):      event_log.append("addonconfigure") diff --git a/test/mitmproxy/script/test_concurrent.py b/test/mitmproxy/script/test_concurrent.py index 080746e8..a5f76994 100644 --- a/test/mitmproxy/script/test_concurrent.py +++ b/test/mitmproxy/script/test_concurrent.py @@ -23,7 +23,7 @@ class TestConcurrent(mastertest.MasterTest):                  "data/addonscripts/concurrent_decorator.py"              )          ) -        m.addons.add(sc) +        m.addons.add(m.options, sc)          f1, f2 = tutils.tflow(), tutils.tflow()          self.invoke(m, "request", f1)          self.invoke(m, "request", f2) diff --git a/test/mitmproxy/test_addons.py b/test/mitmproxy/test_addons.py index 1861d4ac..a5085ea0 100644 --- a/test/mitmproxy/test_addons.py +++ b/test/mitmproxy/test_addons.py @@ -13,8 +13,9 @@ class TAddon:  def test_simple(): -    m = controller.Master(options.Options()) +    o = options.Options() +    m = controller.Master(o)      a = addons.Addons(m) -    a.add(TAddon("one")) +    a.add(o, TAddon("one"))      assert a.has_addon("one")      assert not a.has_addon("two") diff --git a/test/mitmproxy/test_examples.py b/test/mitmproxy/test_examples.py index 0ec85f52..34fcc261 100644 --- a/test/mitmproxy/test_examples.py +++ b/test/mitmproxy/test_examples.py @@ -27,10 +27,11 @@ class RaiseMaster(master.FlowMaster):  def tscript(cmd, args=""): +    o = options.Options()      cmd = example_dir.path(cmd) + " " + args -    m = RaiseMaster(options.Options(), None, state.State()) +    m = RaiseMaster(o, None, state.State())      sc = script.Script(cmd) -    m.addons.add(sc) +    m.addons.add(o, sc)      return m, sc diff --git a/test/mitmproxy/test_optmanager.py b/test/mitmproxy/test_optmanager.py index 67f76ecd..8414e6b5 100644 --- a/test/mitmproxy/test_optmanager.py +++ b/test/mitmproxy/test_optmanager.py @@ -15,6 +15,8 @@ class TO(optmanager.OptManager):  def test_options():      o = TO(two="three") +    assert o.keys() == set(["one", "two"]) +      assert o.one is None      assert o.two == "three"      o.one = "one" @@ -29,7 +31,7 @@ def test_options():      rec = [] -    def sub(opts): +    def sub(opts, updated):          rec.append(copy.copy(opts))      o.changed.connect(sub) @@ -68,7 +70,7 @@ def test_rollback():      rec = [] -    def sub(opts): +    def sub(opts, updated):          rec.append(copy.copy(opts))      recerr = [] @@ -76,7 +78,7 @@ def test_rollback():      def errsub(opts, **kwargs):          recerr.append(kwargs) -    def err(opts): +    def err(opts, updated):          if opts.one == "ten":              raise exceptions.OptionsError() diff --git a/test/mitmproxy/test_server.py b/test/mitmproxy/test_server.py index 233af597..6230fc1f 100644 --- a/test/mitmproxy/test_server.py +++ b/test/mitmproxy/test_server.py @@ -291,7 +291,7 @@ class TestHTTP(tservers.HTTPProxyTest, CommonMixin, AppMixin):          s = script.Script(              tutils.test_data.path("data/addonscripts/stream_modify.py")          ) -        self.master.addons.add(s) +        self.master.addons.add(self.master.options, s)          d = self.pathod('200:b"foo"')          assert d.content == b"bar"          self.master.addons.remove(s) @@ -523,7 +523,7 @@ class TestTransparent(tservers.TransparentProxyTest, CommonMixin, TcpMixin):          s = script.Script(              tutils.test_data.path("data/addonscripts/tcp_stream_modify.py")          ) -        self.master.addons.add(s) +        self.master.addons.add(self.master.options, s)          self._tcpproxy_on()          d = self.pathod('200:b"foo"')          self._tcpproxy_off() diff --git a/test/mitmproxy/tservers.py b/test/mitmproxy/tservers.py index f5119166..d364162c 100644 --- a/test/mitmproxy/tservers.py +++ b/test/mitmproxy/tservers.py @@ -34,7 +34,7 @@ class TestMaster(flow.FlowMaster):          s = ProxyServer(config)          state = flow.State()          flow.FlowMaster.__init__(self, opts, s, state) -        self.addons.add(*builtins.default_addons()) +        self.addons.add(opts, *builtins.default_addons())          self.apps.add(testapp, "testapp", 80)          self.apps.add(errapp, "errapp", 80)          self.clear_log() | 
