@@ -411,6 +411,10 @@ def test_cannot_be_called(self):
411411
412412class TypeVarTupleTests (BaseTestCase ):
413413
414+ def assertEndsWith (self , string , tail ):
415+ if not string .endswith (tail ):
416+ self .fail (f"String { string !r} does not end with { tail !r} " )
417+
414418 def test_instance_is_equal_to_itself (self ):
415419 Ts = TypeVarTuple ('Ts' )
416420 self .assertEqual (Ts , Ts )
@@ -457,6 +461,56 @@ def test_tuple_args_and_parameters_are_correct(self):
457461 self .assertEqual (t2 .__args__ , (Unpack [Ts ],))
458462 self .assertEqual (t2 .__parameters__ , (Ts ,))
459463
464+ def test_var_substitution (self ):
465+ Ts = TypeVarTuple ('Ts' )
466+ T = TypeVar ('T' )
467+ T2 = TypeVar ('T2' )
468+ class G (Generic [Unpack [Ts ]]): pass
469+
470+ for A in G , Tuple :
471+ B = A [Unpack [Ts ]]
472+ if A != Tuple :
473+ self .assertEqual (B [()], A [()])
474+ self .assertEqual (B [float ], A [float ])
475+ self .assertEqual (B [float , str ], A [float , str ])
476+
477+ C = List [A [Unpack [Ts ]]]
478+ if A != Tuple :
479+ self .assertEqual (C [()], List [A [()]])
480+ self .assertEqual (C [float ], List [A [float ]])
481+ self .assertEqual (C [float , str ], List [A [float , str ]])
482+
483+ D = A [T , Unpack [Ts ], T2 ]
484+ with self .assertRaises (TypeError ):
485+ D [()]
486+ with self .assertRaises (TypeError ):
487+ D [float ]
488+ self .assertEqual (D [float , str ], A [float , str ])
489+ self .assertEqual (D [float , str , int ], A [float , str , int ])
490+ self .assertEqual (D [float , str , int , bytes ], A [float , str , int , bytes ])
491+
492+ E = Tuple [List [T ], A [Unpack [Ts ]], List [T2 ]]
493+ with self .assertRaises (TypeError ):
494+ E [()]
495+ with self .assertRaises (TypeError ):
496+ E [float ]
497+ if A != Tuple :
498+ self .assertEqual (E [float , str ],
499+ Tuple [List [float ], A [()], List [str ]])
500+ self .assertEqual (E [float , str , int ],
501+ Tuple [List [float ], A [str ], List [int ]])
502+ self .assertEqual (E [float , str , int , bytes ],
503+ Tuple [List [float ], A [str , int ], List [bytes ]])
504+
505+ def test_repr_is_correct (self ):
506+ Ts = TypeVarTuple ('Ts' )
507+ self .assertEqual (repr (Ts ), 'Ts' )
508+ self .assertEqual (repr (Unpack [Ts ]), '*Ts' )
509+ self .assertEqual (repr (tuple [Unpack [Ts ]]), 'tuple[*Ts]' )
510+ self .assertEqual (repr (Tuple [Unpack [Ts ]]), 'typing.Tuple[*Ts]' )
511+ self .assertEqual (repr (Unpack [tuple [Unpack [Ts ]]]), '*tuple[*Ts]' )
512+ self .assertEqual (repr (Unpack [Tuple [Unpack [Ts ]]]), '*typing.Tuple[*Ts]' )
513+
460514 def test_repr_is_correct (self ):
461515 Ts = TypeVarTuple ('Ts' )
462516 self .assertEqual (repr (Ts ), 'Ts' )
@@ -470,78 +524,51 @@ def test_variadic_class_repr_is_correct(self):
470524 Ts = TypeVarTuple ('Ts' )
471525 class A (Generic [Unpack [Ts ]]): pass
472526
473- self .assertTrue (repr (A [()]).endswith ('A[()]' ))
474- self .assertTrue (repr (A [float ]).endswith ('A[float]' ))
475- self .assertTrue (repr (A [float , str ]).endswith ('A[float, str]' ))
476- self .assertTrue (repr (
477- A [Unpack [tuple [int , ...]]]
478- ).endswith (
479- 'A[*tuple[int, ...]]'
480- ))
481- self .assertTrue (repr (
482- A [float , Unpack [tuple [int , ...]]]
483- ).endswith (
484- 'A[float, *tuple[int, ...]]'
485- ))
486- self .assertTrue (repr (
487- A [Unpack [tuple [int , ...]], str ]
488- ).endswith (
489- 'A[*tuple[int, ...], str]'
490- ))
491- self .assertTrue (repr (
492- A [float , Unpack [tuple [int , ...]], str ]
493- ).endswith (
494- 'A[float, *tuple[int, ...], str]'
495- ))
527+ self .assertEndsWith (repr (A [()]), 'A[()]' )
528+ self .assertEndsWith (repr (A [float ]), 'A[float]' )
529+ self .assertEndsWith (repr (A [float , str ]), 'A[float, str]' )
530+ self .assertEndsWith (repr (A [Unpack [tuple [int , ...]]]),
531+ 'A[*tuple[int, ...]]' )
532+ self .assertEndsWith (repr (A [float , Unpack [tuple [int , ...]]]),
533+ 'A[float, *tuple[int, ...]]' )
534+ self .assertEndsWith (repr (A [Unpack [tuple [int , ...]], str ]),
535+ 'A[*tuple[int, ...], str]' )
536+ self .assertEndsWith (repr (A [float , Unpack [tuple [int , ...]], str ]),
537+ 'A[float, *tuple[int, ...], str]' )
496538
497539 def test_variadic_class_alias_repr_is_correct (self ):
498540 Ts = TypeVarTuple ('Ts' )
499541 class A (Generic [Unpack [Ts ]]): pass
500542
501543 B = A [Unpack [Ts ]]
502- self .assertTrue (repr (B ).endswith ('A[*Ts]' ))
503- with self .assertRaises (NotImplementedError ):
504- B [()]
505- with self .assertRaises (NotImplementedError ):
506- B [float ]
507- with self .assertRaises (NotImplementedError ):
508- B [float , str ]
544+ self .assertEndsWith (repr (B ), 'A[*Ts]' )
545+ self .assertEndsWith (repr (B [()]), 'A[()]' )
546+ self .assertEndsWith (repr (B [float ]), 'A[float]' )
547+ self .assertEndsWith (repr (B [float , str ]), 'A[float, str]' )
509548
510549 C = A [Unpack [Ts ], int ]
511- self .assertTrue (repr (C ).endswith ('A[*Ts, int]' ))
512- with self .assertRaises (NotImplementedError ):
513- C [()]
514- with self .assertRaises (NotImplementedError ):
515- C [float ]
516- with self .assertRaises (NotImplementedError ):
517- C [float , str ]
550+ self .assertEndsWith (repr (C ), 'A[*Ts, int]' )
551+ self .assertEndsWith (repr (C [()]), 'A[int]' )
552+ self .assertEndsWith (repr (C [float ]), 'A[float, int]' )
553+ self .assertEndsWith (repr (C [float , str ]), 'A[float, str, int]' )
518554
519555 D = A [int , Unpack [Ts ]]
520- self .assertTrue (repr (D ).endswith ('A[int, *Ts]' ))
521- with self .assertRaises (NotImplementedError ):
522- D [()]
523- with self .assertRaises (NotImplementedError ):
524- D [float ]
525- with self .assertRaises (NotImplementedError ):
526- D [float , str ]
556+ self .assertEndsWith (repr (D ), 'A[int, *Ts]' )
557+ self .assertEndsWith (repr (D [()]), 'A[int]' )
558+ self .assertEndsWith (repr (D [float ]), 'A[int, float]' )
559+ self .assertEndsWith (repr (D [float , str ]), 'A[int, float, str]' )
527560
528561 E = A [int , Unpack [Ts ], str ]
529- self .assertTrue (repr (E ).endswith ('A[int, *Ts, str]' ))
530- with self .assertRaises (NotImplementedError ):
531- E [()]
532- with self .assertRaises (NotImplementedError ):
533- E [float ]
534- with self .assertRaises (NotImplementedError ):
535- E [float , bool ]
562+ self .assertEndsWith (repr (E ), 'A[int, *Ts, str]' )
563+ self .assertEndsWith (repr (E [()]), 'A[int, str]' )
564+ self .assertEndsWith (repr (E [float ]), 'A[int, float, str]' )
565+ self .assertEndsWith (repr (E [float , str ]), 'A[int, float, str, str]' )
536566
537567 F = A [Unpack [Ts ], Unpack [tuple [str , ...]]]
538- self .assertTrue (repr (F ).endswith ('A[*Ts, *tuple[str, ...]]' ))
539- with self .assertRaises (NotImplementedError ):
540- F [()]
541- with self .assertRaises (NotImplementedError ):
542- F [float ]
543- with self .assertRaises (NotImplementedError ):
544- F [float , int ]
568+ self .assertEndsWith (repr (F ), 'A[*Ts, *tuple[str, ...]]' )
569+ self .assertEndsWith (repr (F [()]), 'A[*tuple[str, ...]]' )
570+ self .assertEndsWith (repr (F [float ]), 'A[float, *tuple[str, ...]]' )
571+ self .assertEndsWith (repr (F [float , str ]), 'A[float, str, *tuple[str, ...]]' )
545572
546573 def test_cannot_subclass_class (self ):
547574 with self .assertRaises (TypeError ):
0 commit comments