Add blinker dependency, start using it to refactor console app

Blinker lets us set up a central pub/sub mechanism to disentangle our object
structure.
This commit is contained in:
Aldo Cortesi 2015-03-21 11:19:20 +13:00
parent b475c8d6ea
commit 8725d50d03
9 changed files with 51 additions and 52 deletions

View File

@ -15,7 +15,7 @@ import urwid
import weakref import weakref
from .. import controller, flow, script from .. import controller, flow, script
from . import flowlist, flowview, help, common, window from . import flowlist, flowview, help, common, window, signals
from . import grideditor, palettes, contentview, flowdetailview, statusbar from . import grideditor, palettes, contentview, flowdetailview, statusbar
EVENTLOG_SIZE = 500 EVENTLOG_SIZE = 500
@ -238,7 +238,9 @@ class ConsoleMaster(flow.FlowMaster):
try: try:
s = script.Script(command, self) s = script.Script(command, self)
except script.ScriptError, v: except script.ScriptError, v:
self.statusbar.message("Error loading script.") signals.status_message.send(
message = "Error loading script."
)
self.add_event("Error loading script:\n%s"%v.args[0], "error") self.add_event("Error loading script:\n%s"%v.args[0], "error")
return return
@ -257,7 +259,7 @@ class ConsoleMaster(flow.FlowMaster):
return return
ret = self.load_script(command) ret = self.load_script(command)
if ret: if ret:
self.statusbar.message(ret) signals.status_message.send(message=ret)
self.state.last_script = command self.state.last_script = command
def toggle_eventlog(self): def toggle_eventlog(self):
@ -279,7 +281,7 @@ class ConsoleMaster(flow.FlowMaster):
print >> sys.stderr, e.strerror print >> sys.stderr, e.strerror
sys.exit(1) sys.exit(1)
else: else:
self.statusbar.message(e.strerror) signals.status_message.send(message=e.strerror)
return None return None
def client_playback_path(self, path): def client_playback_path(self, path):
@ -314,7 +316,7 @@ class ConsoleMaster(flow.FlowMaster):
try: try:
subprocess.call(cmd) subprocess.call(cmd)
except: except:
self.statusbar.message("Can't start editor: %s" % " ".join(c)) signals.status_message.send(message="Can't start editor: %s" % " ".join(c))
else: else:
data = open(name, "rb").read() data = open(name, "rb").read()
self.ui.start() self.ui.start()
@ -353,8 +355,8 @@ class ConsoleMaster(flow.FlowMaster):
try: try:
subprocess.call(cmd, shell=shell) subprocess.call(cmd, shell=shell)
except: except:
self.statusbar.message( signals.status_message.send(
"Can't start external viewer: %s" % " ".join(c) message="Can't start external viewer: %s" % " ".join(c)
) )
self.ui.start() self.ui.start()
os.unlink(name) os.unlink(name)
@ -505,7 +507,7 @@ class ConsoleMaster(flow.FlowMaster):
fw.add(i) fw.add(i)
f.close() f.close()
except IOError, v: except IOError, v:
self.statusbar.message(v.strerror) signals.status_message.send(message=v.strerror)
def save_one_flow(self, path, flow): def save_one_flow(self, path, flow):
return self._write_flows(path, [flow]) return self._write_flows(path, [flow])
@ -565,7 +567,7 @@ class ConsoleMaster(flow.FlowMaster):
self.prompting = False self.prompting = False
self.onekey = False self.onekey = False
self.view.set_focus("body") self.view.set_focus("body")
self.statusbar.message("") signals.status_message.send(message="")
def prompt_execute(self, txt=None): def prompt_execute(self, txt=None):
if not txt: if not txt:
@ -574,7 +576,7 @@ class ConsoleMaster(flow.FlowMaster):
self.prompt_done() self.prompt_done()
msg = p(txt, *args) msg = p(txt, *args)
if msg: if msg:
self.statusbar.message(msg, 1000) signals.status_message.send(message=msg, expire=1000)
def prompt_cancel(self): def prompt_cancel(self):
self.prompt_done() self.prompt_done()

