summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2023-08-10 12:03:52 +0200
committerFlorian Bruhin <me@the-compiler.org>2023-08-10 12:05:07 +0200
commitb7a470025da53e03ff52da712b18fdd0cc20acf7 (patch)
tree24d5e8fb5bacdd3428b12b92cc205d710bd6f046
parent89b91105022be0216d8fb323b20fd15e1391af28 (diff)
downloadqutebrowser-b7a470025da53e03ff52da712b18fdd0cc20acf7.tar.gz
qutebrowser-b7a470025da53e03ff52da712b18fdd0cc20acf7.zip
mypy: Improve typing for cmdutils/qute_args
See https://github.com/python/mypy/issues/2087
-rw-r--r--qutebrowser/api/cmdutils.py31
1 files changed, 24 insertions, 7 deletions
diff --git a/qutebrowser/api/cmdutils.py b/qutebrowser/api/cmdutils.py
index 067ebca92..0c367c6bf 100644
--- a/qutebrowser/api/cmdutils.py
+++ b/qutebrowser/api/cmdutils.py
@@ -35,7 +35,7 @@ Possible values:
import inspect
-from typing import Any, Callable, Iterable
+from typing import Any, Callable, Iterable, Protocol, Optional, Dict, cast
from qutebrowser.utils import qtutils
from qutebrowser.commands import command, cmdexc
@@ -90,7 +90,21 @@ def check_exclusive(flags: Iterable[bool], names: Iterable[str]) -> None:
raise CommandError("Only one of {} can be given!".format(argstr))
-_CmdHandlerType = Callable[..., Any]
+_CmdHandlerFunc = Callable[..., Any]
+
+
+class _CmdHandlerType(Protocol):
+
+ """A qutebrowser command function, which had qute_args patched on it.
+
+ Applying @cmdutils.argument to a function will patch it with a qute_args attribute.
+ Below, we cast the decorated function to _CmdHandlerType to make mypy aware of this.
+ """
+
+ qute_args: Optional[Dict[str, command.ArgInfo]]
+
+ def __call__(self, *args: Any, **kwargs: Any) -> Any:
+ ...
class register: # noqa: N801,N806 pylint: disable=invalid-name
@@ -118,7 +132,7 @@ class register: # noqa: N801,N806 pylint: disable=invalid-name
# The arguments to pass to Command.
self._kwargs = kwargs
- def __call__(self, func: _CmdHandlerType) -> _CmdHandlerType:
+ def __call__(self, func: _CmdHandlerFunc) -> _CmdHandlerType:
"""Register the command before running the function.
Gets called when a function should be decorated.
@@ -158,7 +172,8 @@ class register: # noqa: N801,N806 pylint: disable=invalid-name
# This is checked by future @cmdutils.argument calls so they fail
# (as they'd be silently ignored otherwise)
- func.qute_args = None # type: ignore[attr-defined]
+ func = cast(_CmdHandlerType, func)
+ func.qute_args = None
return func
@@ -210,19 +225,21 @@ class argument: # noqa: N801,N806 pylint: disable=invalid-name
self._argname = argname # The name of the argument to handle.
self._kwargs = kwargs # Valid ArgInfo members.
- def __call__(self, func: _CmdHandlerType) -> _CmdHandlerType:
+ def __call__(self, func: _CmdHandlerFunc) -> _CmdHandlerType:
funcname = func.__name__
if self._argname not in inspect.signature(func).parameters:
raise ValueError("{} has no argument {}!".format(funcname,
self._argname))
+
+ func = cast(_CmdHandlerType, func)
if not hasattr(func, 'qute_args'):
- func.qute_args = {} # type: ignore[attr-defined]
+ func.qute_args = {}
elif func.qute_args is None:
raise ValueError("@cmdutils.argument got called above (after) "
"@cmdutils.register for {}!".format(funcname))
arginfo = command.ArgInfo(**self._kwargs)
- func.qute_args[self._argname] = arginfo # type: ignore[attr-defined]
+ func.qute_args[self._argname] = arginfo
return func