18
18
cast ,
19
19
)
20
20
21
- from typing_extensions import Final , Self , TypeAlias , TypeGuard
21
+ from typing_extensions import Final , TypeAlias , TypeGuard
22
22
23
23
from basedtyping .runtime_only import OldUnionType
24
24
@@ -109,7 +109,7 @@ class NotEnoughTypeParametersError(ReifiedGenericError):
109
109
"""
110
110
111
111
112
- class _ReifiedGenericMetaclass (type , Generic [ T ] ):
112
+ class _ReifiedGenericMetaclass (type ):
113
113
# 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
114
114
115
115
__reified_generics__ : Tuple [type , ...]
@@ -125,7 +125,7 @@ class _ReifiedGenericMetaclass(type, Generic[T]):
125
125
_can_do_instance_and_subclass_checks_without_generics : bool
126
126
"""Used internally for ``isinstance`` and ``issubclass`` checks, ``True`` when the class can currenty be used in said checks without generics in them"""
127
127
128
- def _orig_class (cls ) -> _ReifiedGenericMetaclass [ T ] :
128
+ def _orig_class (cls ) -> _ReifiedGenericMetaclass :
129
129
"""Gets the original class that ``ReifiedGeneric.__class_getitem__`` copied from
130
130
"""
131
131
result = cls .__bases__ [0 ]
@@ -175,7 +175,7 @@ def _check_generics_reified(cls) -> None:
175
175
if not cls ._generics_are_reified () or cls ._has_non_reified_type_vars ():
176
176
cls ._raise_generics_not_reified ()
177
177
178
- def _is_subclass (cls , subclass : object ) -> TypeGuard [_ReifiedGenericMetaclass [ T ] ]:
178
+ def _is_subclass (cls , subclass : object ) -> TypeGuard [_ReifiedGenericMetaclass ]:
179
179
"""For ``__instancecheck__`` and ``__subclasscheck__``. checks whether the
180
180
"origin" type (ie. without the generics) is a subclass of this reified generic
181
181
"""
@@ -188,7 +188,7 @@ def _is_subclass(cls, subclass: object) -> TypeGuard[_ReifiedGenericMetaclass[T]
188
188
cls ._orig_class (),
189
189
# https://github.com/python/mypy/issues/11671
190
190
cast ( # pylint:disable=protected-access
191
- _ReifiedGenericMetaclass [ T ] , subclass
191
+ _ReifiedGenericMetaclass , subclass
192
192
)._orig_class (),
193
193
)
194
194
@@ -220,40 +220,35 @@ def __instancecheck__(cls, instance: object) -> bool:
220
220
cast (ReifiedGeneric [object ], instance ).__reified_generics__
221
221
)
222
222
223
- def __call__ (cls , * args : object , ** kwargs : object ) -> T :
223
+ # need the generic here for pyright. see https://github.com/microsoft/pyright/issues/5488
224
+ def __call__ (cls : type [T ], * args : object , ** kwargs : object ) -> T :
224
225
"""A placeholder ``__call__`` method that gets called when the class is
225
226
instantiated directly, instead of first supplying the type parameters.
226
227
"""
228
+ cls_narrowed = cast (Type [ReifiedGeneric [object ]], cls )
227
229
if (
228
230
# instantiating a ReifiedGeneric without specifying any TypeVars
229
- not hasattr (cls , "_orig_type_vars" )
231
+ not hasattr (cls_narrowed , "_orig_type_vars" )
230
232
# instantiating a subtype of a ReifiedGeneric without specifying any TypeVars
231
- or cls ._orig_type_vars == cls .__type_vars__
233
+ or cls_narrowed ._orig_type_vars == cls_narrowed .__type_vars__
232
234
):
233
235
raise NotReifiedError (
234
- f"Cannot instantiate ReifiedGeneric { cls .__name__ !r} because its type"
235
- " parameters were not supplied. The type parameters must be explicitly"
236
- " specified in the instantiation so that the type data can be made"
237
- " available at runtime.\n \n "
238
- "For example:\n \n "
239
- "foo: Foo[int] = Foo() #wrong\n "
240
- "foo = Foo[T]() #wrong\n "
241
- "foo = Foo[int]() # correct"
236
+ f"Cannot instantiate ReifiedGeneric { cls_narrowed .__name__ !r} because"
237
+ " its type parameters were not supplied. The type parameters must be"
238
+ " explicitly specified in the instantiation so that the type data can"
239
+ " be made available at runtime.\n \n For example:\n \n foo: Foo[int] ="
240
+ " Foo() #wrong\n foo = Foo[T]() #wrong\n foo = Foo[int]() # correct"
242
241
)
243
- cls ._check_generics_reified ()
244
- return cast (T , super ().__call__ (* args , ** kwargs ))
242
+ cls_narrowed ._check_generics_reified ()
243
+ # see comment about cls above
244
+ return cast (T , super ().__call__ (* args , ** kwargs )) # type:ignore[misc]
245
245
246
246
247
247
GenericItems : TypeAlias = Union [type , TypeVar , Tuple [Union [type , TypeVar ], ...]]
248
248
"""The ``items`` argument passed to ``__class_getitem__`` when creating or using a ``Generic``"""
249
249
250
250
251
- class ReifiedGeneric (
252
- Generic [T ],
253
- # mypy doesn't support metaclasses with generics but for pyright we need to correctly type the `__call__`
254
- # return type, otherwise all instances of `ReifiedGeneric` will have the wrong type
255
- metaclass = _ReifiedGenericMetaclass [Self ], # type:ignore[misc]
256
- ):
251
+ class ReifiedGeneric (Generic [T ], metaclass = _ReifiedGenericMetaclass ):
257
252
"""A ``Generic`` where the type parameters are available at runtime and is
258
253
usable in ``isinstance`` and ``issubclass`` checks.
259
254
@@ -316,7 +311,9 @@ def __class_getitem__( # type: ignore[no-any-decorated]
316
311
orig_type_vars = (
317
312
cls .__type_vars__
318
313
if hasattr (cls , "__type_vars__" )
319
- else cast (Tuple [TypeVar , ...], cls .__parameters__ )
314
+ else cast (
315
+ Tuple [TypeVar , ...], cls .__parameters__ # type:ignore[attr-defined]
316
+ )
320
317
)
321
318
322
319
# add any reified generics from the superclass if there is one
0 commit comments