@@ -1720,12 +1720,14 @@ class C(Generic[T]): pass
17201720 # In 3.9 and lower we use typing_extensions's hacky implementation
17211721 # of ParamSpec, which gets incorrectly wrapped in a list
17221722 self .assertIn (get_args (Callable [P , int ]), [(P , int ), ([P ], int )])
1723- self .assertEqual (get_args (Callable [Concatenate [int , P ], int ]),
1724- (Concatenate [int , P ], int ))
17251723 self .assertEqual (get_args (Required [int ]), (int ,))
17261724 self .assertEqual (get_args (NotRequired [int ]), (int ,))
17271725 self .assertEqual (get_args (Unpack [Ts ]), (Ts ,))
17281726 self .assertEqual (get_args (Unpack ), ())
1727+ self .assertEqual (get_args (Callable [Concatenate [int , P ], int ]),
1728+ (Concatenate [int , P ], int ))
1729+ self .assertEqual (get_args (Callable [Concatenate [int , ...], int ]),
1730+ (Concatenate [int , ...], int ))
17291731
17301732
17311733class CollectionsAbcTests (BaseTestCase ):
@@ -5267,6 +5269,10 @@ class Y(Protocol[T, P]):
52675269 self .assertEqual (G2 .__args__ , (int , Concatenate [int , P_2 ]))
52685270 self .assertEqual (G2 .__parameters__ , (P_2 ,))
52695271
5272+ G3 = klass [int , Concatenate [int , ...]]
5273+ self .assertEqual (G3 .__args__ , (int , Concatenate [int , ...]))
5274+ self .assertEqual (G3 .__parameters__ , ())
5275+
52705276 # The following are some valid uses cases in PEP 612 that don't work:
52715277 # These do not work in 3.9, _type_check blocks the list and ellipsis.
52725278 # G3 = X[int, [int, bool]]
@@ -5362,21 +5368,28 @@ class MyClass: ...
53625368 c = Concatenate [MyClass , P ]
53635369 self .assertNotEqual (c , Concatenate )
53645370
5371+ # Test Ellipsis Concatenation
5372+ d = Concatenate [MyClass , ...]
5373+ self .assertNotEqual (d , c )
5374+ self .assertNotEqual (d , Concatenate )
5375+
53655376 def test_valid_uses (self ):
53665377 P = ParamSpec ('P' )
53675378 T = TypeVar ('T' )
5379+ for callable_variant in (Callable , collections .abc .Callable ):
5380+ with self .subTest (callable_variant = callable_variant ):
5381+ if not TYPING_3_9_0 and callable_variant is collections .abc .Callable :
5382+ self .skipTest ("Needs PEP 585" )
53685383
5369- C1 = Callable [Concatenate [int , P ], int ]
5370- C2 = Callable [Concatenate [int , T , P ], T ]
5371- self .assertEqual (C1 .__origin__ , C2 .__origin__ )
5372- self .assertNotEqual (C1 , C2 )
5384+ C1 = callable_variant [Concatenate [int , P ], int ]
5385+ C2 = callable_variant [Concatenate [int , T , P ], T ]
5386+ self .assertEqual (C1 .__origin__ , C2 .__origin__ )
5387+ self .assertNotEqual (C1 , C2 )
53735388
5374- # Test collections.abc.Callable too.
5375- if sys .version_info [:2 ] >= (3 , 9 ):
5376- C3 = collections .abc .Callable [Concatenate [int , P ], int ]
5377- C4 = collections .abc .Callable [Concatenate [int , T , P ], T ]
5378- self .assertEqual (C3 .__origin__ , C4 .__origin__ )
5379- self .assertNotEqual (C3 , C4 )
5389+ C3 = callable_variant [Concatenate [int , ...], int ]
5390+ C4 = callable_variant [Concatenate [int , T , ...], T ]
5391+ self .assertEqual (C3 .__origin__ , C4 .__origin__ )
5392+ self .assertNotEqual (C3 , C4 )
53805393
53815394 def test_invalid_uses (self ):
53825395 P = ParamSpec ('P' )
@@ -5390,16 +5403,30 @@ def test_invalid_uses(self):
53905403
53915404 with self .assertRaisesRegex (
53925405 TypeError ,
5393- 'The last parameter to Concatenate should be a ParamSpec variable' ,
5406+ 'The last parameter to Concatenate should be a ParamSpec variable or ellipsis ' ,
53945407 ):
53955408 Concatenate [P , T ]
53965409
5397- if not TYPING_3_11_0 :
5398- with self .assertRaisesRegex (
5399- TypeError ,
5400- 'each arg must be a type' ,
5401- ):
5402- Concatenate [1 , P ]
5410+ # Test with tuple argument
5411+ with self .assertRaisesRegex (
5412+ TypeError ,
5413+ "The last parameter to Concatenate should be a ParamSpec variable or ellipsis." ,
5414+ ):
5415+ Concatenate [(P , T )]
5416+
5417+ with self .assertRaisesRegex (
5418+ TypeError ,
5419+ 'is not a generic class' ,
5420+ ):
5421+ Callable [Concatenate [int , ...], Any ][Any ]
5422+
5423+ # Assure that `_type_check` is called.
5424+ P = ParamSpec ('P' )
5425+ with self .assertRaisesRegex (
5426+ TypeError ,
5427+ "each arg must be a type" ,
5428+ ):
5429+ Concatenate [(str ,), P ]
54035430
54045431 @skipUnless (TYPING_3_10_0 , "Missing backport to <=3.9. See issue #48" )
54055432 def test_alias_subscription_with_ellipsis (self ):
@@ -5408,19 +5435,22 @@ def test_alias_subscription_with_ellipsis(self):
54085435
54095436 C1 = X [...]
54105437 self .assertEqual (C1 .__parameters__ , ())
5411- with self .subTest ("Compare Concatenate[int, ...]" ):
5412- if sys .version_info [:2 ] == (3 , 10 ):
5413- self .skipTest ("Needs Issue #110 | PR #481: construct Concatenate with ..." )
5414- self .assertEqual (get_args (C1 ), (Concatenate [int , ...], Any ))
5438+ self .assertEqual (get_args (C1 ), (Concatenate [int , ...], Any ))
54155439
54165440 def test_basic_introspection (self ):
54175441 P = ParamSpec ('P' )
54185442 C1 = Concatenate [int , P ]
54195443 C2 = Concatenate [int , T , P ]
5444+ C3 = Concatenate [int , ...]
5445+ C4 = Concatenate [int , T , ...]
54205446 self .assertEqual (C1 .__origin__ , Concatenate )
54215447 self .assertEqual (C1 .__args__ , (int , P ))
54225448 self .assertEqual (C2 .__origin__ , Concatenate )
54235449 self .assertEqual (C2 .__args__ , (int , T , P ))
5450+ self .assertEqual (C3 .__origin__ , Concatenate )
5451+ self .assertEqual (C3 .__args__ , (int , Ellipsis ))
5452+ self .assertEqual (C4 .__origin__ , Concatenate )
5453+ self .assertEqual (C4 .__args__ , (int , T , Ellipsis ))
54245454
54255455 def test_eq (self ):
54265456 P = ParamSpec ('P' )
@@ -5431,6 +5461,13 @@ def test_eq(self):
54315461 self .assertEqual (hash (C1 ), hash (C2 ))
54325462 self .assertNotEqual (C1 , C3 )
54335463
5464+ C4 = Concatenate [int , ...]
5465+ C5 = Concatenate [int , ...]
5466+ C6 = Concatenate [int , T , ...]
5467+ self .assertEqual (C4 , C5 )
5468+ self .assertEqual (hash (C4 ), hash (C5 ))
5469+ self .assertNotEqual (C4 , C6 )
5470+
54345471
54355472class TypeGuardTests (BaseTestCase ):
54365473 def test_basics (self ):
0 commit comments