From 71f9c5d2061093535f10b1ffa0619a5b1e8131ff Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 3 Dec 2018 15:48:52 +0100 Subject: [PATCH] Fix handling of annotated varargs in commands When we have something like "*values: str" in :config-cycle, we get a list of values, but the type converter assumes it's a string. We could implement proper conversion of *args, but for now, let's just make sure it's always a string. --- qutebrowser/commands/command.py | 13 +++++++++---- tests/unit/api/test_cmdutils.py | 9 +++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/qutebrowser/commands/command.py b/qutebrowser/commands/command.py index 8d2f5ad57..9883447a8 100644 --- a/qutebrowser/commands/command.py +++ b/qutebrowser/commands/command.py @@ -333,13 +333,18 @@ class Command: param: The inspect.Parameter to look at. """ arginfo = self.get_arg_info(param) - if param.annotation is not inspect.Parameter.empty: + if arginfo.value: + # Filled values are passed 1:1 + return None + elif param.kind in [inspect.Parameter.VAR_POSITIONAL, + inspect.Parameter.VAR_KEYWORD]: + # For *args/**kwargs we only support strings + assert param.annotation in [inspect.Parameter.empty, str], param + return None + elif param.annotation is not inspect.Parameter.empty: return param.annotation elif param.default not in [None, inspect.Parameter.empty]: return type(param.default) - elif arginfo.value or param.kind in [inspect.Parameter.VAR_POSITIONAL, - inspect.Parameter.VAR_KEYWORD]: - return None else: return str diff --git a/tests/unit/api/test_cmdutils.py b/tests/unit/api/test_cmdutils.py index 5e1389c80..9f01ea7bb 100644 --- a/tests/unit/api/test_cmdutils.py +++ b/tests/unit/api/test_cmdutils.py @@ -154,6 +154,15 @@ class TestRegister: args, kwargs = cmd._get_call_args(win_id=0) fun(*args, **kwargs) + def test_star_args_optional_annotated(self): + @cmdutils.register(star_args_optional=True) + def fun(*args: str): + """Blah.""" + + cmd = objects.commands['fun'] + cmd.namespace = cmd.parser.parse_args([]) + cmd._get_call_args(win_id=0) + @pytest.mark.parametrize('inp, expected', [ (['--arg'], True), (['-a'], True), ([], False)]) def test_flag(self, inp, expected):