Skip to content

"class property" should be Generic[T] #4731

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

Open
Conchylicultor opened this issue Oct 30, 2020 · 6 comments
Open

"class property" should be Generic[T] #4731

Conchylicultor opened this issue Oct 30, 2020 · 6 comments
Labels
stubs: improvement Improve/refactor existing annotations, other stubs issues

Comments

@Conchylicultor
Copy link

Conchylicultor commented Oct 30, 2020

Currently property.__get__ returns Any, which loose information:

class property(object):

This would be more correct for property.__get__ to be generic and return T. Similar to cached_property:

class cached_property(Generic[_T]):

class A:

  @cached_property
  def f(self) -> int:  # f is `cached_property[int]`, f.__get__() -> int
    ...

  @property
  def g(self) -> int:  # f is `property[Any]`, g.__get__() -> Any
    ...
@srittau
Copy link
Collaborator

srittau commented Nov 3, 2020

This makes sense to me. It might even make sense to use two type variables for setting and getting. On the other hand, I don't know what the impact on type checkers is, since I think they usually hard-code properties.

@jp-larose
Copy link

I was going to open a new issue in response to python/typing#758, but found this one already opened :)

@jp-larose
Copy link

I seriously doubt this is idea is supported, but I'll ask anyway.... Is it possible to @overload a class like you can for a function/method? The reason I thought of that is it would allow property with one or two TypeVars. I suspect that the vast majority of uses is for the getter and setter of property to use the same type. However, for those cases where they use different types, there needs to be some way to express that.

@overload
class property(Generic[_T]):
    fget: Optional[Callable[[Any], _T]]
    fset: Optional[Callable[[Any, _T], None]]
    fdel: Optional[Callable[[Any], None]]
    .... # The remaining signatures


@overload
class property(Generic[_T_contra, _T_co]):
    fget: Optional[Callable[[Any], _T_co]]
    fset: Optional[Callable[[Any, _T_contra], None]]
    fdel: Optional[Callable[[Any], None]]
    .... # The remaining signatures

@JelleZijlstra
Copy link
Member

You can overloads its __init__ or __new__ method.

@JelleZijlstra
Copy link
Member

Though I guess that wouldn't give you a way to vary the number of type parameters.

@davidhalter
Copy link
Contributor

davidhalter commented Mar 9, 2023

How about something like this?

_C = TypeVar("_C", contravariant=True)
_R = TypeVar("_R", covariant=True)
_R2 = TypeVar("_R2", covariant=True)
_V = TypeVar("_V", contravariant=True)
_V2 = TypeVar("_V2", contravariant=True)

class property(Generic[_C, _R, _V]):
    fget: Callable[[_C], _R] | None
    fset: Callable[[_C, _V], None] | None
    fdel: Callable[[_C], None] | None
    __isabstractmethod__: bool
    def __init__(
        self,
        fget: Callable[[_C], _R] | None = ...,
        fset: Callable[[_C, _V], None] | None = ...,
        fdel: Callable[[_C], None] | None = ...,
        doc: str | None = ...,
    ) -> None: ...
    def getter(self, __fget: Callable[[_C], _R2]) -> property[_C, _R2, _V]: ...
    def setter(self, __fset: Callable[[_C, _V2], None]) -> property[_C, _R, _V2]: ...
    def deleter(self, __fdel: Callable[[_C], None]) -> property: ...
    def __get__(self, __obj: _C | None, __type: Type[_C] | None = ...) -> Any: ...
    def __set__(self, __obj: _C, __value: _V) -> None: ...
    def __delete__(self, __obj: _C) -> None: ...

Since the undefined type vars default to Never when they are not provided, this should work fine.

I'm happy to create a pull request if this is something that would potentially be accepted. What do you guys think?

Edit: After writing this, I realized that @erictraut has written something similar

@srittau srittau added stubs: improvement Improve/refactor existing annotations, other stubs issues and removed size-large labels Mar 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stubs: improvement Improve/refactor existing annotations, other stubs issues
Projects
None yet
Development

No branches or pull requests

6 participants