diff --git a/qutebrowser/commands/cmdutils.py b/qutebrowser/commands/cmdutils.py index 9612b2255..e708cbcd1 100644 --- a/qutebrowser/commands/cmdutils.py +++ b/qutebrowser/commands/cmdutils.py @@ -185,8 +185,10 @@ class argument: # pylint: disable=invalid-name self._kwargs = kwargs def __call__(self, func): + funcname = func.__name__ + if self._argname not in inspect.signature(func).parameters: - raise ValueError("{} has no argument {}!".format(func.__name__, + raise ValueError("{} has no argument {}!".format(funcname, self._argname)) # Fill up args which weren't passed @@ -196,6 +198,10 @@ class argument: # pylint: disable=invalid-name if not hasattr(func, 'qute_args'): func.qute_args = {} + elif func.qute_args is None: + raise ValueError("@cmdutils.argument got called above (after) " + "@cmdutils.register for {}!".format(funcname)) + func.qute_args[self._argname] = command.ArgInfo(**self._kwargs) return func diff --git a/qutebrowser/commands/command.py b/qutebrowser/commands/command.py index 69aa2fa77..59dbcf278 100644 --- a/qutebrowser/commands/command.py +++ b/qutebrowser/commands/command.py @@ -128,6 +128,10 @@ class Command: args = self._inspect_func() + # This is checked by future @cmdutils.argument calls so they fail + # (as they'd be silently ignored otherwise) + self.handler.qute_args = None + if self.completion is not None and len(self.completion) > len(args): raise ValueError("Got {} completions, but only {} " "arguments!".format(len(self.completion), diff --git a/tests/unit/commands/test_cmdutils.py b/tests/unit/commands/test_cmdutils.py index 40eb53df0..282bbf935 100644 --- a/tests/unit/commands/test_cmdutils.py +++ b/tests/unit/commands/test_cmdutils.py @@ -260,3 +260,17 @@ class TestArgument: 'bar': self._arginfo(flag='y') } assert fun.qute_args == expected + + def test_wrong_order(self): + """When @cmdutils.argument is used above (after) @register, fail.""" + with pytest.raises(ValueError) as excinfo: + @cmdutils.argument('bar', flag='y') + @cmdutils.register() + def fun(bar): + """Blah.""" + pass + + text = ("@cmdutils.argument got called above (after) " + "@cmdutils.register for fun!") + + assert str(excinfo.value) == text