@@ -141,8 +141,9 @@ def _type_check(arg, msg, is_argument=True):
141
141
if (isinstance (arg , _GenericAlias ) and
142
142
arg .__origin__ in invalid_generic_forms ):
143
143
raise TypeError (f"{ arg } is not valid as type argument" )
144
- if (isinstance (arg , _SpecialForm ) and arg not in (Any , NoReturn ) or
145
- arg in (Generic , Protocol )):
144
+ if arg in (Any , NoReturn ):
145
+ return arg
146
+ if isinstance (arg , _SpecialForm ) or arg in (Generic , Protocol ):
146
147
raise TypeError (f"Plain { arg } is not valid as type argument" )
147
148
if isinstance (arg , (type , TypeVar , ForwardRef )):
148
149
return arg
@@ -299,41 +300,18 @@ def __deepcopy__(self, memo):
299
300
return self
300
301
301
302
302
- class _SpecialForm (_Final , _Immutable , _root = True ):
303
- """Internal indicator of special typing constructs.
304
- See _doc instance attribute for specific docs.
305
- """
306
-
307
- __slots__ = ('_name' , '_doc' )
308
-
309
- def __new__ (cls , * args , ** kwds ):
310
- """Constructor.
311
-
312
- This only exists to give a better error message in case
313
- someone tries to subclass a special typing object (not a good idea).
314
- """
315
- if (len (args ) == 3 and
316
- isinstance (args [0 ], str ) and
317
- isinstance (args [1 ], tuple )):
318
- # Close enough.
319
- raise TypeError (f"Cannot subclass { cls !r} " )
320
- return super ().__new__ (cls )
321
-
322
- def __init__ (self , name , doc ):
323
- self ._name = name
324
- self ._doc = doc
325
-
326
- @property
327
- def __doc__ (self ):
328
- return self ._doc
303
+ # Internal indicator of special typing constructs.
304
+ # See __doc__ instance attribute for specific docs.
305
+ class _SpecialForm (_Final , _root = True ):
306
+ __slots__ = ('_name' , '__doc__' , '_getitem' )
329
307
330
- def __eq__ (self , other ):
331
- if not isinstance ( other , _SpecialForm ):
332
- return NotImplemented
333
- return self ._name == other . _name
308
+ def __init__ (self , getitem ):
309
+ self . _getitem = getitem
310
+ self . _name = getitem . __name__
311
+ self .__doc__ = getitem . __doc__
334
312
335
- def __hash__ (self ):
336
- return hash (( self . _name ,) )
313
+ def __mro_entries__ (self , bases ):
314
+ raise TypeError ( f"Cannot subclass { self !r } " )
337
315
338
316
def __repr__ (self ):
339
317
return 'typing.' + self ._name
@@ -352,31 +330,10 @@ def __subclasscheck__(self, cls):
352
330
353
331
@_tp_cache
354
332
def __getitem__ (self , parameters ):
355
- if self ._name in ('ClassVar' , 'Final' ):
356
- item = _type_check (parameters , f'{ self ._name } accepts only single type.' )
357
- return _GenericAlias (self , (item ,))
358
- if self ._name == 'Union' :
359
- if parameters == ():
360
- raise TypeError ("Cannot take a Union of no types." )
361
- if not isinstance (parameters , tuple ):
362
- parameters = (parameters ,)
363
- msg = "Union[arg, ...]: each arg must be a type."
364
- parameters = tuple (_type_check (p , msg ) for p in parameters )
365
- parameters = _remove_dups_flatten (parameters )
366
- if len (parameters ) == 1 :
367
- return parameters [0 ]
368
- return _GenericAlias (self , parameters )
369
- if self ._name == 'Optional' :
370
- arg = _type_check (parameters , "Optional[t] requires a single type." )
371
- return Union [arg , type (None )]
372
- if self ._name == 'Literal' :
373
- # There is no '_type_check' call because arguments to Literal[...] are
374
- # values, not types.
375
- return _GenericAlias (self , parameters )
376
- raise TypeError (f"{ self } is not subscriptable" )
377
-
378
-
379
- Any = _SpecialForm ('Any' , doc =
333
+ return self ._getitem (self , parameters )
334
+
335
+ @_SpecialForm
336
+ def Any (self , parameters ):
380
337
"""Special type indicating an unconstrained type.
381
338
382
339
- Any is compatible with every type.
@@ -386,9 +343,11 @@ def __getitem__(self, parameters):
386
343
Note that all the above statements are true from the point of view of
387
344
static type checkers. At runtime, Any should not be used with instance
388
345
or class checks.
389
- """ )
346
+ """
347
+ raise TypeError (f"{ self } is not subscriptable" )
390
348
391
- NoReturn = _SpecialForm ('NoReturn' , doc =
349
+ @_SpecialForm
350
+ def NoReturn (self , parameters ):
392
351
"""Special type indicating functions that never return.
393
352
Example::
394
353
@@ -399,9 +358,11 @@ def stop() -> NoReturn:
399
358
400
359
This type is invalid in other positions, e.g., ``List[NoReturn]``
401
360
will fail in static type checkers.
402
- """ )
361
+ """
362
+ raise TypeError (f"{ self } is not subscriptable" )
403
363
404
- ClassVar = _SpecialForm ('ClassVar' , doc =
364
+ @_SpecialForm
365
+ def ClassVar (self , parameters ):
405
366
"""Special type construct to mark class variables.
406
367
407
368
An annotation wrapped in ClassVar indicates that a given
@@ -416,9 +377,12 @@ class Starship:
416
377
417
378
Note that ClassVar is not a class itself, and should not
418
379
be used with isinstance() or issubclass().
419
- """ )
380
+ """
381
+ item = _type_check (parameters , f'{ self } accepts only single type.' )
382
+ return _GenericAlias (self , (item ,))
420
383
421
- Final = _SpecialForm ('Final' , doc =
384
+ @_SpecialForm
385
+ def Final (self , parameters ):
422
386
"""Special typing construct to indicate final names to type checkers.
423
387
424
388
A final name cannot be re-assigned or overridden in a subclass.
@@ -434,9 +398,12 @@ class FastConnector(Connection):
434
398
TIMEOUT = 1 # Error reported by type checker
435
399
436
400
There is no runtime checking of these properties.
437
- """ )
401
+ """
402
+ item = _type_check (parameters , f'{ self } accepts only single type.' )
403
+ return _GenericAlias (self , (item ,))
438
404
439
- Union = _SpecialForm ('Union' , doc =
405
+ @_SpecialForm
406
+ def Union (self , parameters ):
440
407
"""Union type; Union[X, Y] means either X or Y.
441
408
442
409
To define a union, use e.g. Union[int, str]. Details:
@@ -461,15 +428,29 @@ class FastConnector(Connection):
461
428
462
429
- You cannot subclass or instantiate a union.
463
430
- You can use Optional[X] as a shorthand for Union[X, None].
464
- """ )
465
-
466
- Optional = _SpecialForm ('Optional' , doc =
431
+ """
432
+ if parameters == ():
433
+ raise TypeError ("Cannot take a Union of no types." )
434
+ if not isinstance (parameters , tuple ):
435
+ parameters = (parameters ,)
436
+ msg = "Union[arg, ...]: each arg must be a type."
437
+ parameters = tuple (_type_check (p , msg ) for p in parameters )
438
+ parameters = _remove_dups_flatten (parameters )
439
+ if len (parameters ) == 1 :
440
+ return parameters [0 ]
441
+ return _GenericAlias (self , parameters )
442
+
443
+ @_SpecialForm
444
+ def Optional (self , parameters ):
467
445
"""Optional type.
468
446
469
447
Optional[X] is equivalent to Union[X, None].
470
- """ )
448
+ """
449
+ arg = _type_check (parameters , f"{ self } requires a single type." )
450
+ return Union [arg , type (None )]
471
451
472
- Literal = _SpecialForm ('Literal' , doc =
452
+ @_SpecialForm
453
+ def Literal (self , parameters ):
473
454
"""Special typing form to define literal types (a.k.a. value types).
474
455
475
456
This form can be used to indicate to type checkers that the corresponding
@@ -486,10 +467,13 @@ def open_helper(file: str, mode: MODE) -> str:
486
467
open_helper('/some/path', 'r') # Passes type check
487
468
open_helper('/other/path', 'typo') # Error in type checker
488
469
489
- Literal[...] cannot be subclassed. At runtime, an arbitrary value
490
- is allowed as type argument to Literal[...], but type checkers may
491
- impose restrictions.
492
- """ )
470
+ Literal[...] cannot be subclassed. At runtime, an arbitrary value
471
+ is allowed as type argument to Literal[...], but type checkers may
472
+ impose restrictions.
473
+ """
474
+ # There is no '_type_check' call because arguments to Literal[...] are
475
+ # values, not types.
476
+ return _GenericAlias (self , parameters )
493
477
494
478
495
479
class ForwardRef (_Final , _root = True ):
0 commit comments