@@ -1681,12 +1681,16 @@ class C(Generic[T]): pass
16811681 # In 3.9 and lower we use typing_extensions's hacky implementation
16821682 # of ParamSpec, which gets incorrectly wrapped in a list
16831683 self .assertIn (get_args (Callable [P , int ]), [(P , int ), ([P ], int )])
1684- self .assertEqual (get_args (Callable [Concatenate [int , P ], int ]),
1685- (Concatenate [int , P ], int ))
16861684 self .assertEqual (get_args (Required [int ]), (int ,))
16871685 self .assertEqual (get_args (NotRequired [int ]), (int ,))
16881686 self .assertEqual (get_args (Unpack [Ts ]), (Ts ,))
16891687 self .assertEqual (get_args (Unpack ), ())
1688+ self .assertEqual (get_args (Callable [Concatenate [int , P ], int ]),
1689+ (Concatenate [int , P ], int ))
1690+ if sys .version_info >= (3 , 9 ):
1691+ # Cannot construct Callable[Concatenate[int, ...] with non-types
1692+ self .assertEqual (get_args (Callable [Concatenate [int , ...], int ]),
1693+ (Concatenate [int , ...], int ))
16901694
16911695
16921696class CollectionsAbcTests (BaseTestCase ):
@@ -5228,6 +5232,10 @@ class Y(Protocol[T, P]):
52285232 self .assertEqual (G2 .__args__ , (int , Concatenate [int , P_2 ]))
52295233 self .assertEqual (G2 .__parameters__ , (P_2 ,))
52305234
5235+ G3 = klass [int , Concatenate [int , ...]]
5236+ self .assertEqual (G3 .__args__ , (int , Concatenate [int , ...]))
5237+ self .assertEqual (G3 .__parameters__ , ())
5238+
52315239 # The following are some valid uses cases in PEP 612 that don't work:
52325240 # These do not work in 3.9, _type_check blocks the list and ellipsis.
52335241 # G3 = X[int, [int, bool]]
@@ -5323,6 +5331,11 @@ class MyClass: ...
53235331 c = Concatenate [MyClass , P ]
53245332 self .assertNotEqual (c , Concatenate )
53255333
5334+ # Test Ellipsis Concatenation
5335+ d = Concatenate [MyClass , ...]
5336+ self .assertNotEqual (d , c )
5337+ self .assertNotEqual (d , Concatenate )
5338+
53265339 def test_valid_uses (self ):
53275340 P = ParamSpec ('P' )
53285341 T = TypeVar ('T' )
@@ -5339,6 +5352,21 @@ def test_valid_uses(self):
53395352 self .assertEqual (C3 .__origin__ , C4 .__origin__ )
53405353 self .assertNotEqual (C3 , C4 )
53415354
5355+ # Callable with Ellipsis cannot be constructed in Python3.8
5356+ if sys .version_info [:2 ] <= (3 , 8 ):
5357+ return
5358+
5359+ C5 = Callable [Concatenate [int , ...], int ]
5360+ C6 = Callable [Concatenate [int , T , ...], T ]
5361+ self .assertEqual (C5 .__origin__ , C6 .__origin__ )
5362+ self .assertNotEqual (C5 , C6 )
5363+
5364+ # Test collections.abc.Callable too.
5365+ C7 = collections .abc .Callable [Concatenate [int , ...], int ]
5366+ C8 = collections .abc .Callable [Concatenate [int , T , ...], T ]
5367+ self .assertEqual (C7 .__origin__ , C8 .__origin__ )
5368+ self .assertNotEqual (C7 , C8 )
5369+
53425370 def test_invalid_uses (self ):
53435371 P = ParamSpec ('P' )
53445372 T = TypeVar ('T' )
@@ -5351,25 +5379,58 @@ def test_invalid_uses(self):
53515379
53525380 with self .assertRaisesRegex (
53535381 TypeError ,
5354- 'The last parameter to Concatenate should be a ParamSpec variable' ,
5382+ 'The last parameter to Concatenate should be a ParamSpec variable or ellipsis ' ,
53555383 ):
53565384 Concatenate [P , T ]
53575385
5386+
5387+ if sys .version_info [:2 ] >= (3 , 9 ):
5388+ # Cannot construct a Callable with Ellipsis in Python3.8 as args must be types
5389+ with self .assertRaisesRegex (
5390+ TypeError ,
5391+ 'is not a generic class' ,
5392+ ):
5393+ Callable [Concatenate [int , ...], Any ][T ]
5394+
5395+
53585396 if not TYPING_3_11_0 :
53595397 with self .assertRaisesRegex (
53605398 TypeError ,
53615399 'each arg must be a type' ,
53625400 ):
53635401 Concatenate [1 , P ]
53645402
5403+ with self .assertRaisesRegex (
5404+ TypeError ,
5405+ 'each arg must be a type.' ,
5406+ ):
5407+ Concatenate [1 , ..., P ]
5408+
5409+ @skipUnless (TYPING_3_11_0 , "Cannot be backported to <=3.9"
5410+ "Cannot use typing._ConcatenateGenericAlias in 3.10" )
5411+ def test_alias (self ):
5412+ P = ParamSpec ("P" )
5413+ C1 = Callable [Concatenate [int , P ], Any ]
5414+ # Python <= 3.9 fails because parameters to generic types must be types.
5415+ # For Python 3.10 & typing._ConcatenateGenericAlias will
5416+ # as Ellipsis is not supported for ParamSpec
5417+ # Fallback to 3.10 & typing_extensions._ConcatenateGenericAlias not implemented
5418+ C1 [...]
5419+
53655420 def test_basic_introspection (self ):
53665421 P = ParamSpec ('P' )
53675422 C1 = Concatenate [int , P ]
53685423 C2 = Concatenate [int , T , P ]
5424+ C3 = Concatenate [int , ...]
5425+ C4 = Concatenate [int , T , ...]
53695426 self .assertEqual (C1 .__origin__ , Concatenate )
53705427 self .assertEqual (C1 .__args__ , (int , P ))
53715428 self .assertEqual (C2 .__origin__ , Concatenate )
53725429 self .assertEqual (C2 .__args__ , (int , T , P ))
5430+ self .assertEqual (C3 .__origin__ , Concatenate )
5431+ self .assertEqual (C3 .__args__ , (int , Ellipsis ))
5432+ self .assertEqual (C4 .__origin__ , Concatenate )
5433+ self .assertEqual (C4 .__args__ , (int , T , Ellipsis ))
53735434
53745435 def test_eq (self ):
53755436 P = ParamSpec ('P' )
@@ -5380,6 +5441,13 @@ def test_eq(self):
53805441 self .assertEqual (hash (C1 ), hash (C2 ))
53815442 self .assertNotEqual (C1 , C3 )
53825443
5444+ C4 = Concatenate [int , ...]
5445+ C5 = Concatenate [int , ...]
5446+ C6 = Concatenate [int , T , ...]
5447+ self .assertEqual (C4 , C5 )
5448+ self .assertEqual (hash (C4 ), hash (C5 ))
5449+ self .assertNotEqual (C4 , C6 )
5450+
53835451
53845452class TypeGuardTests (BaseTestCase ):
53855453 def test_basics (self ):
@@ -6050,7 +6118,7 @@ def test_typing_extensions_defers_when_possible(self):
60506118 if sys .version_info < (3 , 10 , 1 ):
60516119 exclude |= {"Literal" }
60526120 if sys .version_info < (3 , 11 ):
6053- exclude |= {'final' , 'Any' , 'NewType' , 'overload' }
6121+ exclude |= {'final' , 'Any' , 'NewType' , 'overload' , 'Concatenate' }
60546122 if sys .version_info < (3 , 12 ):
60556123 exclude |= {
60566124 'SupportsAbs' , 'SupportsBytes' ,
0 commit comments