Add OptManager.subscribe, use it to clean up palettes in console

.subscribe lets you subscribe a function to a specified set of options.
This commit is contained in:
Aldo Cortesi
2016-12-03 11:54:04 +13:00
parent 0c091bd92b
commit c062e302e9
4 changed files with 61 additions and 22 deletions

View File

@@ -3,6 +3,8 @@ import blinker
import pprint
import inspect
import copy
import functools
import weakref
from mitmproxy import exceptions
from mitmproxy.utils import typecheck
@@ -63,6 +65,27 @@ class OptManager:
self.__dict__["_opts"] = old
self.changed.send(self, updated=updated)
def subscribe(self, func, opts):
"""
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.
"""
func = weakref.proxy(func)
@functools.wraps(func)
def _call(options, updated):
if updated.intersection(set(opts)):
try:
func(options, updated)
except ReferenceError:
self.changed.disconnect(_call)
# Our wrapper function goes out of scope immediately, so we have to set
# weakrefs to false. This means we need to keep our own weakref, and
# clean up the hook when it's gone.
self.changed.connect(_call, weak=False)
def __eq__(self, other):
return self._opts == other._opts

View File

@@ -77,9 +77,6 @@ class ConsoleMaster(master.Master):
self.options = self.options # type: Options
self.options.errored.connect(self.options_error)
self.palette = options.palette
self.palette_transparent = options.palette_transparent
self.logbuffer = urwid.SimpleListWalker([])
self.view_stack = []
@@ -253,10 +250,11 @@ class ConsoleMaster(master.Master):
self.ui.start()
os.unlink(name)
def set_palette(self, name):
self.palette = name
def set_palette(self, options, updated):
self.ui.register_palette(
palettes.palettes[name].palette(self.palette_transparent)
palettes.palettes[options.palette].palette(
options.palette_transparent
)
)
self.ui.clear()
@@ -269,7 +267,11 @@ class ConsoleMaster(master.Master):
def run(self):
self.ui = urwid.raw_display.Screen()
self.ui.set_terminal_properties(256)
self.set_palette(self.palette)
self.set_palette(self.options, None)
self.options.subscribe(
self.set_palette,
["palette", "palette_transparent"]
)
self.loop = urwid.MainLoop(
urwid.SolidFill("x"),
screen = self.ui,

View File

@@ -3,7 +3,6 @@ import urwid
from mitmproxy.tools.console import common
from mitmproxy.tools.console import palettes
from mitmproxy.tools.console import select
from mitmproxy.tools.console import signals
footer = [
('heading_key', "enter/space"), ":select",
@@ -43,8 +42,8 @@ class PalettePicker(urwid.WidgetWrap):
return select.Option(
i,
None,
lambda: self.master.palette == name,
lambda: self.select(name)
lambda: self.master.options.palette == name,
lambda: setattr(self.master.options, "palette", name)
)
for i in high:
@@ -59,8 +58,8 @@ class PalettePicker(urwid.WidgetWrap):
select.Option(
"Transparent",
"T",
lambda: master.palette_transparent,
self.toggle_palette_transparent
lambda: master.options.palette_transparent,
master.options.toggler("palette_transparent")
)
]
)
@@ -73,15 +72,7 @@ class PalettePicker(urwid.WidgetWrap):
self.lb,
header = title
)
signals.update_settings.connect(self.sig_update_settings)
master.options.changed.connect(self.sig_options_changed)
def sig_update_settings(self, sender):
def sig_options_changed(self, options, updated):
self.lb.walker._modified()
def select(self, name):
self.master.set_palette(name)
def toggle_palette_transparent(self):
self.master.palette_transparent = not self.master.palette_transparent
self.master.set_palette(self.master.palette)
signals.update_settings.send(self)

View File

@@ -104,6 +104,29 @@ def test_toggler():
o.toggler("nonexistent")
class Rec():
def __init__(self):
self.called = None
def __call__(self, *args, **kwargs):
self.called = (args, kwargs)
def test_subscribe():
o = TO()
r = Rec()
o.subscribe(r, ["two"])
o.one = "foo"
assert not r.called
o.two = "foo"
assert r.called
assert len(o.changed.receivers) == 1
del r
o.two = "bar"
assert len(o.changed.receivers) == 0
def test_rollback():
o = TO(one="two")