View File

@ -6,6 +6,7 @@ import os
from .. import utils from .. import utils
from ..protocol.http import CONTENT_MISSING, decoded from ..protocol.http import CONTENT_MISSING, decoded
from . import signals
try: try:
import pyperclip import pyperclip
@ -198,7 +199,7 @@ def save_data(path, data, master, state):
with file(path, "wb") as f: with file(path, "wb") as f:
f.write(data) f.write(data)
except IOError, v: except IOError, v:
master.statusbar.message(v.strerror) signals.status_message.send(message=v.strerror)
def ask_save_path(prompt, data, master, state): def ask_save_path(prompt, data, master, state):
@ -248,11 +249,11 @@ def copy_flow(part, scope, flow, master, state):
if not data: if not data:
if scope == "q": if scope == "q":
master.statusbar.message("No request content to copy.") signals.status_message.send(message="No request content to copy.")
elif scope == "s": elif scope == "s":
master.statusbar.message("No response content to copy.") signals.status_message.send(message="No response content to copy.")
else: else:
master.statusbar.message("No contents to copy.") signals.status_message.send(message="No contents to copy.")
return return
try: try:
@ -336,7 +337,7 @@ def ask_save_body(part, master, state, flow):
state state
) )
else: else:
master.statusbar.message("No content to save.") signals.status_message.send(message="No content to save.")
class FlowCache: class FlowCache:

View File

