aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2017-12-14 17:49:53 +1300
committerAldo Cortesi <aldo@corte.si>2017-12-15 10:07:47 +1300
commit0cd4a7726892ecda494d94bd12af0094c53a6a85 (patch)
tree503cb348e029a1ad9d8888de0139e20551b75496
parente64d5c6bb963dedf291ed3c694ef735c8980a019 (diff)
downloadmitmproxy-0cd4a7726892ecda494d94bd12af0094c53a6a85.tar.gz
mitmproxy-0cd4a7726892ecda494d94bd12af0094c53a6a85.tar.bz2
mitmproxy-0cd4a7726892ecda494d94bd12af0094c53a6a85.zip
commands: add a parser for partial commands
We only return Cmd and str types for the moment.
-rw-r--r--mitmproxy/command.py25
-rw-r--r--test/mitmproxy/test_command.py10
2 files changed, 35 insertions, 0 deletions
diff --git a/mitmproxy/command.py b/mitmproxy/command.py
index a638b7ee..f73eeb68 100644
--- a/mitmproxy/command.py
+++ b/mitmproxy/command.py
@@ -3,6 +3,7 @@
"""
import inspect
import types
+import io
import typing
import shlex
import textwrap
@@ -137,6 +138,30 @@ class CommandManager:
def add(self, path: str, func: typing.Callable):
self.commands[path] = Command(self, path, func)
+ def parse_partial(self, cmdstr: str) -> typing.Sequence[typing.Tuple[str, type]]:
+ """
+ Parse a possibly partial command. Return a sequence of (part, type) tuples.
+ """
+ parts: typing.List[typing.Tuple[str, type]] = []
+ buf = io.StringIO(cmdstr)
+ # mypy mis-identifies shlex.shlex as abstract
+ lex = shlex.shlex(buf) # type: ignore
+ while 1:
+ remainder = cmdstr[buf.tell():]
+ try:
+ t = lex.get_token()
+ except ValueError:
+ parts.append((remainder, str))
+ break
+ if not t:
+ break
+ typ: type = str
+ # First value is a special case: it has to be a command
+ if not parts:
+ typ = Cmd
+ parts.append((t, typ))
+ return parts
+
def call_args(self, path, args):
"""
Call a command using a list of string arguments. May raise CommandError.
diff --git a/test/mitmproxy/test_command.py b/test/mitmproxy/test_command.py
index c8007463..5218042c 100644
--- a/test/mitmproxy/test_command.py
+++ b/test/mitmproxy/test_command.py
@@ -64,6 +64,16 @@ class TestCommand:
c = command.Command(cm, "cmd.three", a.cmd3)
assert c.call(["1"]) == 1
+ def test_parse_partial(self):
+ tests = [
+ ["foo bar", [("foo", command.Cmd), ("bar", str)]],
+ ["foo 'bar", [("foo", command.Cmd), ("'bar", str)]],
+ ]
+ with taddons.context() as tctx:
+ cm = command.CommandManager(tctx.master)
+ for s, expected in tests:
+ assert cm.parse_partial(s) == expected
+
def test_simple():
with taddons.context() as tctx: