8000 mypy: Improve typing for cmdutils/qute_args · qutebrowser/qutebrowser@b7a4700 · GitHub 8000
[go: up one dir, main page]

Skip to content

Commit b7a4700

Browse files
committed
mypy: Improve typing for cmdutils/qute_args
See python/mypy#2087
1 parent 89b9110 commit b7a4700

File tree

1 file changed

+24
-7
lines changed

1 file changed

+24
-7
lines changed

qutebrowser/api/cmdutils.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def foo(bar: int, baz=True):
3535

3636

3737
import inspect
38-
from typing import Any, Callable, Iterable
38+
from typing import Any, Callable, Iterable, Protocol, Optional, Dict, cast
3939

4040
from qutebrowser.utils import qtutils
4141
from qutebrowser.commands import command, cmdexc
@@ -90,7 +90,21 @@ def check_exclusive(flags: Iterable[bool], names: Iterable[str]) -> None:
9090
raise CommandError("Only one of {} can be given!".format(argstr))
9191

9292

93-
_CmdHandlerType = Callable[..., Any]
93+
_CmdHandlerFunc = Callable[..., Any]
94+
95+
96+
class _CmdHandlerType(Protocol):
97+
98+
"""A qutebrowser command function, which had qute_args patched on it.
99+
100+
Applying @cmdutils.argument to a function will patch it with a qute_args attribute.
101+
Below, we cast the decorated function to _CmdHandlerType to make mypy aware of this.
102+
"""
103+
104+
qute_args: Optional[Dict[str, command.ArgInfo]]
105+
106+
def __call__(self, *args: Any, **kwargs: Any) -> Any:
107+
...
94108

95109

96110
class register: # noqa: N801,N806 pylint: disable=invalid-name
@@ -118,7 +132,7 @@ def __init__(self, *,
118132
# The arguments to pass to Command.
119133
self._kwargs = kwargs
120134

121-
def __call__(self, func: _CmdHandlerType) -> _CmdHandlerType:
135+
def __call__(self, func: _CmdHandlerFunc) -> _CmdHandlerType:
122136
"""Register the command before running the function.
123137
124138
Gets called when a function should be decorated.
@@ -158,7 +172,8 @@ def __call__(self, func: _CmdHandlerType) -> _CmdHandlerType:
158172

159173
# This is checked by future @cmdutils.argument calls so they fail
160174
# (as they'd be silently ignored otherwise)
161-
func.qute_args = None # type: ignore[attr-defined]
175+
func = cast(_CmdHandlerType, func)
176+
func.qute_args = None
162177

163178
return func
164179

@@ -210,19 +225,21 @@ def __init__(self, argname: str, **kwargs: Any) -> None:
210225
self._argname = argname # The name of the argument to handle.
211226
self._kwargs = kwargs # Valid ArgInfo members.
212227

213-
def __call__(self, func: _CmdHandlerType) -> _CmdHandlerType:
228+
def __call__(self, func: _CmdHandlerFunc) -> _CmdHandlerType:
214229
funcname = func.__name__
215230

216231
if self._argname not in inspect.signature(func).parameters:
217232
raise ValueError("{} has no argument {}!".format(funcname,
218233
self._argname))
234+
235+
func = cast(_CmdHandlerType, func)
219236
if not hasattr(func, 'qute_args'):
220-
func.qute_args = {} # type: ignore[attr-defined]
237+
func.qute_args = {}
221238
elif func.qute_args is None:
222239
raise ValueError("@cmdutils.argument got called above (after) "
223240
"@cmdutils.register for {}!".format(funcname))
224241

225242
arginfo = command.ArgInfo(**self._kwargs)
226-
func.qute_args[self._argname] = arginfo # type: ignore[attr-defined]
243+
func.qute_args[self._argname] = arginfo
227244

228245
return func

0 commit comments

Comments
 (0)
0