@ -1,7 +1,7 @@
from __future__ import absolute_import from __future__ import absolute_import
import urwid import urwid
from netlib import http from netlib import http
from . import common from . import common, signals
def _mkhelp(): def _mkhelp():
@ -171,7 +171,7 @@ class ConnectionItem(urwid.WidgetWrap):
elif key == "r": elif key == "r":
r = self.master.replay_request(self.flow) r = self.master.replay_request(self.flow)
if r: if r:
self.master.statusbar.message(r) signals.status_message.send(message=r)
self.master.sync_list_view() self.master.sync_list_view()
elif key == "S": elif key == "S":
if not self.master.server_playback: if not self.master.server_playback:
@ -195,11 +195,11 @@ class ConnectionItem(urwid.WidgetWrap):
) )
elif key == "V": elif key == "V":
if not self.flow.modified(): if not self.flow.modified():
self.master.statusbar.message("Flow not modified.") signals.status_message.send(message="Flow not modified.")
return return
self.state.revert(self.flow) self.state.revert(self.flow)
self.master.sync_list_view() self.master.sync_list_view()
self.master.statusbar.message("Reverted.") signals.status_message.send(message="Reverted.")
elif key == "w": elif key == "w":
self.master.prompt_onekey( self.master.prompt_onekey(
"Save", "Save",
@ -285,7 +285,7 @@ class FlowListBox(urwid.ListBox):
def new_request(self, url, method): def new_request(self, url, method):
parts = http.parse_url(str(url)) parts = http.parse_url(str(url))
if not parts: if not parts:
self.master.statusbar.message("Invalid Url") signals.status_message.send(message="Invalid Url")
return return
scheme, host, port, path = parts scheme, host, port, path = parts
f = self.master.create_request(method, scheme, host, port, path) f = self.master.create_request(method, scheme, host, port, path)

View File

@ -1,7 +1,7 @@
from __future__ import absolute_import from __future__ import absolute_import
import os, sys, copy import os, sys, copy
import urwid import urwid
from . import common, grideditor, contentview from . import common, grideditor, contentview, signals
from .. import utils, flow, controller from .. import utils, flow, controller
from ..protocol.http import HTTPRequest, HTTPResponse, CONTENT_MISSING, decoded from ..protocol.http import HTTPRequest, HTTPResponse, CONTENT_MISSING, decoded
@ -282,10 +282,10 @@ class FlowView(urwid.WidgetWrap):
if last_search_string: if last_search_string:
message = self.search(last_search_string, backwards) message = self.search(last_search_string, backwards)
if message: if message:
self.master.statusbar.message(message) signals.status_message.send(message=message)
else: else:
message = "no previous searches have been made" message = "no previous searches have been made"
self.master.statusbar.message(message) signals.status_message.send(message=message)
return message return message
@ -606,7 +606,7 @@ class FlowView(urwid.WidgetWrap):
else: else:
new_flow, new_idx = self.state.get_prev(idx) new_flow, new_idx = self.state.get_prev(idx)
if new_flow is None: if new_flow is None:
self.master.statusbar.message("No more flows!") signals.status_message.send(message="No more flows!")
return return
self.master.view_flow(new_flow) self.master.view_flow(new_flow)
@ -681,7 +681,7 @@ class FlowView(urwid.WidgetWrap):
elif key == "D": elif key == "D":
f = self.master.duplicate_flow(self.flow) f = self.master.duplicate_flow(self.flow)
self.master.view_flow(f) self.master.view_flow(f)
self.master.statusbar.message("Duplicated.") signals.status_message.send(message="Duplicated.")
elif key == "e": elif key == "e":
if self.state.view_flow_mode == common.VIEW_FLOW_REQUEST: if self.state.view_flow_mode == common.VIEW_FLOW_REQUEST:
self.master.prompt_onekey( self.master.prompt_onekey(
@ -710,14 +710,14 @@ class FlowView(urwid.WidgetWrap):
) )
key = None key = None
elif key == "f": elif key == "f":
self.master.statusbar.message("Loading all body data...") signals.status_message.send(message="Loading all body data...")
self.state.add_flow_setting( self.state.add_flow_setting(
self.flow, self.flow,
(self.state.view_flow_mode, "fullcontents"), (self.state.view_flow_mode, "fullcontents"),
True True
) )
self.master.refresh_flow(self.flow) self.master.refresh_flow(self.flow)
self.master.statusbar.message("") signals.status_message.send(message="")
elif key == "g": elif key == "g":
if self.state.view_flow_mode == common.VIEW_FLOW_REQUEST: if self.state.view_flow_mode == common.VIEW_FLOW_REQUEST:
scope = "q" scope = "q"
@ -738,15 +738,15 @@ class FlowView(urwid.WidgetWrap):
elif key == "r": elif key == "r":
r = self.master.replay_request(self.flow) r = self.master.replay_request(self.flow)
if r: if r:
self.master.statusbar.message(r) signals.status_message.send(message=r)
self.master.refresh_flow(self.flow) self.master.refresh_flow(self.flow)
elif key == "V": elif key == "V":
if not self.flow.modified(): if not self.flow.modified():
self.master.statusbar.message("Flow not modified.") signals.status_message.send(message="Flow not modified.")
return return
self.state.revert(self.flow) self.state.revert(self.flow)
self.master.refresh_flow(self.flow) self.master.refresh_flow(self.flow)
self.master.statusbar.message("Reverted.") signals.status_message.send(message="Reverted.")
elif key == "W": elif key == "W":
self.master.path_prompt( self.master.path_prompt(
"Save this flow: ", "Save this flow: ",
@ -761,7 +761,7 @@ class FlowView(urwid.WidgetWrap):
if os.environ.has_key("EDITOR") or os.environ.has_key("PAGER"): if os.environ.has_key("EDITOR") or os.environ.has_key("PAGER"):
self.master.spawn_external_viewer(conn.content, t) self.master.spawn_external_viewer(conn.content, t)
else: else:
self.master.statusbar.message("Error! Set $EDITOR or $PAGER.") signals.status_message.send(message="Error! Set $EDITOR or $PAGER.")
elif key == "|": elif key == "|":
self.master.path_prompt( self.master.path_prompt(
"Send flow to script: ", self.state.last_script, "Send flow to script: ", self.state.last_script,
@ -785,7 +785,7 @@ class FlowView(urwid.WidgetWrap):
e = conn.headers.get_first("content-encoding", "identity") e = conn.headers.get_first("content-encoding", "identity")
if e != "identity": if e != "identity":
if not conn.decode(): if not conn.decode():
self.master.statusbar.message("Could not decode - invalid data?") signals.status_message.send(message="Could not decode - invalid data?")
else: else:
self.master.prompt_onekey( self.master.prompt_onekey(
"Select encoding: ", "Select encoding: ",

View File

@ -5,7 +5,7 @@ import re
import os import os
import urwid import urwid
from . import common from . import common, signals
from .. import utils, filt, script from .. import utils, filt, script
from netlib import http_uastrings from netlib import http_uastrings
@ -125,14 +125,14 @@ class GridWalker(urwid.ListWalker):
try: try:
val = val.decode("string-escape") val = val.decode("string-escape")
except ValueError: except ValueError:
self.editor.master.statusbar.message( signals.status_message.send(
"Invalid Python-style string encoding.", 1000 self, message = "Invalid Python-style string encoding.", expure = 1000
) )
return return
errors = self.lst[self.focus][1] errors = self.lst[self.focus][1]
emsg = self.editor.is_error(self.focus_col, val) emsg = self.editor.is_error(self.focus_col, val)
if emsg: if emsg:
self.editor.master.statusbar.message(emsg, 1000) signals.status_message.send(message = emsg, expire = 1000)
errors.add(self.focus_col) errors.add(self.focus_col)
else: else:
errors.discard(self.focus_col) errors.discard(self.focus_col)

View File

@ -0,0 +1,4 @@
import blinker
status_message = blinker.Signal()

View File

@ -3,26 +3,26 @@ import time
import urwid import urwid
from . import pathedit from . import pathedit, signals
from .. import utils from .. import utils
class ActionBar(urwid.WidgetWrap): class ActionBar(urwid.WidgetWrap):
def __init__(self): def __init__(self):
self.message("") urwid.WidgetWrap.__init__(self, urwid.Text(""))
signals.status_message.connect(self.message)
def selectable(self): def selectable(self):
return True return True
def path_prompt(self, prompt, text): def path_prompt(self, prompt, text):
self.expire = None
self._w = pathedit.PathEdit(prompt, text) self._w = pathedit.PathEdit(prompt, text)
def prompt(self, prompt, text = ""): def prompt(self, prompt, text = ""):
self.expire = None
self._w = urwid.Edit(prompt, text or "") self._w = urwid.Edit(prompt, text or "")
def message(self, message, expire=None): def message(self, sender, message, expire=None):
self.expire = expire self.expire = expire
self._w = urwid.Text(message) self._w = urwid.Text(message)
@ -127,9 +127,6 @@ class StatusBar(urwid.WidgetWrap):
return r return r
def redraw(self): def redraw(self):
if self.ab.expire and time.time() > self.ab.expire:
self.message("")
fc = self.master.state.flow_count() fc = self.master.state.flow_count()
if self.master.state.focus is None: if self.master.state.focus is None:
offset = 0 offset = 0
@ -175,9 +172,3 @@ class StatusBar(urwid.WidgetWrap):
def prompt(self, prompt, text = ""): def prompt(self, prompt, text = ""):
self.ab.prompt(prompt, text) self.ab.prompt(prompt, text)
def message(self, msg, expire=None):
if expire:
expire = time.time() + float(expire)/1000
self.ab.message(msg, expire)
self.master.loop.draw_screen()

View File

@ -1,5 +1,5 @@
import urwid import urwid
from . import common from . import common, grideditor
class Window(urwid.Frame): class Window(urwid.Frame):
def __init__(self, master, body, header, footer): def __init__(self, master, body, header, footer):

View File

@ -21,7 +21,8 @@ deps = {
"pyOpenSSL>=0.14", "pyOpenSSL>=0.14",
"tornado>=4.0.2", "tornado>=4.0.2",
"configargparse>=0.9.3", "configargparse>=0.9.3",
"pyperclip>=1.5.8" "pyperclip>=1.5.8",
"blinker>=1.3"
} }
script_deps = { script_deps = {
"mitmproxy": { "mitmproxy": {