Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a way to properly annotate decorators for both functions and methods? #824

Closed
lonelyenvoy opened this issue Jul 23, 2021 · 6 comments

Comments

@lonelyenvoy
Copy link

lonelyenvoy commented Jul 23, 2021

I opened an issue about method decorators previously and it was transferred to python/mypy. Although it looks like an implementation issue in mypy, it's indeed related to the design of the typing.

For now, it seems impossible to annotate decorators that can be applied to both functions outside and inside classes (i.e. methods). Is there a workaround?

def decorator(func):
    def wrapper(*args, **kwargs):
        ...
    return wrapper

@decorator
def foo(arg):
    ... 

class A:
    @decorator
    def bar(self, arg):
        ...
@gvanrossum
Copy link
Member

Still seems a mypy issue. It conflates class and instance methods.

@lonelyenvoy
Copy link
Author

Still seems a mypy issue. It conflates class and instance methods.

@gvanrossum Can you please elaborate a little bit by commenting in the mypy issue so that they can fix it? Thank you.

@gvanrossum
Copy link
Member

Not right now, I am about to head on vacation. All I know is that this is a longstanding mypy issue.

@lonelyenvoy
Copy link
Author

OK, enjoy your vacation time.

@Tomaz-Vieira
Copy link

Tomaz-Vieira commented Nov 3, 2021

I tried it with pyright and things seem to check just right:

# pyright: strict

from typing import Callable, TypeVar
from typing_extensions import ParamSpec


_P = ParamSpec("_P")
_OUT = TypeVar("_OUT")

def decorator(func: Callable[_P, _OUT]) -> Callable[_P, _OUT]:
    def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _OUT:
        print(f"caling {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

@decorator
def foo(arg: int) -> int:
    return 123

reveal_type(foo) # (arg: int) -> int

class A:
    @decorator
    def bar(self, arg: str) -> None:
        return None

reveal_type(A().bar) # (arg: str) -> None

so I'd say there is a way to properly annotate decorators for both functions and methods. But I think mypy doesn't support ParamSpec yet

@srittau
Copy link
Collaborator

srittau commented Nov 3, 2021

I am closing this here as this seems to be a mypy issue (python/mypy#10805).

@srittau srittau closed this as completed Nov 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants