diff options
-rw-r--r-- | mitmproxy/optmanager.py | 20 | ||||
-rw-r--r-- | mitmproxy/tools/console/options.py | 17 | ||||
-rw-r--r-- | test/mitmproxy/test_optmanager.py | 37 |
3 files changed, 58 insertions, 16 deletions
diff --git a/mitmproxy/optmanager.py b/mitmproxy/optmanager.py index 20492f82..0421d4be 100644 --- a/mitmproxy/optmanager.py +++ b/mitmproxy/optmanager.py @@ -1,6 +1,7 @@ import contextlib import blinker import pprint +import inspect from mitmproxy import exceptions from mitmproxy.utils import typecheck @@ -12,6 +13,10 @@ from mitmproxy.utils import typecheck class OptManager: """ + OptManager is the base class from which Options objects are derived. + Note that the __init__ method of all child classes must force all + arguments to be positional only, by including a "*" argument. + .changed is a blinker Signal that triggers whenever options are updated. If any handler in the chain raises an exceptions.OptionsError exception, all changes are rolled back, the exception is suppressed, @@ -26,6 +31,15 @@ class OptManager: # ._initialized = True as the final operation. instance = super().__new__(cls) instance.__dict__["_opts"] = {} + + defaults = {} + for klass in reversed(inspect.getmro(cls)): + for p in inspect.signature(klass.__init__).parameters.values(): + if p.kind in (p.KEYWORD_ONLY, p.POSITIONAL_OR_KEYWORD): + if not p.default == p.empty: + defaults[p.name] = p.default + instance.__dict__["_defaults"] = defaults + return instance def __init__(self): @@ -78,6 +92,12 @@ class OptManager: def get(self, k, d=None): return self._opts.get(k, d) + def reset(self): + """ + Restore defaults for all options. + """ + self.update(**self._defaults) + def update(self, **kwargs): updated = set(kwargs.keys()) for k, v in kwargs.items(): diff --git a/mitmproxy/tools/console/options.py b/mitmproxy/tools/console/options.py index 824041dc..9d698161 100644 --- a/mitmproxy/tools/console/options.py +++ b/mitmproxy/tools/console/options.py @@ -160,22 +160,7 @@ class Options(urwid.WidgetWrap): return super().keypress(size, key) def clearall(self): - self.master.options.update( - anticache = False, - anticomp = False, - ignore_hosts = (), - tcp_hosts = (), - replay_kill_extra = False, - no_upstream_cert = False, - refresh_server_playback = True, - replacements = [], - scripts = [], - setheaders = [], - showhost = False, - stickyauth = None, - stickycookie = None, - default_contentview = "auto", - ) + self.master.options.reset() signals.update_settings.send(self) signals.status_message.send( message = "All select.Options cleared", diff --git a/test/mitmproxy/test_optmanager.py b/test/mitmproxy/test_optmanager.py index 3c845707..47e40d98 100644 --- a/test/mitmproxy/test_optmanager.py +++ b/test/mitmproxy/test_optmanager.py @@ -12,6 +12,43 @@ class TO(optmanager.OptManager): super().__init__() +class TD(optmanager.OptManager): + def __init__(self, one="done", two="dtwo", three="error"): + self.one = one + self.two = two + self.three = three + super().__init__() + + +class TD2(TD): + def __init__(self, *, three="dthree", four="dfour", **kwargs): + self.three = three + self.four = four + super().__init__(**kwargs) + + +def test_defaults(): + o = TD2() + assert o._defaults == { + "one": "done", + "two": "dtwo", + "three": "dthree", + "four": "dfour", + } + newvals = dict( + one="xone", + two="xtwo", + three="xthree", + four="xfour", + ) + o.update(**newvals) + for k, v in newvals.items(): + assert v == o.get(k) + o.reset() + for k, v in o._defaults.items(): + assert v == o.get(k) + + def test_options(): o = TO(two="three") assert o.keys() == set(["one", "two"]) |