Merge pull request #1823 from cortesi/options2

options: add a merge method to assimilate options
This commit is contained in:
Aldo Cortesi 2016-12-08 19:23:02 +13:00 committed by GitHub
commit 6792cc1de9
7 changed files with 54 additions and 29 deletions

View File

@ -32,7 +32,7 @@ def parse_command(command):
Returns a (path, args) tuple. Returns a (path, args) tuple.
""" """
if not command or not command.strip(): if not command or not command.strip():
raise exceptions.AddonError("Empty script command.") raise exceptions.OptionsError("Empty script command.")
# Windows: escape all backslashes in the path. # Windows: escape all backslashes in the path.
if os.name == "nt": # pragma: no cover if os.name == "nt": # pragma: no cover
backslashes = shlex.split(command, posix=False)[0].count("\\") backslashes = shlex.split(command, posix=False)[0].count("\\")
@ -40,13 +40,13 @@ def parse_command(command):
args = shlex.split(command) # pragma: no cover args = shlex.split(command) # pragma: no cover
args[0] = os.path.expanduser(args[0]) args[0] = os.path.expanduser(args[0])
if not os.path.exists(args[0]): if not os.path.exists(args[0]):
raise exceptions.AddonError( raise exceptions.OptionsError(
("Script file not found: %s.\r\n" ("Script file not found: %s.\r\n"
"If your script path contains spaces, " "If your script path contains spaces, "
"make sure to wrap it in additional quotes, e.g. -s \"'./foo bar/baz.py' --args\".") % "make sure to wrap it in additional quotes, e.g. -s \"'./foo bar/baz.py' --args\".") %
args[0]) args[0])
elif os.path.isdir(args[0]): elif os.path.isdir(args[0]):
raise exceptions.AddonError("Not a file: %s" % args[0]) raise exceptions.OptionsError("Not a file: %s" % args[0])
return args[0], args[1:] return args[0], args[1:]

View File

@ -244,6 +244,21 @@ class OptManager(metaclass=_DefaultsMeta):
txt = f.read() txt = f.read()
self.load(txt) self.load(txt)
def merge(self, opts):
"""
Merge a dict of options into this object. Options that have None
value are ignored. Lists and tuples are appended to the current
option value.
"""
toset = {}
for k, v in opts.items():
if v is not None:
if isinstance(v, (list, tuple)):
toset[k] = getattr(self, k) + v
else:
toset[k] = v
self.update(**toset)
def __repr__(self): def __repr__(self):
options = pprint.pformat(self._opts, indent=4).strip(" {}") options = pprint.pformat(self._opts, indent=4).strip(" {}")
if "\n" in options: if "\n" in options:

View File

@ -164,7 +164,7 @@ class ScriptEditor(base.GridEditor):
def is_error(self, col, val): def is_error(self, col, val):
try: try:
script.parse_command(val) script.parse_command(val)
except exceptions.AddonError as e: except exceptions.OptionsError as e:
return str(e) return str(e)

View File

