@@ -1683,6 +1683,8 @@ class C(Generic[T]): pass
1683
1683
self .assertIn (get_args (Callable [P , int ]), [(P , int ), ([P ], int )])
1684
1684
self .assertEqual (get_args (Callable [Concatenate [int , P ], int ]),
1685
1685
(Concatenate [int , P ], int ))
1686
+ self .assertEqual (get_args (Callable [Concatenate [int , ...], int ]),
1687
+ (Concatenate [int , ...], int ))
1686
1688
self .assertEqual (get_args (Required [int ]), (int ,))
1687
1689
self .assertEqual (get_args (NotRequired [int ]), (int ,))
1688
1690
self .assertEqual (get_args (Unpack [Ts ]), (Ts ,))
@@ -5322,6 +5324,11 @@ class MyClass: ...
5322
5324
5323
5325
c = Concatenate [MyClass , P ]
5324
5326
self .assertNotEqual (c , Concatenate )
5327
+
5328
+ # Test Ellipsis Concatenation
5329
+ d = Concatenate [MyClass , ...]
5330
+ self .assertNotEqual (d , c )
5331
+ self .assertNotEqual (d , Concatenate )
5325
5332
5326
5333
def test_valid_uses (self ):
5327
5334
P = ParamSpec ('P' )
@@ -5338,6 +5345,18 @@ def test_valid_uses(self):
5338
5345
C4 = collections .abc .Callable [Concatenate [int , T , P ], T ]
5339
5346
self .assertEqual (C3 .__origin__ , C4 .__origin__ )
5340
5347
self .assertNotEqual (C3 , C4 )
5348
+
5349
+ C5 = Callable [Concatenate [int , ...], int ]
5350
+ C6 = Callable [Concatenate [int , T , ...], T ]
5351
+ self .assertEqual (C5 .__origin__ , C6 .__origin__ )
5352
+ self .assertNotEqual (C5 , C6 )
5353
+
5354
+ # Test collections.abc.Callable too.
5355
+ if sys .version_info [:2 ] >= (3 , 9 ):
5356
+ C7 = collections .abc .Callable [Concatenate [int , ...], int ]
5357
+ C8 = collections .abc .Callable [Concatenate [int , T , ...], T ]
5358
+ self .assertEqual (C7 .__origin__ , C8 .__origin__ )
5359
+ self .assertNotEqual (C7 , C8 )
5341
5360
5342
5361
def test_invalid_uses (self ):
5343
5362
P = ParamSpec ('P' )
@@ -5351,7 +5370,7 @@ def test_invalid_uses(self):
5351
5370
5352
5371
with self .assertRaisesRegex (
5353
5372
TypeError ,
5354
- 'The last parameter to Concatenate should be a ParamSpec variable' ,
5373
+ 'The last parameter to Concatenate should be a ParamSpec variable or ellipsis ' ,
5355
5374
):
5356
5375
Concatenate [P , T ]
5357
5376
@@ -5361,15 +5380,27 @@ def test_invalid_uses(self):
5361
5380
'each arg must be a type' ,
5362
5381
):
5363
5382
Concatenate [1 , P ]
5383
+
5384
+ with self .assertRaisesRegex (
5385
+ TypeError ,
5386
+ 'each arg must be a type.' ,
5387
+ ):
5388
+ Concatenate [1 , ..., P ]
5364
5389
5365
5390
def test_basic_introspection (self ):
5366
5391
P = ParamSpec ('P' )
5367
5392
C1 = Concatenate [int , P ]
5368
5393
C2 = Concatenate [int , T , P ]
5394
+ C3 = Concatenate [int , ...]
5395
+ C4 = Concatenate [int , T , ...]
5369
5396
self .assertEqual (C1 .__origin__ , Concatenate )
5370
5397
self .assertEqual (C1 .__args__ , (int , P ))
5371
5398
self .assertEqual (C2 .__origin__ , Concatenate )
5372
5399
self .assertEqual (C2 .__args__ , (int , T , P ))
5400
+ self .assertEqual (C3 .__origin__ , Concatenate )
5401
+ self .assertEqual (C3 .__args__ , (int , Ellipsis ))
5402
+ self .assertEqual (C4 .__origin__ , Concatenate )
5403
+ self .assertEqual (C4 .__args__ , (int , T , Ellipsis ))
5373
5404
5374
5405
def test_eq (self ):
5375
5406
P = ParamSpec ('P' )
@@ -5379,6 +5410,13 @@ def test_eq(self):
5379
5410
self .assertEqual (C1 , C2 )
5380
5411
self .assertEqual (hash (C1 ), hash (C2 ))
5381
5412
self .assertNotEqual (C1 , C3 )
5413
+
5414
+ C4 = Concatenate [int , ...]
5415
+ C5 = Concatenate [int , ...]
5416
+ C6 = Concatenate [int , T , ...]
5417
+ self .assertEqual (C4 , C5 )
5418
+ self .assertEqual (hash (C4 ), hash (C5 ))
5419
+ self .assertNotEqual (C4 , C6 )
5382
5420
5383
5421
5384
5422
class TypeGuardTests (BaseTestCase ):
@@ -6050,7 +6088,7 @@ def test_typing_extensions_defers_when_possible(self):
6050
6088
if sys .version_info < (3 , 10 , 1 ):
6051
6089
exclude |= {"Literal" }
6052
6090
if sys .version_info < (3 , 11 ):
6053
- exclude |= {'final' , 'Any' , 'NewType' , 'overload' }
6091
+ exclude |= {'final' , 'Any' , 'NewType' , 'overload' , 'Concatenate' }
6054
6092
if sys .version_info < (3 , 12 ):
6055
6093
exclude |= {
6056
6094
'SupportsAbs' , 'SupportsBytes' ,
0 commit comments