Skip to content Skip to sidebar Skip to footer

Mypy Errors For Decorator W/ Arguments

I'm trying to do strict type checking with MyPy and I can't seem to get decorators with arguments to work without throwing conflicting errors. According to docs and other answers,

Solution 1:

The issue here is the return type of the outer layer of your decorator. You need to correct your type annotation to the following:

from time import sleep 
from typing import TypeVar, Any, Callable, castF= TypeVar('F', bound=Callable[..., Any])

def multi_try_if_error(n_tries: int, sleep_duration: int) -> Callable[[F], F]:
    def decorator(fn: F) -> F:
        def wrapper(*args: Any, **kwargs: Any) -> Any:
            for _ in range(n_tries):
                try:
                    return fn(*args, **kwargs)
                except Exception as e:
                    caught = e
                    sleep(sleep_duration)
            raise ValueError(caught)return cast(F, wrapper)
    return decorator


@multi_try_if_error(n_tries=3, sleep_duration=1)
def query_db(q: str) -> None:
    return

What's going on here

Conceptualising (and type-hinting) a simple decorator that doesn't take arguments is fairly straighforward. We define a function C that takes in a function of type F and spits out a new function that is also of type F.

# Decorator that doesn't take arguments takes in a function,# and spits out a function of the same typeDecoratorTypeNoArgs = Callable[[F], F]

It's important to recognise, however, that that's not what a decorator that takes arguments is doing. Rather than taking in a function of type F and spitting out a new function of type F (which can be conceptualised as Callable[[F], F]), multi_try_if_error is a function that takes in two int arguments and returns a function that will take in a function of type F and return a function of type F (which can be conceptualised as Callable[[int, int], Callable[[F], F]]).

# Decorator that takes arguments takes in arguments,# and spits out a decorator that doesn't take arguments
DecoratorTypeWithArgs = Callable[[int, int], Callable[[F], F]]

As such, the outer layer of your decorator must be annotated as returning Callable[[F], F] rather than as returning F. Once you make this change, your decorator passes MyPy --strict with flying colours.

Post a Comment for "Mypy Errors For Decorator W/ Arguments"