@@ -1809,12 +1809,14 @@ class C(Generic[T]): pass
18091809 # In 3.9 and lower we use typing_extensions's hacky implementation
18101810 # of ParamSpec, which gets incorrectly wrapped in a list
18111811 self .assertIn (get_args (Callable [P , int ]), [(P , int ), ([P ], int )])
1812- self .assertEqual (get_args (Callable [Concatenate [int , P ], int ]),
1813- (Concatenate [int , P ], int ))
18141812 self .assertEqual (get_args (Required [int ]), (int ,))
18151813 self .assertEqual (get_args (NotRequired [int ]), (int ,))
18161814 self .assertEqual (get_args (Unpack [Ts ]), (Ts ,))
18171815 self .assertEqual (get_args (Unpack ), ())
1816+ self .assertEqual (get_args (Callable [Concatenate [int , P ], int ]),
1817+ (Concatenate [int , P ], int ))
1818+ self .assertEqual (get_args (Callable [Concatenate [int , ...], int ]),
1819+ (Concatenate [int , ...], int ))
18181820
18191821
18201822class CollectionsAbcTests (BaseTestCase ):
@@ -5356,6 +5358,10 @@ class Y(Protocol[T, P]):
53565358 self .assertEqual (G2 .__args__ , (int , Concatenate [int , P_2 ]))
53575359 self .assertEqual (G2 .__parameters__ , (P_2 ,))
53585360
5361+ G3 = klass [int , Concatenate [int , ...]]
5362+ self .assertEqual (G3 .__args__ , (int , Concatenate [int , ...]))
5363+ self .assertEqual (G3 .__parameters__ , ())
5364+
53595365 # The following are some valid uses cases in PEP 612 that don't work:
53605366 # These do not work in 3.9, _type_check blocks the list and ellipsis.
53615367 # G3 = X[int, [int, bool]]
@@ -5451,21 +5457,28 @@ class MyClass: ...
54515457 c = Concatenate [MyClass , P ]
54525458 self .assertNotEqual (c , Concatenate )
54535459
5460+ # Test Ellipsis Concatenation
5461+ d = Concatenate [MyClass , ...]
5462+ self .assertNotEqual (d , c )
5463+ self .assertNotEqual (d , Concatenate )
5464+
54545465 def test_valid_uses (self ):
54555466 P = ParamSpec ('P' )
54565467 T = TypeVar ('T' )
5468+ for callable_variant in (Callable , collections .abc .Callable ):
5469+ with self .subTest (callable_variant = callable_variant ):
5470+ if not TYPING_3_9_0 and callable_variant is collections .abc .Callable :
5471+ self .skipTest ("Needs PEP 585" )
54575472
5458- C1 = Callable [Concatenate [int , P ], int ]
5459- C2 = Callable [Concatenate [int , T , P ], T ]
5460- self .assertEqual (C1 .__origin__ , C2 .__origin__ )
5461- self .assertNotEqual (C1 , C2 )
5473+ C1 = callable_variant [Concatenate [int , P ], int ]
5474+ C2 = callable_variant [Concatenate [int , T , P ], T ]
5475+ self .assertEqual (C1 .__origin__ , C2 .__origin__ )
5476+ self .assertNotEqual (C1 , C2 )
54625477
5463- # Test collections.abc.Callable too.
5464- if sys .version_info [:2 ] >= (3 , 9 ):
5465- C3 = collections .abc .Callable [Concatenate [int , P ], int ]
5466- C4 = collections .abc .Callable [Concatenate [int , T , P ], T ]
5467- self .assertEqual (C3 .__origin__ , C4 .__origin__ )
5468- self .assertNotEqual (C3 , C4 )
5478+ C3 = callable_variant [Concatenate [int , ...], int ]
5479+ C4 = callable_variant [Concatenate [int , T , ...], T ]
5480+ self .assertEqual (C3 .__origin__ , C4 .__origin__ )
5481+ self .assertNotEqual (C3 , C4 )
54695482
54705483 def test_invalid_uses (self ):
54715484 P = ParamSpec ('P' )
@@ -5479,25 +5492,54 @@ def test_invalid_uses(self):
54795492
54805493 with self .assertRaisesRegex (
54815494 TypeError ,
5482- 'The last parameter to Concatenate should be a ParamSpec variable' ,
5495+ 'The last parameter to Concatenate should be a ParamSpec variable or ellipsis ' ,
54835496 ):
54845497 Concatenate [P , T ]
54855498
5486- if not TYPING_3_11_0 :
5487- with self .assertRaisesRegex (
5488- TypeError ,
5489- 'each arg must be a type' ,
5490- ):
5491- Concatenate [1 , P ]
5499+ # Test with tuple argument
5500+ with self .assertRaisesRegex (
5501+ TypeError ,
5502+ "The last parameter to Concatenate should be a ParamSpec variable or ellipsis." ,
5503+ ):
5504+ Concatenate [(P , T )]
5505+
5506+ with self .assertRaisesRegex (
5507+ TypeError ,
5508+ 'is not a generic class' ,
5509+ ):
5510+ Callable [Concatenate [int , ...], Any ][Any ]
5511+
5512+ # Assure that `_type_check` is called.
5513+ P = ParamSpec ('P' )
5514+ with self .assertRaisesRegex (
5515+ TypeError ,
5516+ "each arg must be a type" ,
5517+ ):
5518+ Concatenate [(str ,), P ]
5519+
5520+ @skipUnless (TYPING_3_10_0 , "Missing backport to <=3.9. See issue #48" )
5521+ def test_alias_subscription_with_ellipsis (self ):
5522+ P = ParamSpec ('P' )
5523+ X = Callable [Concatenate [int , P ], Any ]
5524+
5525+ C1 = X [...]
5526+ self .assertEqual (C1 .__parameters__ , ())
5527+ self .assertEqual (get_args (C1 ), (Concatenate [int , ...], Any ))
54925528
54935529 def test_basic_introspection (self ):
54945530 P = ParamSpec ('P' )
54955531 C1 = Concatenate [int , P ]
54965532 C2 = Concatenate [int , T , P ]
5533+ C3 = Concatenate [int , ...]
5534+ C4 = Concatenate [int , T , ...]
54975535 self .assertEqual (C1 .__origin__ , Concatenate )
54985536 self .assertEqual (C1 .__args__ , (int , P ))
54995537 self .assertEqual (C2 .__origin__ , Concatenate )
55005538 self .assertEqual (C2 .__args__ , (int , T , P ))
5539+ self .assertEqual (C3 .__origin__ , Concatenate )
5540+ self .assertEqual (C3 .__args__ , (int , Ellipsis ))
5541+ self .assertEqual (C4 .__origin__ , Concatenate )
5542+ self .assertEqual (C4 .__args__ , (int , T , Ellipsis ))
55015543
55025544 def test_eq (self ):
55035545 P = ParamSpec ('P' )
@@ -5508,6 +5550,13 @@ def test_eq(self):
55085550 self .assertEqual (hash (C1 ), hash (C2 ))
55095551 self .assertNotEqual (C1 , C3 )
55105552
5553+ C4 = Concatenate [int , ...]
5554+ C5 = Concatenate [int , ...]
5555+ C6 = Concatenate [int , T , ...]
5556+ self .assertEqual (C4 , C5 )
5557+ self .assertEqual (hash (C4 ), hash (C5 ))
5558+ self .assertNotEqual (C4 , C6 )
5559+
55115560
55125561class TypeGuardTests (BaseTestCase ):
55135562 def test_basics (self ):
@@ -6219,7 +6268,7 @@ def test_typing_extensions_defers_when_possible(self):
62196268 if sys .version_info < (3 , 10 , 1 ):
62206269 exclude |= {"Literal" }
62216270 if sys .version_info < (3 , 11 ):
6222- exclude |= {'final' , 'Any' , 'NewType' , 'overload' }
6271+ exclude |= {'final' , 'Any' , 'NewType' , 'overload' , 'Concatenate' }
62236272 if sys .version_info < (3 , 12 ):
62246273 exclude |= {
62256274 'SupportsAbs' , 'SupportsBytes' ,
0 commit comments