@@ -416,7 +416,7 @@ def __subclasshook__(cls, C):
416416class _CallableGenericAlias (GenericAlias ):
417417 """ Represent `Callable[argtypes, resulttype]`.
418418
419- This sets ``__args__`` to a tuple containing the flattened``argtypes``
419+ This sets ``__args__`` to a tuple containing the flattened ``argtypes``
420420 followed by ``resulttype``.
421421
422422 Example: ``Callable[[int, str], float]`` sets ``__args__`` to
@@ -426,53 +426,107 @@ class _CallableGenericAlias(GenericAlias):
426426 __slots__ = ()
427427
428428 def __new__ (cls , origin , args ):
429- try :
430- return cls .__create_ga (origin , args )
431- except TypeError as exc :
432- import warnings
433- warnings .warn (f'{ str (exc )} '
434- f'(This will raise a TypeError in Python 3.10.)' ,
435- DeprecationWarning )
436- return GenericAlias (origin , args )
437-
438- @classmethod
439- def __create_ga (cls , origin , args ):
440- if not isinstance (args , tuple ) or len (args ) != 2 :
429+ if not (isinstance (args , tuple ) and len (args ) == 2 ):
441430 raise TypeError (
442431 "Callable must be used as Callable[[arg, ...], result]." )
443432 t_args , t_result = args
444- if isinstance (t_args , (list , tuple )):
445- ga_args = tuple (t_args ) + (t_result ,)
446- # This relaxes what t_args can be on purpose to allow things like
447- # PEP 612 ParamSpec. Responsibility for whether a user is using
448- # Callable[...] properly is deferred to static type checkers.
449- else :
450- ga_args = args
451- return super ().__new__ (cls , origin , ga_args )
433+ if isinstance (t_args , list ):
434+ args = (* t_args , t_result )
435+ elif not _is_param_expr (t_args ):
436+ raise TypeError (f"Expected a list of types, an ellipsis, "
437+ f"ParamSpec, or Concatenate. Got { t_args } " )
438+ return super ().__new__ (cls , origin , args )
439+
440+ @property
441+ def __parameters__ (self ):
442+ params = []
443+ for arg in self .__args__ :
444+ # Looks like a genericalias
445+ if hasattr (arg , "__parameters__" ) and isinstance (arg .__parameters__ , tuple ):
446+ params .extend (arg .__parameters__ )
447+ else :
448+ if _is_typevarlike (arg ):
449+ params .append (arg )
450+ return tuple (dict .fromkeys (params ))
452451
453452 def __repr__ (self ):
454- if len (self .__args__ ) == 2 and self .__args__ [0 ] is Ellipsis :
453+ if len (self .__args__ ) == 2 and _is_param_expr ( self .__args__ [0 ]) :
455454 return super ().__repr__ ()
456455 return (f'collections.abc.Callable'
457456 f'[[{ ", " .join ([_type_repr (a ) for a in self .__args__ [:- 1 ]])} ], '
458457 f'{ _type_repr (self .__args__ [- 1 ])} ]' )
459458
460459 def __reduce__ (self ):
461460 args = self .__args__
462- if not (len (args ) == 2 and args [0 ] is Ellipsis ):
461+ if not (len (args ) == 2 and _is_param_expr ( args [0 ]) ):
463462 args = list (args [:- 1 ]), args [- 1 ]
464463 return _CallableGenericAlias , (Callable , args )
465464
466465 def __getitem__ (self , item ):
467466 # Called during TypeVar substitution, returns the custom subclass
468- # rather than the default types.GenericAlias object.
469- ga = super ().__getitem__ (item )
470- args = ga .__args__
471- t_result = args [- 1 ]
472- t_args = args [:- 1 ]
473- args = (t_args , t_result )
474- return _CallableGenericAlias (Callable , args )
475-
467+ # rather than the default types.GenericAlias object. Most of the
468+ # code is copied from typing's _GenericAlias and the builtin
469+ # types.GenericAlias.
470+
471+ # A special case in PEP 612 where if X = Callable[P, int],
472+ # then X[int, str] == X[[int, str]].
473+ param_len = len (self .__parameters__ )
474+ if param_len == 0 :
475+ raise TypeError (f'{ self } is not a generic class' )
476+ if not isinstance (item , tuple ):
477+ item = (item ,)
478+ if (param_len == 1 and _is_param_expr (self .__parameters__ [0 ])
479+ and item and not _is_param_expr (item [0 ])):
480+ item = (list (item ),)
481+ item_len = len (item )
482+ if item_len != param_len :
483+ raise TypeError (f'Too { "many" if item_len > param_len else "few" } '
484+ f' arguments for { self } ;'
485+ f' actual { item_len } , expected { param_len } ' )
486+ subst = dict (zip (self .__parameters__ , item ))
487+ new_args = []
488+ for arg in self .__args__ :
489+ if _is_typevarlike (arg ):
490+ if _is_param_expr (arg ):
491+ arg = subst [arg ]
492+ if not _is_param_expr (arg ):
493+ raise TypeError (f"Expected a list of types, an ellipsis, "
494+ f"ParamSpec, or Concatenate. Got { arg } " )
495+ else :
496+ arg = subst [arg ]
497+ # Looks like a GenericAlias
498+ elif hasattr (arg , '__parameters__' ) and isinstance (arg .__parameters__ , tuple ):
499+ subparams = arg .__parameters__
500+ if subparams :
501+ subargs = tuple (subst [x ] for x in subparams )
502+ arg = arg [subargs ]
503+ new_args .append (arg )
504+
505+ # args[0] occurs due to things like Z[[int, str, bool]] from PEP 612
506+ if not isinstance (new_args [0 ], list ):
507+ t_result = new_args [- 1 ]
508+ t_args = new_args [:- 1 ]
509+ new_args = (t_args , t_result )
510+ return _CallableGenericAlias (Callable , tuple (new_args ))
511+
512+
513+ def _is_typevarlike (arg ):
514+ obj = type (arg )
515+ # looks like a TypeVar/ParamSpec
516+ return (obj .__module__ == 'typing'
517+ and obj .__name__ in {'ParamSpec' , 'TypeVar' })
518+
519+ def _is_param_expr (obj ):
520+ """Checks if obj matches either a list of types, ``...``, ``ParamSpec`` or
521+ ``_ConcatenateGenericAlias`` from typing.py
522+ """
523+ if obj is Ellipsis :
524+ return True
525+ if isinstance (obj , list ):
526+ return True
527+ obj = type (obj )
528+ names = ('ParamSpec' , '_ConcatenateGenericAlias' )
529+ return obj .__module__ == 'typing' and any (obj .__name__ == name for name in names )
476530
477531def _type_repr (obj ):
478532 """Return the repr() of an object, special-casing types (internal helper).
@@ -514,7 +568,6 @@ def __subclasshook__(cls, C):
514568
515569
516570class Set (Collection ):
517-
518571 """A set is a finite, iterable container.
519572
520573 This class provides concrete generic implementations of all
@@ -740,19 +793,19 @@ def __isub__(self, it):
740793
741794### MAPPINGS ###
742795
743-
744796class Mapping (Collection ):
745-
746- __slots__ = ()
747-
748797 """A Mapping is a generic container for associating key/value
749798 pairs.
750799
751800 This class provides concrete generic implementations of all
752801 methods except for __getitem__, __iter__, and __len__.
753-
754802 """
755803
804+ __slots__ = ()
805+
806+ # Tell ABCMeta.__new__ that this class should have TPFLAGS_MAPPING set.
807+ __abc_tpflags__ = 1 << 6 # Py_TPFLAGS_MAPPING
808+
756809 @abstractmethod
757810 def __getitem__ (self , key ):
758811 raise KeyError
@@ -791,7 +844,6 @@ def __eq__(self, other):
791844
792845 __reversed__ = None
793846
794-
795847Mapping .register (mappingproxy )
796848
797849
@@ -874,18 +926,16 @@ def __iter__(self):
874926
875927
876928class MutableMapping (Mapping ):
877-
878- __slots__ = ()
879-
880929 """A MutableMapping is a generic container for associating
881930 key/value pairs.
882931
883932 This class provides concrete generic implementations of all
884933 methods except for __getitem__, __setitem__, __delitem__,
885934 __iter__, and __len__.
886-
887935 """
888936
937+ __slots__ = ()
938+
889939 @abstractmethod
890940 def __setitem__ (self , key , value ):
891941 raise KeyError
@@ -962,9 +1012,7 @@ def setdefault(self, key, default=None):
9621012
9631013### SEQUENCES ###
9641014
965-
9661015class Sequence (Reversible , Collection ):
967-
9681016 """All the operations on a read-only sequence.
9691017
9701018 Concrete subclasses must override __new__ or __init__,
@@ -973,6 +1021,9 @@ class Sequence(Reversible, Collection):
9731021
9741022 __slots__ = ()
9751023
1024+ # Tell ABCMeta.__new__ that this class should have TPFLAGS_SEQUENCE set.
1025+ __abc_tpflags__ = 1 << 5 # Py_TPFLAGS_SEQUENCE
1026+
9761027 @abstractmethod
9771028 def __getitem__ (self , index ):
9781029 raise IndexError
@@ -1024,15 +1075,13 @@ def count(self, value):
10241075 'S.count(value) -> integer -- return number of occurrences of value'
10251076 return sum (1 for v in self if v is value or v == value )
10261077
1027-
10281078Sequence .register (tuple )
10291079Sequence .register (str )
10301080Sequence .register (range )
10311081Sequence .register (memoryview )
10321082
10331083
10341084class ByteString (Sequence ):
1035-
10361085 """This unifies bytes and bytearray.
10371086
10381087 XXX Should add all their methods.
@@ -1045,16 +1094,14 @@ class ByteString(Sequence):
10451094
10461095
10471096class MutableSequence (Sequence ):
1048-
1049- __slots__ = ()
1050-
10511097 """All the operations on a read-write sequence.
10521098
10531099 Concrete subclasses must provide __new__ or __init__,
10541100 __getitem__, __setitem__, __delitem__, __len__, and insert().
1055-
10561101 """
10571102
1103+ __slots__ = ()
1104+
10581105 @abstractmethod
10591106 def __setitem__ (self , index , value ):
10601107 raise IndexError
0 commit comments