@@ -1765,6 +1765,19 @@ def __call__(self, *args, **kwargs):
17651765# 3.8-3.9
17661766if not hasattr (typing , 'Concatenate' ):
17671767 # Inherits from list as a workaround for Callable checks in Python < 3.9.2.
1768+
1769+ #3.9.0-1
1770+ if not hasattr (typing , '_type_convert' ):
1771+ def _type_convert (arg , module = None , * , allow_special_forms = False ):
1772+ """For converting None to type(None), and strings to ForwardRef."""
1773+ if arg is None :
1774+ return type (None )
1775+ if isinstance (arg , str ):
1776+ return ForwardRef (arg , module = module , is_class = allow_special_forms )
1777+ return arg
1778+ else :
1779+ _type_convert = typing ._type_convert
1780+
17681781 class _ConcatenateGenericAlias (list ):
17691782
17701783 # Trick Generic into looking into this for __parameters__.
@@ -1797,16 +1810,66 @@ def __parameters__(self):
17971810 )
17981811
17991812 # 3.8; needed for typing._subs_tvars
1800- if sys .version_info < (3 , 9 ):
1801- def copy_with (self , params ):
1802- if isinstance (params [- 1 ], (list , tuple )):
1803- return (* params [:- 1 ], * params [- 1 ])
1804- if isinstance (params [- 1 ], _ConcatenateGenericAlias ):
1805- params = (* params [:- 1 ], * params [- 1 ].__args__ )
1806- elif not (params [- 1 ] is ... or isinstance (params [- 1 ], ParamSpec )):
1807- raise TypeError ("The last parameter to Concatenate should be a "
1808- "ParamSpec variable or ellipsis." )
1809- return self .__class__ (self .__origin__ , params )
1813+ # 3.9 used by __getitem__ below
1814+ def copy_with (self , params ):
1815+ if isinstance (params [- 1 ], (list , tuple )):
1816+ return (* params [:- 1 ], * params [- 1 ])
1817+ if isinstance (params [- 1 ], _ConcatenateGenericAlias ):
1818+ params = (* params [:- 1 ], * params [- 1 ].__args__ )
1819+ elif (not (params [- 1 ] is ... or isinstance (params [- 1 ], ParamSpec ))):
1820+ raise TypeError ("The last parameter to Concatenate should be a "
1821+ "ParamSpec variable or ellipsis." )
1822+ return self .__class__ (self .__origin__ , params )
1823+
1824+ # 3.9; accessed during GenericAlias.__getitem__when substituting
1825+ def __getitem__ (self , args ):
1826+ if self .__origin__ in (Generic , Protocol ):
1827+ # Can't subscript Generic[...] or Protocol[...].
1828+ raise TypeError (f"Cannot subscript already-subscripted { self } " )
1829+ if not self .__parameters__ :
1830+ raise TypeError (f"{ self } is not a generic class" )
1831+
1832+ if not isinstance (args , tuple ):
1833+ args = (args ,)
1834+ args = _unpack_args (* (_type_convert (p ) for p in args ))
1835+ params = self .__parameters__
1836+ for param in params :
1837+ if isinstance (param , ParamSpec ):
1838+ i = params .index (param )
1839+ if (
1840+ i == len (args )
1841+ and getattr (param , '__default__' , NoDefault ) is not NoDefault
1842+ ):
1843+ args = [* args , param .__default__ ]
1844+ if i >= len (args ):
1845+ raise TypeError (f"Too few arguments for { self } " )
1846+ # Special case for Z[[int, str, bool]] == Z[int, str, bool]
1847+ if len (params ) == 1 and not _is_param_expr (args [0 ]):
1848+ assert i == 0
1849+ args = (args ,)
1850+ # Convert lists to tuples to help other libraries cache the results.
1851+ elif isinstance (args [i ], list ):
1852+ args = (* args [:i ], tuple (args [i ]), * args [i + 1 :])
1853+
1854+ subst = dict (zip (self .__parameters__ , args ))
1855+ # determine new args
1856+ new_args = []
1857+ for arg in self .__args__ :
1858+ if isinstance (arg , type ):
1859+ new_args .append (arg )
1860+ continue
1861+ if isinstance (arg , TypeVar ):
1862+ arg = subst [arg ]
1863+ elif isinstance (arg ,
1864+ typing ._GenericAlias
1865+ if not hasattr (_types , "GenericAlias" ) else
1866+ (typing ._GenericAlias , _types .GenericAlias )):
1867+ subparams = arg .__parameters__
1868+ if subparams :
1869+ subargs = tuple (subst [x ] for x in subparams )
1870+ arg = arg [subargs ]
1871+ new_args .append (arg )
1872+ return self .copy_with (tuple (new_args ))
18101873
18111874# 3.10+
18121875else :
@@ -1830,6 +1893,12 @@ def copy_with(self, params):
18301893 "ParamSpec variable or ellipsis." )
18311894 return super (_typing_ConcatenateGenericAlias , self ).copy_with (params )
18321895
1896+ def __getitem__ (self , args ):
1897+ value = super ().__getitem__ (args )
1898+ if isinstance (value , tuple ) and any (_is_unpack (t ) for t in value ):
1899+ return tuple (_unpack_args (* (n for n in value )))
1900+ return value
1901+
18331902
18341903# 3.8-3.9.2
18351904class _EllipsisDummy : ...
@@ -2509,6 +2578,21 @@ def _is_unpack(obj):
25092578 class _UnpackAlias (typing ._GenericAlias , _root = True ):
25102579 __class__ = typing .TypeVar
25112580
2581+ def _typing_unpacked_tuple_args (self ):
2582+ assert self .__origin__ is Unpack
2583+ assert len (self .__args__ ) == 1
2584+ arg , = self .__args__
2585+ if isinstance (arg , typing ._GenericAlias ):
2586+ if arg .__origin__ is not tuple :
2587+ raise TypeError ("Unpack[...] must be used with a tuple type" )
2588+ return arg .__args__
2589+ return None
2590+
2591+ def __getattr__ (self , attr ):
2592+ if attr == '__typing_unpacked_tuple_args__' :
2593+ return self ._typing_unpacked_tuple_args ()
2594+ return super ().__getattr__ (attr )
2595+
25122596 @property
25132597 def __typing_is_unpacked_typevartuple__ (self ):
25142598 assert self .__origin__ is Unpack
@@ -2532,21 +2616,21 @@ def _is_unpack(obj):
25322616 return isinstance (obj , _UnpackAlias )
25332617
25342618
2619+ def _unpack_args (* args ):
2620+ newargs = []
2621+ for arg in args :
2622+ subargs = getattr (arg , '__typing_unpacked_tuple_args__' , None )
2623+ if subargs is not None and (not (subargs and subargs [- 1 ] is ...)):
2624+ newargs .extend (subargs )
2625+ else :
2626+ newargs .append (arg )
2627+ return newargs
2628+
25352629if _PEP_696_IMPLEMENTED :
25362630 from typing import TypeVarTuple
25372631
25382632elif hasattr (typing , "TypeVarTuple" ): # 3.11+
25392633
2540- def _unpack_args (* args ):
2541- newargs = []
2542- for arg in args :
2543- subargs = getattr (arg , '__typing_unpacked_tuple_args__' , None )
2544- if subargs is not None and not (subargs and subargs [- 1 ] is ...):
2545- newargs .extend (subargs )
2546- else :
2547- newargs .append (arg )
2548- return newargs
2549-
25502634 # Add default parameter - PEP 696
25512635 class TypeVarTuple (metaclass = _TypeVarLikeMeta ):
25522636 """Type variable tuple."""
0 commit comments