@ -18,14 +18,6 @@ from mitmproxy.utils import version_check # noqa
from mitmproxy.utils import debug # noqa from mitmproxy.utils import debug # noqa
def notnone(d):
ret = {}
for k, v in d.items():
if v is not None:
ret[k] = v
return ret
def assert_utf8_env(): def assert_utf8_env():
spec = "" spec = ""
for i in ["LANG", "LC_CTYPE", "LC_ALL"]: for i in ["LANG", "LC_CTYPE", "LC_ALL"]:
@ -74,9 +66,9 @@ def mitmproxy(args=None): # pragma: no cover
try: try:
console_options = options.Options() console_options = options.Options()
console_options.load_paths(args.conf) console_options.load_paths(args.conf)
console_options.update(**notnone(cmdline.get_common_options(args))) console_options.merge(cmdline.get_common_options(args))
console_options.update( console_options.merge(
**notnone(dict( dict(
palette = args.palette, palette = args.palette,
palette_transparent = args.palette_transparent, palette_transparent = args.palette_transparent,
eventlog = args.eventlog, eventlog = args.eventlog,
@ -85,7 +77,7 @@ def mitmproxy(args=None): # pragma: no cover
filter = args.filter, filter = args.filter,
no_mouse = args.no_mouse, no_mouse = args.no_mouse,
order = args.order, order = args.order,
)) )
) )
server = process_options(parser, console_options, args) server = process_options(parser, console_options, args)
@ -113,13 +105,13 @@ def mitmdump(args=None): # pragma: no cover
try: try:
dump_options = options.Options() dump_options = options.Options()
dump_options.load_paths(args.conf) dump_options.load_paths(args.conf)
dump_options.update(**notnone(cmdline.get_common_options(args))) dump_options.merge(cmdline.get_common_options(args))
dump_options.update( dump_options.merge(
**notnone(dict( dict(
flow_detail = args.flow_detail, flow_detail = args.flow_detail,
keepserving = args.keepserving, keepserving = args.keepserving,
filtstr = " ".join(args.filter) if args.filter else None, filtstr = " ".join(args.filter) if args.filter else None,
)) )
) )
server = process_options(parser, dump_options, args) server = process_options(parser, dump_options, args)
@ -152,15 +144,15 @@ def mitmweb(args=None): # pragma: no cover
try: try:
web_options = options.Options() web_options = options.Options()
web_options.load_paths(args.conf) web_options.load_paths(args.conf)
web_options.update(**notnone(cmdline.get_common_options(args))) web_options.merge(cmdline.get_common_options(args))
web_options.update( web_options.merge(
**notnone(dict( dict(
intercept = args.intercept, intercept = args.intercept,
open_browser = args.open_browser, open_browser = args.open_browser,
wdebug = args.wdebug, wdebug = args.wdebug,
wiface = args.wiface, wiface = args.wiface,
wport = args.wport, wport = args.wport,
)) )
) )
server = process_options(parser, web_options, args) server = process_options(parser, web_options, args)
m = web.master.WebMaster(web_options, server) m = web.master.WebMaster(web_options, server)

View File

@ -64,10 +64,10 @@ def test_reloadhandler():
class TestParseCommand: class TestParseCommand:
def test_empty_command(self): def test_empty_command(self):
with tutils.raises(exceptions.AddonError): with tutils.raises(exceptions.OptionsError):
script.parse_command("") script.parse_command("")
with tutils.raises(exceptions.AddonError): with tutils.raises(exceptions.OptionsError):
script.parse_command(" ") script.parse_command(" ")
def test_no_script_file(self): def test_no_script_file(self):

View File

@ -220,3 +220,21 @@ def test_saving():
o.load_paths(dst) o.load_paths(dst)
assert o.three == "foo" assert o.three == "foo"
class TM(optmanager.OptManager):
def __init__(self, one="one", two=["foo"], three=None):
self.one = one
self.two = two
self.three = three
super().__init__()
def test_merge():
m = TM()
m.merge(dict(one="two"))
assert m.one == "two"
m.merge(dict(one=None))
assert m.one == "two"
m.merge(dict(two=["bar"]))
assert m.two == ["foo", "bar"]

View File

@ -5,7 +5,6 @@ import argparse
from OpenSSL import SSL from OpenSSL import SSL
from mitmproxy.tools import cmdline from mitmproxy.tools import cmdline
from mitmproxy.tools import main
from mitmproxy import options from mitmproxy import options
from mitmproxy.proxy import ProxyConfig from mitmproxy.proxy import ProxyConfig
from mitmproxy import connections from mitmproxy import connections
@ -76,8 +75,9 @@ class TestProcessProxyOptions:
parser = MockParser() parser = MockParser()
cmdline.common_options(parser) cmdline.common_options(parser)
args = parser.parse_args(args=args) args = parser.parse_args(args=args)
opts = cmdline.get_common_options(args) opts = options.Options()
pconf = config.ProxyConfig(options.Options(**main.notnone(opts))) opts.merge(cmdline.get_common_options(args))
pconf = config.ProxyConfig(opts)
return parser, pconf return parser, pconf
def assert_err(self, err, *args): def assert_err(self, err, *args):