mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2025-02-02 00:05:27 +00:00
commands: partial parser now returns help for remaining arguments
This commit is contained in:
parent
843bad187c
commit
d98fc4f03a
@ -133,9 +133,12 @@ class CommandManager(mitmproxy.types._CommandBase):
|
||||
def add(self, path: str, func: typing.Callable):
|
||||
self.commands[path] = Command(self, path, func)
|
||||
|
||||
def parse_partial(self, cmdstr: str) -> typing.Sequence[ParseResult]:
|
||||
def parse_partial(
|
||||
self,
|
||||
cmdstr: str
|
||||
) -> typing.Tuple[typing.Sequence[ParseResult], typing.Sequence[str]]:
|
||||
"""
|
||||
Parse a possibly partial command. Return a sequence of (part, type) tuples.
|
||||
Parse a possibly partial command. Return a sequence of ParseResults and a sequence of remainder type help items.
|
||||
"""
|
||||
buf = io.StringIO(cmdstr)
|
||||
parts = [] # type: typing.List[str]
|
||||
@ -188,7 +191,16 @@ class CommandManager(mitmproxy.types._CommandBase):
|
||||
valid=valid,
|
||||
)
|
||||
)
|
||||
return parse
|
||||
|
||||
remhelp = []
|
||||
for x in params:
|
||||
remt = mitmproxy.types.CommandTypes.get(x, None)
|
||||
if not x:
|
||||
remhelp = []
|
||||
break
|
||||
remhelp.append(remt.display)
|
||||
|
||||
return parse, remhelp
|
||||
|
||||
def call_args(self, path: str, args: typing.Sequence[str]) -> typing.Any:
|
||||
"""
|
||||
|
@ -79,7 +79,7 @@ class CommandBuffer():
|
||||
|
||||
def cycle_completion(self) -> None:
|
||||
if not self.completion:
|
||||
parts = self.master.commands.parse_partial(self.buf[:self.cursor])
|
||||
parts, remainhelp = self.master.commands.parse_partial(self.buf[:self.cursor])
|
||||
last = parts[-1]
|
||||
ct = mitmproxy.types.CommandTypes.get(last.type, None)
|
||||
if ct:
|
||||
|
@ -174,6 +174,8 @@ class _CmdType(_BaseType):
|
||||
return list(manager.commands.keys())
|
||||
|
||||
def parse(self, manager: _CommandBase, t: type, s: str) -> str:
|
||||
if s not in manager.commands:
|
||||
raise exceptions.TypeError("Unknown command: %s" % s)
|
||||
return s
|
||||
|
||||
def is_valid(self, manager: _CommandBase, typ: typing.Any, val: typing.Any) -> bool:
|
||||
|
@ -78,39 +78,54 @@ class TestCommand:
|
||||
[
|
||||
"foo bar",
|
||||
[
|
||||
command.ParseResult(value = "foo", type = mitmproxy.types.Cmd, valid = True),
|
||||
command.ParseResult(value = "foo", type = mitmproxy.types.Cmd, valid = False),
|
||||
command.ParseResult(value = "bar", type = str, valid = True)
|
||||
],
|
||||
[],
|
||||
],
|
||||
[
|
||||
"foo 'bar",
|
||||
"cmd1 'bar",
|
||||
[
|
||||
command.ParseResult(value = "foo", type = mitmproxy.types.Cmd, valid = True),
|
||||
command.ParseResult(value = "cmd1", type = mitmproxy.types.Cmd, valid = True),
|
||||
command.ParseResult(value = "'bar", type = str, valid = True)
|
||||
]
|
||||
],
|
||||
[],
|
||||
],
|
||||
[
|
||||
"a",
|
||||
[command.ParseResult(value = "a", type = mitmproxy.types.Cmd, valid = False)],
|
||||
[],
|
||||
],
|
||||
[
|
||||
"",
|
||||
[command.ParseResult(value = "", type = mitmproxy.types.Cmd, valid = False)],
|
||||
[]
|
||||
],
|
||||
["a", [command.ParseResult(value = "a", type = mitmproxy.types.Cmd, valid = True)]],
|
||||
["", [command.ParseResult(value = "", type = mitmproxy.types.Cmd, valid = True)]],
|
||||
[
|
||||
"cmd3 1",
|
||||
[
|
||||
command.ParseResult(value = "cmd3", type = mitmproxy.types.Cmd, valid = True),
|
||||
command.ParseResult(value = "1", type = int, valid = True),
|
||||
]
|
||||
],
|
||||
[]
|
||||
],
|
||||
[
|
||||
"cmd3 ",
|
||||
[
|
||||
command.ParseResult(value = "cmd3", type = mitmproxy.types.Cmd, valid = True),
|
||||
command.ParseResult(value = "", type = int, valid = False),
|
||||
]
|
||||
],
|
||||
[]
|
||||
],
|
||||
[
|
||||
"subcommand ",
|
||||
[
|
||||
command.ParseResult(value = "subcommand", type = mitmproxy.types.Cmd, valid = True),
|
||||
command.ParseResult(value = "", type = mitmproxy.types.Cmd, valid = True),
|
||||
]
|
||||
command.ParseResult(
|
||||
value = "subcommand", type = mitmproxy.types.Cmd, valid = True,
|
||||
),
|
||||
command.ParseResult(value = "", type = mitmproxy.types.Cmd, valid = False),
|
||||
],
|
||||
["arg"],
|
||||
],
|
||||
[
|
||||
"subcommand cmd3 ",
|
||||
@ -118,13 +133,16 @@ class TestCommand:
|
||||
command.ParseResult(value = "subcommand", type = mitmproxy.types.Cmd, valid = True),
|
||||
command.ParseResult(value = "cmd3", type = mitmproxy.types.Cmd, valid = True),
|
||||
command.ParseResult(value = "", type = int, valid = False),
|
||||
]
|
||||
],
|
||||
[]
|
||||
],
|
||||
]
|
||||
with taddons.context() as tctx:
|
||||
tctx.master.addons.add(TAddon())
|
||||
for s, expected in tests:
|
||||
assert tctx.master.commands.parse_partial(s) == expected
|
||||
for s, expected, expectedremain in tests:
|
||||
current, remain = tctx.master.commands.parse_partial(s)
|
||||
assert current == expected
|
||||
assert expectedremain == remain
|
||||
|
||||
|
||||
def test_simple():
|
||||
@ -179,51 +197,11 @@ def test_parsearg():
|
||||
with taddons.context() as tctx:
|
||||
tctx.master.addons.add(DummyConsole())
|
||||
assert command.parsearg(tctx.master.commands, "foo", str) == "foo"
|
||||
|
||||
assert command.parsearg(tctx.master.commands, "1", int) == 1
|
||||
with pytest.raises(exceptions.CommandError, match="Unsupported"):
|
||||
command.parsearg(tctx.master.commands, "foo", type)
|
||||
with pytest.raises(exceptions.CommandError):
|
||||
command.parsearg(tctx.master.commands, "foo", int)
|
||||
|
||||
assert command.parsearg(tctx.master.commands, "true", bool) is True
|
||||
assert command.parsearg(tctx.master.commands, "false", bool) is False
|
||||
with pytest.raises(exceptions.CommandError):
|
||||
command.parsearg(tctx.master.commands, "flobble", bool)
|
||||
|
||||
assert len(command.parsearg(
|
||||
tctx.master.commands, "2", typing.Sequence[flow.Flow]
|
||||
)) == 2
|
||||
assert command.parsearg(tctx.master.commands, "1", flow.Flow)
|
||||
with pytest.raises(exceptions.CommandError):
|
||||
command.parsearg(tctx.master.commands, "2", flow.Flow)
|
||||
with pytest.raises(exceptions.CommandError):
|
||||
command.parsearg(tctx.master.commands, "0", flow.Flow)
|
||||
with pytest.raises(exceptions.CommandError):
|
||||
command.parsearg(tctx.master.commands, "foo", Exception)
|
||||
|
||||
assert command.parsearg(
|
||||
tctx.master.commands, "foo", typing.Sequence[str]
|
||||
) == ["foo"]
|
||||
assert command.parsearg(
|
||||
tctx.master.commands, "foo, bar", typing.Sequence[str]
|
||||
) == ["foo", "bar"]
|
||||
|
||||
a = TAddon()
|
||||
tctx.master.commands.add("choices", a.choices)
|
||||
assert command.parsearg(
|
||||
tctx.master.commands, "one", mitmproxy.types.Choice("choices"),
|
||||
) == "one"
|
||||
with pytest.raises(exceptions.CommandError):
|
||||
assert command.parsearg(
|
||||
tctx.master.commands, "invalid", mitmproxy.types.Choice("choices"),
|
||||
)
|
||||
|
||||
assert command.parsearg(
|
||||
tctx.master.commands, "foo", mitmproxy.types.Path
|
||||
) == "foo"
|
||||
assert command.parsearg(
|
||||
tctx.master.commands, "foo", mitmproxy.types.Cmd
|
||||
) == "foo"
|
||||
|
||||
|
||||
class TDec:
|
||||
@command.command("cmd1")
|
||||
|
@ -88,7 +88,9 @@ def test_cmd():
|
||||
b = mitmproxy.types._CmdType()
|
||||
assert b.is_valid(tctx.master.commands, mitmproxy.types.Cmd, "foo") is False
|
||||
assert b.is_valid(tctx.master.commands, mitmproxy.types.Cmd, "cmd1") is True
|
||||
assert b.parse(tctx.master.commands, mitmproxy.types.Cmd, "foo") == "foo"
|
||||
assert b.parse(tctx.master.commands, mitmproxy.types.Cmd, "cmd1") == "cmd1"
|
||||
with pytest.raises(mitmproxy.exceptions.TypeError):
|
||||
assert b.parse(tctx.master.commands, mitmproxy.types.Cmd, "foo")
|
||||
assert len(
|
||||
b.completion(tctx.master.commands, mitmproxy.types.Cmd, "")
|
||||
) == len(tctx.master.commands.commands.keys())
|
||||
|
Loading…
Reference in New Issue
Block a user