Skip to content

Would it be possible to broaden classmethod to accept ParamSpec when MyPy's support is better? #7689

Description

@NeilGirdhar

It could be something like:

P = ParamSpec('P')
class classmethod(Generic[P, _R_co]):
    @property
    def __func__(self) -> Callable[P, _R_co]: ...
    @property
    def __isabstractmethod__(self) -> bool: ...
    def __init__(self: classmethod[_R_co], __f: Callable[P, _R_co]) -> None: ...
    def __get__(self, __obj: _T, __type: type[_T] | None = ...) -> Callable[P, _R_co]: ...
    if sys.version_info >= (3, 10):
        __name__: str
        __qualname__: str
        __wrapped__: Callable[P, _R_co]

Activity

  1. AlexWaygood commented on Apr 26, 2022

    @AlexWaygood
    Member

    This is on my to-do list for as soon as mypy 0.950 is released 🙂

  2. JelleZijlstra commented on Apr 26, 2022

    @JelleZijlstra
    Member

    Though I'm not sure how much of a difference this will make, considering how thoroughly type checkers special case classmethod (and staticmethod).

  3. AlexWaygood commented on Apr 26, 2022

    @AlexWaygood
    Member

    Also, staticmethod is quite a lot easier than classmethod. staticmethod doesn't change the signature of the function it wraps, but classmethod does -- it requires Concatenate. It would be something like this:

    import sys
    from typing import TypeVar, Callable, Generic
    from typing_extensions import ParamSpec, Concatenate
    
    _P = ParamSpec("_P")
    _R_co = TypeVar("_R_co", covariant=True)
    _T = TypeVar("_T")
    
    class classmethod(Generic[_P, _R_co, _T]):
        @property
        def __func__(self) -> Callable[Concatenate[_T, _P], _R_co]: ...
        @property
        def __isabstractmethod__(self) -> bool: ...
        def __init__(self: classmethod[_P, _R_co, _T], __f: Callable[Concatenate[_T, _P], _R_co]) -> None: ...
        def __get__(self, __obj: _T | None, __type: type[_T] | None = ...) -> Callable[_P, _R_co]: ...
        if sys.version_info >= (3, 10):
            __name__: str
            __qualname__: str
            @property
            def __wrapped__(self) -> Callable[Concatenate[_T, _P], _R_co]: ...
  4. NeilGirdhar commented on Apr 26, 2022

    @NeilGirdhar
    ContributorAuthor

    @JelleZijlstra Yup, I just learned about that here. It's not too big a deal since it's very rare that you decorate class methods, but maybe after classmethod is broadened they might consider producing a classmethod[P, R, T] instead of a Callable[Concatenate[type[T], P], R].

  5. AlexWaygood commented on Apr 28, 2022

    @AlexWaygood
    Member

    Mypy 0.950 is now out, but sadly we still cannot use ParamSpec in classmethod or staticmethod due to python/mypy#12011. (abc.abstractclassmethod and abc.abstractstaticmethod inherit from classmethod and staticmethod respectively, so while that mypy issue is outstanding, we cannot make builtins.staticmethod or builtins.classmethod generic over a parameter specification without breaking those two classes.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions