Decouple types.DynamicClassAttribute from property (#13276)

This commit is contained in:
Stephen Morton
2025-03-07 10:08:27 -08:00
committed by GitHub
parent 7cb3eef00c
commit 56fa438a27
6 changed files with 40 additions and 10 deletions
@@ -25,8 +25,6 @@ posixpath.join
ntpath.join
os.path.join
types.DynamicClassAttribute..* # In the stub we pretend it's an alias for property, but it has positional-only differences
# typing.IO uses positional-or-keyword arguments, but in the stubs we prefer
# to mark these as positional-only for compatibility with existing sub-classes.
typing(_extensions)?\.BinaryIO\.write
@@ -46,8 +46,6 @@ posixpath.join
ntpath.join
os.path.join
types.DynamicClassAttribute..* # In the stub we pretend it's an alias for property, but it has positional-only differences
# typing.IO uses positional-or-keyword arguments, but in the stubs we prefer
# to mark these as positional-only for compatibility with existing sub-classes.
typing(_extensions)?\.BinaryIO\.write
@@ -45,8 +45,6 @@ posixpath.join
ntpath.join
os.path.join
types.DynamicClassAttribute..* # In the stub we pretend it's an alias for property, but it has positional-only differences
# typing.IO uses positional-or-keyword arguments, but in the stubs we prefer
# to mark these as positional-only for compatibility with existing sub-classes.
typing(_extensions)?\.BinaryIO\.write
@@ -45,8 +45,6 @@ posixpath.join
ntpath.join
os.path.join
types.DynamicClassAttribute..* # In the stub we pretend it's an alias for property, but it has positional-only differences
# typing.IO uses positional-or-keyword arguments, but in the stubs we prefer
# to mark these as positional-only for compatibility with existing sub-classes.
typing(_extensions)?\.BinaryIO\.write
+19
View File
@@ -1,3 +1,5 @@
from __future__ import annotations
import sys
import types
from collections import UserDict
@@ -39,3 +41,20 @@ item_3 = mp.get(3, "default")
assert_type(item_3, Union[int, str])
# Default isn't accepted as a keyword argument.
mp.get(4, default="default") # type: ignore
# test: `types.DynamicClassAttribute`
class DCAtest:
_value: int | None = None
@types.DynamicClassAttribute
def foo(self) -> int | None:
return self._value
@foo.setter
def foo(self, value: int) -> None:
self._value = value
@foo.deleter
def foo(self) -> None:
self._value = None
+21 -2
View File
@@ -615,8 +615,27 @@ def prepare_class(
if sys.version_info >= (3, 12):
def get_original_bases(cls: type, /) -> tuple[Any, ...]: ...
# Actually a different type, but `property` is special and we want that too.
DynamicClassAttribute = property
# Does not actually inherit from property, but saying it does makes sure that
# pyright handles this class correctly.
class DynamicClassAttribute(property):
fget: Callable[[Any], Any] | None
fset: Callable[[Any, Any], object] | None # type: ignore[assignment]
fdel: Callable[[Any], object] | None # type: ignore[assignment]
overwrite_doc: bool
__isabstractmethod__: bool
def __init__(
self,
fget: Callable[[Any], Any] | None = None,
fset: Callable[[Any, Any], object] | None = None,
fdel: Callable[[Any], object] | None = None,
doc: str | None = None,
) -> None: ...
def __get__(self, instance: Any, ownerclass: type | None = None) -> Any: ...
def __set__(self, instance: Any, value: Any) -> None: ...
def __delete__(self, instance: Any) -> None: ...
def getter(self, fget: Callable[[Any], Any]) -> DynamicClassAttribute: ...
def setter(self, fset: Callable[[Any, Any], object]) -> DynamicClassAttribute: ...
def deleter(self, fdel: Callable[[Any], object]) -> DynamicClassAttribute: ...
_Fn = TypeVar("_Fn", bound=Callable[..., object])
_R = TypeVar("_R")