Skip to content

Commit 61595bd

Browse files
committed
fix ReifiedGeneric for pyright
1 parent b3ae449 commit 61595bd

File tree

1 file changed

+14
-9
lines changed

1 file changed

+14
-9
lines changed

basedtyping/__init__.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
ForwardRef,
1010
Generic,
1111
NoReturn,
12+
Self,
1213
Sequence,
1314
Tuple,
1415
Type,
@@ -108,7 +109,7 @@ class NotEnoughTypeParametersError(ReifiedGenericError):
108109
"""
109110

110111

111-
class _ReifiedGenericMetaclass(type):
112+
class _ReifiedGenericMetaclass(type, Generic[T]):
112113
# these should really only be on the class not the metaclass, but since it needs to be accessible from both instances and the class itself, its duplicated here
113114

114115
__reified_generics__: Tuple[type, ...]
@@ -124,9 +125,8 @@ class _ReifiedGenericMetaclass(type):
124125
_can_do_instance_and_subclass_checks_without_generics: bool
125126
"""Used internally for ``isinstance`` and ``issubclass`` checks, ``True`` when the class can currenty be used in said checks without generics in them"""
126127

127-
def _orig_class(cls) -> _ReifiedGenericMetaclass:
128-
"""Gets the original class that ``ReifiedGeneric.__class_getitem__`` copied from
129-
"""
128+
def _orig_class(cls) -> _ReifiedGenericMetaclass[T]:
129+
"""Gets the original class that ``ReifiedGeneric.__class_getitem__`` copied from"""
130130
result = cls.__bases__[0]
131131
if result is ReifiedGeneric:
132132
return cls
@@ -174,7 +174,7 @@ def _check_generics_reified(cls) -> None:
174174
if not cls._generics_are_reified() or cls._has_non_reified_type_vars():
175175
cls._raise_generics_not_reified()
176176

177-
def _is_subclass(cls, subclass: object) -> TypeGuard[_ReifiedGenericMetaclass]:
177+
def _is_subclass(cls, subclass: object) -> TypeGuard[_ReifiedGenericMetaclass[T]]:
178178
"""For ``__instancecheck__`` and ``__subclasscheck__``. checks whether the
179179
"origin" type (ie. without the generics) is a subclass of this reified generic
180180
"""
@@ -187,7 +187,7 @@ def _is_subclass(cls, subclass: object) -> TypeGuard[_ReifiedGenericMetaclass]:
187187
cls._orig_class(),
188188
# https://github.com/python/mypy/issues/11671
189189
cast( # pylint:disable=protected-access
190-
_ReifiedGenericMetaclass, subclass
190+
_ReifiedGenericMetaclass[T], subclass
191191
)._orig_class(),
192192
)
193193

@@ -219,7 +219,7 @@ def __instancecheck__(cls, instance: object) -> bool:
219219
cast(ReifiedGeneric[object], instance).__reified_generics__
220220
)
221221

222-
def __call__(cls, *args: object, **kwargs: object) -> object:
222+
def __call__(cls, *args: object, **kwargs: object) -> T:
223223
"""A placeholder ``__call__`` method that gets called when the class is
224224
instantiated directly, instead of first supplying the type parameters.
225225
"""
@@ -240,14 +240,19 @@ def __call__(cls, *args: object, **kwargs: object) -> object:
240240
"foo = Foo[int]() # correct"
241241
)
242242
cls._check_generics_reified()
243-
return super().__call__(*args, **kwargs) # type: ignore[no-any-expr]
243+
return cast(T, super().__call__(*args, **kwargs))
244244

245245

246246
GenericItems: TypeAlias = Union[type, TypeVar, Tuple[Union[type, TypeVar], ...]]
247247
"""The ``items`` argument passed to ``__class_getitem__`` when creating or using a ``Generic``"""
248248

249249

250-
class ReifiedGeneric(Generic[T], metaclass=_ReifiedGenericMetaclass):
250+
class ReifiedGeneric(
251+
# mypy doesn't support metaclasses with generics but it's needed for pyrright to correctly type the `__call__
252+
# return type, otherwise all instances of `ReifiedGeneric` will have the wrong type
253+
Generic[T],
254+
metaclass=_ReifiedGenericMetaclass[Self], # type:ignore[misc]
255+
):
251256
"""A ``Generic`` where the type parameters are available at runtime and is
252257
usable in ``isinstance`` and ``issubclass`` checks.
253258

0 commit comments

Comments
 (0)