Sebastian Thomas
Sebastian Thomas

Reputation: 595

mypy call-arg error where default argument is set

I have code that looks like the following:

from typing import Callable


def decorate(func: Callable[[str], None]) -> Callable[[str], None]:
    return func


@decorate
def do_something(some_str: str = 'Hello world') -> None:
    print(some_str)


if __name__ == '__main__':
    do_something()

When running mypy, it reports the following error for the last line:

error: Too few arguments for "do_something" [call-arg]

How can I fix this error (without changing the return type of decorate to Callable[..., None])?

Upvotes: 2

Views: 2877

Answers (2)

MisterMiyagi
MisterMiyagi

Reputation: 52169

Use a TypeVar to indicate that the input and return type are equivalent and defined by the Callable received. Since Callable types include the entire signature, this lets the type checker infer positional/optional/keyword arguments as well.

from typing import Callable, TypeVar

# A type variable that can represent any Callable type
C = TypeVar("C", bound=Callable)

# The input Callable type defines the output Callable type as well
def decorate(func: C) -> C:
    return func

If decorate can only work with callables that may take a string, adjust the bound accordingly.

# A type variable that can represent any Callable type that takes a string
C = TypeVar("C", bound=Callable[[str], None])

Notably, a callable taking a str or using a default still satisfies Callable[[str], None] since it can be called with a str argument.

Upvotes: 1

joel
joel

Reputation: 7887

Protocol and __call__ give a lot of (somewhat verbose) power when expressing function types

class Foo(Protocol):
    def __call__(self, some_str: str = 'Hello world') -> None:
        ...

def decorate(func: Foo) -> Foo:
    return func

@decorate
def do_something(some_str: str = 'Hello world') -> None:
    print(some_str)

if __name__ == '__main__':
    do_something()

Not sure how to satisfyingly avoid the "Hello World!" duplication.

Upvotes: 1

Related Questions