@@ -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 , 2 ):
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 3.8 and below 3.9.2
5356+ if sys .version_info [:2 ] <= (3 , 9 , 2 ):
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,56 @@ 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+ # Cannot construct a Callable with Ellipsis in 3.8 as args must be types
5387+ if sys .version_info [:2 ] >= (3 , 9 , 2 ):
5388+ with self .assertRaisesRegex (
5389+ TypeError ,
5390+ 'is not a generic class' ,
5391+ ):
5392+ Callable [Concatenate [int , ...], Any ][T ]
5393+
53585394 if not TYPING_3_11_0 :
53595395 with self .assertRaisesRegex (
53605396 TypeError ,
53615397 'each arg must be a type' ,
53625398 ):
53635399 Concatenate [1 , P ]
53645400
5401+ with self .assertRaisesRegex (
5402+ TypeError ,
5403+ 'each arg must be a type.' ,
5404+ ):
5405+ Concatenate [1 , ..., P ]
5406+
5407+ @skipUnless (TYPING_3_11_0 , "Cannot be backported to <=3.9"
5408+ "Cannot use ... with 3.10 typing._ConcatenateGenericAlias" )
5409+ def test_alias (self ):
5410+ P = ParamSpec ("P" )
5411+ C1 = Callable [Concatenate [int , P ], Any ]
5412+ # Python <= 3.9 fails because parameters to generic types must be types.
5413+ # For Python 3.10 & typing._ConcatenateGenericAlias will
5414+ # as Ellipsis is not supported for ParamSpec
5415+ # Fallback to 3.10 & typing_extensions._ConcatenateGenericAlias not implemented
5416+ C1 [...]
5417+
53655418 def test_basic_introspection (self ):
53665419 P = ParamSpec ('P' )
53675420 C1 = Concatenate [int , P ]
53685421 C2 = Concatenate [int , T , P ]
5422+ C3 = Concatenate [int , ...]
5423+ C4 = Concatenate [int , T , ...]
53695424 self .assertEqual (C1 .__origin__ , Concatenate )
53705425 self .assertEqual (C1 .__args__ , (int , P ))
53715426 self .assertEqual (C2 .__origin__ , Concatenate )
53725427 self .assertEqual (C2 .__args__ , (int , T , P ))
5428+ self .assertEqual (C3 .__origin__ , Concatenate )
5429+ self .assertEqual (C3 .__args__ , (int , Ellipsis ))
5430+ self .assertEqual (C4 .__origin__ , Concatenate )
5431+ self .assertEqual (C4 .__args__ , (int , T , Ellipsis ))
53735432
53745433 def test_eq (self ):
53755434 P = ParamSpec ('P' )
@@ -5380,6 +5439,13 @@ def test_eq(self):
53805439 self .assertEqual (hash (C1 ), hash (C2 ))
53815440 self .assertNotEqual (C1 , C3 )
53825441
5442+ C4 = Concatenate [int , ...]
5443+ C5 = Concatenate [int , ...]
5444+ C6 = Concatenate [int , T , ...]
5445+ self .assertEqual (C4 , C5 )
5446+ self .assertEqual (hash (C4 ), hash (C5 ))
5447+ self .assertNotEqual (C4 , C6 )
5448+
53835449
53845450class TypeGuardTests (BaseTestCase ):
53855451 def test_basics (self ):
@@ -6050,7 +6116,7 @@ def test_typing_extensions_defers_when_possible(self):
60506116 if sys .version_info < (3 , 10 , 1 ):
60516117 exclude |= {"Literal" }
60526118 if sys .version_info < (3 , 11 ):
6053- exclude |= {'final' , 'Any' , 'NewType' , 'overload' }
6119+ exclude |= {'final' , 'Any' , 'NewType' , 'overload' , 'Concatenate' }
60546120 if sys .version_info < (3 , 12 ):
60556121 exclude |= {
60566122 'SupportsAbs' , 'SupportsBytes' ,
0 commit comments