| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Hi!
Here's how property type is defined right now from a typing perspective:
from typing import Any, Callable
class property(object):
fget: Callable[[Any], Any] | None
fset: Callable[[Any, Any], None] | None
fdel: Callable[[Any], None] | None
def __init__(
self,
fget: Callable[[Any], Any] | None = ...,
fset: Callable[[Any, Any], None] | None = ...,
fdel: Callable[[Any], None] | None = ...,
doc: str | None = ...,
) -> None: ...
def getter(self, __fget: Callable[[Any], Any]) -> property: ...
def setter(self, __fset: Callable[[Any, Any], None]) -> property: ...
def deleter(self, __fdel: Callable[[Any], None]) -> property: ...
def __get__(self, __obj: Any, __type: type | None = ...) -> Any: ...
def __set__(self, __obj: Any, __value: Any) -> None: ...
def __delete__(self, __obj: Any) -> None: ...Note, that it is not generic. But, this is a type that surely can be modeled as a generic type.
Why? Because @property works with two major scenarios: getting some inner type and setting some extrenal type. This can be represented as property[GetType, SetType].
It might not seem very important to end users, because of how @propertys are used, but it quite importatnt for type-checkers and type stubs.
Here are some problems that we have in mypy with properties:
Yes, we can work around the fact we cannot simply express property[GetType, SetType], but I don't think that missing this important detail is good for the typing system in the long run.
Without this change we cannot treat @property as a regular descriptor, which follows the same rules.
Implementing generic @property will require several changes.
I guess we would need something similar as we did in https://www.python.org/dev/peps/pep-0585/
Something like adding:
{"__class_getitem__", Py_GenericAlias, METH_O\|METH_CLASS, PyDoc_STR("See PEP 585")},I am sure that this code can be improved, but it does its job as a reference / demo:
from typing import Any, Callable, Generic
G = TypeVar('G') # think about variance
S = TypeVar('S')
class property(Generic[G, S]):
fget: Callable[[Any], G] | None
fset: Callable[[Any, S], None] | None
fdel: Callable[[Any], None] | None
def __init__(
self,
fget: Callable[[Any], G] | None = ...,
fset: Callable[[Any, S], None] | None = ...,
fdel: Callable[[Any], None] | None = ...,
doc: str | None = ...,
) -> None: ...
def getter(self, __fget: Callable[[Any], G]) -> property: ...
def setter(self, __fset: Callable[[Any, S], None]) -> property: ...
def deleter(self, __fdel: Callable[[Any], None]) -> property: ...
def __get__(self, __obj: Any, __type: type | None = ...) -> Any: ...
def __set__(self, __obj: Any, __value: Any) -> None: ...
def __delete__(self, __obj: Any) -> None: ...It almost works as-is, but @property.setter part requires some extra handling from type-checkers.
As far as I understand CPython's development process, we can add this new feature to 3.11 only.
I think that using from __future__ import annotations should also work for @property the same way PEP585 defines.
If others agree with me that property[GetType, SetType] is a good thing to have, I can:
Looking forward to your feedback! 😊
Refs:
| Back | FazBrowse Home | New Git URL |
Activity
AlexWaygood commented on Dec 19, 2021
See also:
hauntsaninja commented on Dec 19, 2021
(In particular, see erictraut's comments on the second link)
sobolevn commented on Dec 19, 2021
To address some of @erictraut's feedback about @properties in python/typeshed#5987
Yes, this is my main motivation when I suggest adding generic properties support.
At least in mypy we can remove quite a lot of special cases and make property a first-class citizen.
This can easily be addressed:
From my work on decorated property support in mypy, we can see that there are not so many errors in mypy_primer output. See related comment: python/mypy#11719 (comment)
ariebovenberg commented on Dec 20, 2021
Another big opportunity of generic property could be easier annotation of read-only attributes.
This would be a big win for type stubs, as well as Protocols. A quick look at typeshed shows >10% of defs there are used simply for properties. A more readable representation would be a big win!
See also: #922 (comment)
also: since the get-only case is so common, it'd probably be logical to allow property with one type argument (where the second defaults to NoReturn). This would be consistent with how property on its own creates only a getter by default.
gvanrossum commented on Dec 20, 2021
It's clear there is something valuable here; there seem to be no lack of other issues/PRs where this has been discussed before, so it's clear there's a need. I hope you all solve the puzzle!
IIUC it should be possible to completely remove the special-casing for properties from type checkers, instead deferring completely to the more general descriptor semantics, right? Then we'd still have to debate some finer points about descriptors, but at least the behavior of properties would be fully defined by its definition in typeshed plus descriptor semantics.
JelleZijlstra commented on Dec 20, 2021
The biggest blocker for that may be the @property.setter mechanic—I don't think that can be mapped to the current type system.
(And the same for @property.deleter, if anyone uses that.)
sobolevn commented on Dec 20, 2021
Yes, with some minor special-case points. Like identifying writable / read-only properties by @.setter definition / its absence. And the same with @.deleter.
But, it is specific to property.setter and property.deleter which are not a part of a descriptor protocol.
While x = property(get_x, set_x) would be completely typed with this proposal.
gvanrossum commented on Dec 20, 2021
Hm, yeah, we'll need to special-case .setter and .deleter. Fine, as long it ends up being fully typed then. (I'm guessing one issue is that ordinarily you cannot override a method.)
sobolevn commented on Dec 26, 2021
CC @erictraut and @rchen152 from pyright and pytype 🙂
erictraut commented on Dec 29, 2021
I played around with this. Here's a variant of the proposed class definition:
Some observations:
Overall, I'm pretty negative on this change.
It would have been nice if property were defined as generic earlier, but making the change now would be very disruptive, and it would be a step backward in some respects if type checkers removed all of their custom logic and error messages specifically for properties.
sobolevn commented on Jan 11, 2022
Thanks everyone for their feedback!
Since no one is really interested in this, I am going to close this for now.
Maybe later we can revisit this decision.
ofek commented on Dec 17, 2022
@sobolevn Hmm, what gave you the impression that no one is interested in this? Many are it seems, including at my workplace.