diff options
author | Aldo Cortesi <aldo@corte.si> | 2017-03-18 12:11:48 +1300 |
---|---|---|
committer | Aldo Cortesi <aldo@corte.si> | 2017-03-19 10:32:22 +1300 |
commit | 4e24c95a61802fd6fb9a03fdffd0380d90c46e0c (patch) | |
tree | b9a03918f7be0f373ae291a51bb9a451f3bc5aa1 | |
parent | 3f50d5fdbbd4c09a9b2f511f6e776930576b9633 (diff) | |
download | mitmproxy-4e24c95a61802fd6fb9a03fdffd0380d90c46e0c.tar.gz mitmproxy-4e24c95a61802fd6fb9a03fdffd0380d90c46e0c.tar.bz2 mitmproxy-4e24c95a61802fd6fb9a03fdffd0380d90c46e0c.zip |
optmanager: cope with bound methods in .subscribe
Fixes #2122
-rw-r--r-- | mitmproxy/optmanager.py | 19 | ||||
-rw-r--r-- | mitmproxy/tools/console/master.py | 2 | ||||
-rw-r--r-- | test/mitmproxy/test_optmanager.py | 15 |
3 files changed, 30 insertions, 6 deletions
diff --git a/mitmproxy/optmanager.py b/mitmproxy/optmanager.py index 77990306..f1d6461d 100644 --- a/mitmproxy/optmanager.py +++ b/mitmproxy/optmanager.py @@ -1,9 +1,9 @@ import contextlib import blinker +import blinker._saferef import pprint import copy import functools -import weakref import os import typing import textwrap @@ -127,15 +127,24 @@ class OptManager: Subscribe a callable to the .changed signal, but only for a specified list of options. The callable should accept arguments (options, updated), and may raise an OptionsError. + + The event will automatically be unsubscribed if the callable goes out of scope. """ - func = weakref.proxy(func) + for i in opts: + if i not in self._options: + raise exceptions.OptionsError("No such option: %s" % i) + + # We reuse blinker's safe reference functionality to cope with weakrefs + # to bound methods. + func = blinker._saferef.safe_ref(func) @functools.wraps(func) def _call(options, updated): if updated.intersection(set(opts)): - try: - func(options, updated) - except ReferenceError: + f = func() + if f: + f(options, updated) + else: self.changed.disconnect(_call) # Our wrapper function goes out of scope immediately, so we have to set diff --git a/mitmproxy/tools/console/master.py b/mitmproxy/tools/console/master.py index 5d481eeb..a6885733 100644 --- a/mitmproxy/tools/console/master.py +++ b/mitmproxy/tools/console/master.py @@ -276,7 +276,7 @@ class ConsoleMaster(master.Master): self.set_palette(self.options, None) self.options.subscribe( self.set_palette, - ["palette", "palette_transparent"] + ["console_palette", "console_palette_transparent"] ) self.loop = urwid.MainLoop( urwid.SolidFill("x"), diff --git a/test/mitmproxy/test_optmanager.py b/test/mitmproxy/test_optmanager.py index 84e574f5..6f87ac06 100644 --- a/test/mitmproxy/test_optmanager.py +++ b/test/mitmproxy/test_optmanager.py @@ -151,6 +151,21 @@ def test_subscribe(): o.two = 4 assert len(o.changed.receivers) == 0 + class binder: + def __init__(self): + self.o = TO() + self.called = False + self.o.subscribe(self.bound, ["two"]) + + def bound(self, *args, **kwargs): + self.called = True + + t = binder() + t.o.one = 3 + assert not t.called + t.o.two = 3 + assert t.called + def test_rollback(): o = TO() |