I want to do something like
from typing import Callable
def a(foo: Callable[[int], None]):
foo(b=5)
This code works, but gives a warning Unexpected argument.
Defining as
def a(foo: Callable[[int], None]):
foo(5)
works with no warnings as expected.
How can I pass in an expected argument as a kwarg into a function with the type checker not being angry at me?
You can use a "callable protocol" here, so:
import typing
class MyCallableType(typing.Protocol):
def __call__(self, bar:int) -> None:
...
def a(foo: MyCallableType):
foo(32)
foo(bar=32)
Now, testing the above with mypy:
jarrivillaga$ mypy --version
mypy 0.910
jarrivillaga$ mypy test.py
Success: no issues found in 1 source file
Note, this allows mypy to catch all kinds of errors, e.g. a function with the wrong argument name, or if we want b to be a function that specifies a keyword-only bar argument:
import typing
class MyCallableType(typing.Protocol):
def __call__(self, b:int) -> None:
...
def a(foo: MyCallableType):
foo(32)
foo(b=32)
def bar(b: int) -> None:
pass
def baz(*, b: int) -> None:
pass
def bing(x: int) -> None:
pass
a(bar)
a(baz)
a(bing)
And mypy will complain with the following:
jarrivillaga$ mypy test.py
test.py:21: error: Argument 1 to "a" has incompatible type "Callable[[NamedArg(int, 'b')], None]"; expected "MyCallableType"
test.py:22: error: Argument 1 to "a" has incompatible type "Callable[[int], None]"; expected "MyCallableType"
Found 2 errors in 1 file (checked 1 source file)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With