diff --git a/README b/README index ee26d13bb..e25754ce8 100644 --- a/README +++ b/README @@ -36,8 +36,8 @@ Requirements * A recent [Python](http://www.python.org) interpreter. * SSL certificates are generated using [openssl](http://www.openssl.org/) -* The curses interface relies on a current version of the -[urwid](http://excess.org/urwid/) library. +* The curses interface relies on version 0.9.8 or newer of the + [urwid](http://excess.org/urwid/) library. * The test suite uses the [pry](http://github.com/cortesi/pry) unit testing library. diff --git a/libmproxy/console.py b/libmproxy/console.py index 4740ee6b9..475d9be24 100644 --- a/libmproxy/console.py +++ b/libmproxy/console.py @@ -43,6 +43,26 @@ def format_keyvals(lst, key="key", val="text", space=5, indent=0): #begin nocover +def int_version(v): + SIG = 3 + v = urwid.__version__.split(".") + x = 0 + for i in range(min(SIG, len(v))): + x += int(v[i]) * 10**(SIG-i) + return x + + +# We have to do this to be portable over 0.9.8 and 0.9.9 If compatibility +# becomes a pain to maintain, we'll just mandate 0.9.9 or newer. +class WWrap(urwid.WidgetWrap): + if int_version(urwid.__version__) >= 990: + def set_w(self, x): + self._w = x + def get_w(self): + return self._w + w = property(get_w, set_w) + + class ReplayThread(threading.Thread): def __init__(self, flow, masterq): self.flow, self.masterq = flow, masterq @@ -58,15 +78,15 @@ class ReplayThread(threading.Thread): err.send(self.masterq) -class ConnectionItem(urwid.WidgetWrap): +class ConnectionItem(WWrap): def __init__(self, master, state, flow): self.master, self.state, self.flow = master, state, flow w = self.get_text() - urwid.WidgetWrap.__init__(self, w) + WWrap.__init__(self, w) def intercept(self): self.intercepting = True - self._w = self.get_text() + self.w = self.get_text() def get_text(self, nofocus=False): return urwid.Text(self.flow.get_text(nofocus)) @@ -123,17 +143,17 @@ class ConnectionListView(urwid.ListWalker): return f, i -class ConnectionViewHeader(urwid.WidgetWrap): +class ConnectionViewHeader(WWrap): def __init__(self, flow): self.flow = flow - self._w = urwid.Text(flow.get_text(nofocus=True, padding=0)) + self.w = urwid.Text(flow.get_text(nofocus=True, padding=0)) def refresh_connection(self, f): if f == self.flow: - self._w = urwid.Text(f.get_text(nofocus=True, padding=0)) + self.w = urwid.Text(f.get_text(nofocus=True, padding=0)) -class ConnectionView(urwid.WidgetWrap): +class ConnectionView(WWrap): REQ = 0 RESP = 1 tabs = ["Request", "Response"] @@ -224,13 +244,13 @@ class ConnectionView(urwid.WidgetWrap): def view_request(self): self.viewing = self.REQ body = self._conn_text(self.flow.request) - self._w = self.wrap_body(self.REQ, body) + self.w = self.wrap_body(self.REQ, body) def view_response(self): if self.flow.response: self.viewing = self.RESP body = self._conn_text(self.flow.response) - self._w = self.wrap_body(self.RESP, body) + self.w = self.wrap_body(self.RESP, body) def refresh_connection(self, c=None): if c == self.flow: @@ -317,7 +337,7 @@ class ConnectionView(urwid.WidgetWrap): self.view_request() elif key in ("up", "down", "page up", "page down"): # Why doesn't this just work?? - self._w.body.keypress(size, key) + self.w.body.keypress(size, key) elif key == "a": self.flow.accept_intercept() self.master.view_connection(self.flow) @@ -397,7 +417,7 @@ class ConnectionView(urwid.WidgetWrap): return key -class ActionBar(urwid.WidgetWrap): +class ActionBar(WWrap): def __init__(self): self.message("") @@ -405,18 +425,18 @@ class ActionBar(urwid.WidgetWrap): return True def prompt(self, prompt): - self._w = urwid.Edit(prompt) + self.w = urwid.Edit(prompt) def message(self, message): - self._w = urwid.Text(message) + self.w = urwid.Text(message) -class StatusBar(urwid.WidgetWrap): +class StatusBar(WWrap): def __init__(self, master, text): self.master, self.text = master, text self.ab = ActionBar() self.ib = urwid.AttrWrap(urwid.Text(""), 'foot') - self._w = urwid.Pile([self.ib, self.ab]) + self.w = urwid.Pile([self.ib, self.ab]) self.redraw() def redraw(self): @@ -439,7 +459,7 @@ class StatusBar(urwid.WidgetWrap): return True def get_edit_text(self): - return self.ab._w.get_edit_text() + return self.ab.w.get_edit_text() def prompt(self, prompt): self.ab.prompt(prompt)