commands: options control

Use the new commands to bind the Options view in console.
This commit is contained in:
Aldo Cortesi 2017-05-02 11:49:46 +12:00
parent 9e58c36639
commit 4e39d387d3
5 changed files with 102 additions and 34 deletions

View File

@ -4,6 +4,7 @@ from mitmproxy import ctx
from mitmproxy import exceptions
from mitmproxy import command
from mitmproxy import flow
from mitmproxy import optmanager
from mitmproxy.net.http import status_codes
@ -212,3 +213,47 @@ class Core:
"""
return ["gzip", "deflate", "br"]
@command.command("options.load")
def options_load(self, path: str) -> None:
"""
Load options from a file.
"""
try:
optmanager.load_paths(ctx.options, path)
except (OSError, exceptions.OptionsError) as e:
raise exceptions.CommandError(
"Could not load options - %s" % e
) from e
@command.command("options.save")
def options_save(self, path: str) -> None:
"""
Save options to a file.
"""
try:
optmanager.save(ctx.options, path)
except OSError as e:
raise exceptions.CommandError(
"Could not save options - %s" % e
) from e
@command.command("options.reset")
def options_reset(self) -> None:
"""
Reset all options to defaults.
"""
ctx.options.reset()
@command.command("options.reset.one")
def options_reset_one(self, name: str) -> None:
"""
Reset one option to its default value.
"""
if name not in ctx.options:
raise exceptions.CommandError("No such option: %s" % name)
setattr(
ctx.options,
name,
ctx.options.default(name),
)

View File

@ -83,6 +83,16 @@ class ConsoleAddon:
self.master = master
self.started = False
@command.command("console.options.reset.current")
def options_reset_current(self) -> None:
"""
Reset the current option in the options editor.
"""
if self.master.window.focus.keyctx != "options":
raise exceptions.CommandError("Not viewing options.")
name = self.master.window.windows["options"].current_name()
self.master.commands.call("options.reset.one %s" % name)
@command.command("console.nav.start")
def nav_start(self) -> None:
"""
@ -434,6 +444,11 @@ def default_keymap(km):
["flowview"]
)
km.add("L", "console.command options.load ", ["options"])
km.add("S", "console.command options.save ", ["options"])
km.add("D", "options.reset", ["options"])
km.add("d", "console.options.reset.current", ["options"])
class ConsoleMaster(master.Master):

View File

@ -187,12 +187,6 @@ class OptionsList(urwid.ListBox):
except exceptions.OptionsError as e:
signals.status_message.send(message=str(e))
def load_config(self, path):
try:
optmanager.load_paths(self.master.options, path)
except exceptions.OptionsError as e:
signals.status_message.send(message=str(e))
def keypress(self, size, key):
if self.walker.editing:
if key == "enter":
@ -207,29 +201,12 @@ class OptionsList(urwid.ListBox):
elif key == "esc":
self.walker.stop_editing()
else:
if key == "d":
foc, idx = self.get_focus()
setattr(
self.master.options,
foc.opt.name,
self.master.options.default(foc.opt.name)
)
elif key == "m_start":
if key == "m_start":
self.set_focus(0)
self.walker._modified()
elif key == "m_end":
self.set_focus(len(self.walker.opts) - 1)
self.walker._modified()
elif key == "l":
signals.status_prompt_path.send(
prompt = "Load config from",
callback = self.load_config
)
elif key == "w":
signals.status_prompt_path.send(
prompt = "Save config to",
callback = self.save_config
)
elif key == "enter":
foc, idx = self.get_focus()
if foc.opt.typespec == bool:
@ -290,14 +267,19 @@ class Options(urwid.Pile):
def __init__(self, master):
oh = OptionHelp(master)
self.optionslist = OptionsList(master)
super().__init__(
[
OptionsList(master),
self.optionslist,
(HELP_HEIGHT, oh),
]
)
self.master = master
def current_name(self):
foc, idx = self.optionslist.get_focus()
return foc.opt.name
def keypress(self, size, key):
if key == "tab":
self.focus_position = (
@ -305,9 +287,6 @@ class Options(urwid.Pile):
) % len(self.widget_list)
self.widget_list[1].set_active(self.focus_position == 1)
key = None
elif key == "D":
self.master.options.reset()
key = None
# This is essentially a copypasta from urwid.Pile's keypress handler.
# So much for "closed for modification, but open for extension".

View File

@ -128,3 +128,38 @@ def test_encoding():
with pytest.raises(exceptions.CommandError):
sa.encode([f], "request", "invalid")
def test_options(tmpdir):
p = str(tmpdir.join("path"))
sa = core.Core()
with taddons.context() as tctx:
tctx.options.stickycookie = "foo"
assert tctx.options.stickycookie == "foo"
sa.options_reset()
assert tctx.options.stickycookie is None
tctx.options.stickycookie = "foo"
tctx.options.stickyauth = "bar"
sa.options_reset_one("stickycookie")
assert tctx.options.stickycookie is None
assert tctx.options.stickyauth == "bar"
with pytest.raises(exceptions.CommandError):
sa.options_reset_one("unknown")
sa.options_save(p)
with pytest.raises(exceptions.CommandError):
sa.options_save("/nonexistent")
sa.options_reset()
assert tctx.options.stickyauth is None
sa.options_load(p)
assert tctx.options.stickyauth == "bar"
sa.options_load("/nonexistent")
with open(p, 'a') as f:
f.write("'''")
with pytest.raises(exceptions.CommandError):
sa.options_load(p)

View File

@ -9,9 +9,3 @@ class TestHelp:
def test_helptext(self):
h = help.HelpView(None)
assert h.helptext()
def test_keypress(self):
h = help.HelpView([1, 2, 3])
assert not h.keypress((0, 0), "q")
assert not h.keypress((0, 0), "?")
assert h.keypress((0, 0), "o") == "o"