2727
2828 # ABCs (from collections.abc).
2929 'AbstractSet' , # collections.abc.Set.
30+ 'GenericMeta' , # subclass of abc.ABCMeta and a metaclass
31+ # for 'Generic' and ABCs below.
3032 'ByteString' ,
3133 'Container' ,
3234 'Hashable' ,
@@ -145,7 +147,7 @@ def __repr__(self):
145147class _TypingBase (metaclass = TypingMeta , _root = True ):
146148 """Internal indicator of special typing constructs."""
147149
148- __slots__ = ()
150+ __slots__ = ('__weakref__' , )
149151
150152 def __init__ (self , * args , ** kwds ):
151153 pass
@@ -514,7 +516,7 @@ def _replace_arg(arg, tvars, args):
514516
515517 if tvars is None :
516518 tvars = []
517- if hasattr (arg , '_subs_tree' ):
519+ if hasattr (arg , '_subs_tree' ) and isinstance ( arg , ( GenericMeta , _TypingBase )) :
518520 return arg ._subs_tree (tvars , args )
519521 if isinstance (arg , TypeVar ):
520522 for i , tvar in enumerate (tvars ):
@@ -523,6 +525,16 @@ def _replace_arg(arg, tvars, args):
523525 return arg
524526
525527
528+ # Special typing constructs Union, Optional, Generic, Callable and Tuple
529+ # use three special attributes for internal bookkeeping of generic types:
530+ # * __parameters__ is a tuple of unique free type parameters of a generic
531+ # type, for example, Dict[T, T].__parameters__ == (T,);
532+ # * __origin__ keeps a reference to a type that was subscripted,
533+ # e.g., Union[T, int].__origin__ == Union;
534+ # * __args__ is a tuple of all arguments used in subscripting,
535+ # e.g., Dict[T, int].__args__ == (T, int).
536+
537+
526538def _subs_tree (cls , tvars = None , args = None ):
527539 """An internal helper function: calculate substitution tree
528540 for generic cls after replacing its type parameters with
@@ -757,9 +769,12 @@ def _subs_tree(self, tvars=None, args=None):
757769 return (Union ,) + tree_args
758770
759771 def __eq__ (self , other ):
760- if not isinstance (other , _Union ):
772+ if isinstance (other , _Union ):
773+ return self .__tree_hash__ == other .__tree_hash__
774+ elif self is not Union :
761775 return self ._subs_tree () == other
762- return self .__tree_hash__ == other .__tree_hash__
776+ else :
777+ return self is other
763778
764779 def __hash__ (self ):
765780 return self .__tree_hash__
@@ -883,10 +898,26 @@ def _no_slots_copy(dct):
883898
884899
885900class GenericMeta (TypingMeta , abc .ABCMeta ):
886- """Metaclass for generic types."""
901+ """Metaclass for generic types.
902+
903+ This is a metaclass for typing.Generic and generic ABCs defined in
904+ typing module. User defined subclasses of GenericMeta can override
905+ __new__ and invoke super().__new__. Note that GenericMeta.__new__
906+ has strict rules on what is allowed in its bases argument:
907+ * plain Generic is disallowed in bases;
908+ * Generic[...] should appear in bases at most once;
909+ * if Generic[...] is present, then it should list all type variables
910+ that appear in other bases.
911+ In addition, type of all generic bases is erased, e.g., C[int] is
912+ stripped to plain C.
913+ """
887914
888915 def __new__ (cls , name , bases , namespace ,
889916 tvars = None , args = None , origin = None , extra = None , orig_bases = None ):
917+ """Create a new generic class. GenericMeta.__new__ accepts
918+ keyword arguments that are used for internal bookkeeping, therefore
919+ an override should pass unused keyword arguments to super().
920+ """
890921 if tvars is not None :
891922 # Called from __getitem__() below.
892923 assert origin is not None
@@ -1906,7 +1937,9 @@ def _make_nmtuple(name, types):
19061937 msg = "NamedTuple('Name', [(f0, t0), (f1, t1), ...]); each t must be a type"
19071938 types = [(n , _type_check (t , msg )) for n , t in types ]
19081939 nm_tpl = collections .namedtuple (name , [n for n , t in types ])
1909- nm_tpl ._field_types = dict (types )
1940+ # Prior to PEP 526, only _field_types attribute was assigned.
1941+ # Now, both __annotations__ and _field_types are used to maintain compatibility.
1942+ nm_tpl .__annotations__ = nm_tpl ._field_types = collections .OrderedDict (types )
19101943 try :
19111944 nm_tpl .__module__ = sys ._getframe (2 ).f_globals .get ('__name__' , '__main__' )
19121945 except (AttributeError , ValueError ):
@@ -1941,8 +1974,10 @@ class Employee(NamedTuple):
19411974
19421975 Employee = collections.namedtuple('Employee', ['name', 'id'])
19431976
1944- The resulting class has one extra attribute: _field_types,
1945- giving a dict mapping field names to types. (The field names
1977+ The resulting class has extra __annotations__ and _field_types
1978+ attributes, giving an ordered dict mapping field names to types.
1979+ __annotations__ should be preferred, while _field_types
1980+ is kept to maintain pre PEP 526 compatibility. (The field names
19461981 are in the _fields attribute, which is part of the namedtuple
19471982 API.) Alternative equivalent keyword syntax is also accepted::
19481983
0 commit comments