Is this decorator type-annotated correctly? [closed]

from functools import wraps
from typing import Any, Callable


def timer(func: Callable[..., Any]) -> Callable[..., Any]:
    """Calculates the runtime of a function, and outputs it to logging.DEBUG."""

    @wraps(func)
    def wrapper(*args, **kwargs):
        start = perf_counter()
        value = func(*args, **kwargs)
        end = perf_counter()
        _logger = logging.getLogger(__name__ + "." + func.__name__)
        _logger.debug(" runtime: {:.4f} seconds".format(end - start))
        return value

    return wrapper

Answer

Indentation seems a bit off here, but otherwise, yes, the types aren’t incorrect. You could make this a bit more precise, though. The function you output has the same return type as the function taken as input, but you don’t note this.

In particular, you can say something like

from typing import Callable, TypeVar

T = TypeVar("T")
def timer(func: Callable[..., T]) -> Callable[..., T]:

It seems like you should be able to do the same with the args/kwargs, but I haven’t come across that case in my own typing experience, so I can’t say exactly how. EDIT – See this GitHub issue for more about typing those; it doesn’t seem possible (yet?).

I suppose you could also say

def timer(func: T) -> T:

but that doesn’t seem as useful.

Leave a Reply

Your email address will not be published. Required fields are marked *