5
5
import re
6
6
import sys
7
7
from unittest import TestCase , main , SkipTest
8
+ from copy import copy , deepcopy
8
9
9
10
from typing import Any
10
11
from typing import TypeVar , AnyStr
@@ -141,8 +142,9 @@ def test_union_unique(self):
141
142
self .assertEqual (Union [X , X ], X )
142
143
self .assertNotEqual (Union [X , int ], Union [X ])
143
144
self .assertNotEqual (Union [X , int ], Union [int ])
144
- self .assertEqual (Union [X , int ].__union_params__ , (X , int ))
145
- self .assertEqual (Union [X , int ].__union_set_params__ , {X , int })
145
+ self .assertEqual (Union [X , int ].__args__ , (X , int ))
146
+ self .assertEqual (Union [X , int ].__parameters__ , (X ,))
147
+ self .assertIs (Union [X , int ].__origin__ , Union )
146
148
147
149
def test_union_constrained (self ):
148
150
A = TypeVar ('A' , str , bytes )
@@ -308,8 +310,6 @@ def Elem(*args):
308
310
class TupleTests (BaseTestCase ):
309
311
310
312
def test_basics (self ):
311
- with self .assertRaises (TypeError ):
312
- issubclass (Tuple [int , str ], Tuple )
313
313
with self .assertRaises (TypeError ):
314
314
issubclass (Tuple , Tuple [int , str ])
315
315
with self .assertRaises (TypeError ):
@@ -364,22 +364,6 @@ def test_eq_hash(self):
364
364
self .assertNotEqual (Callable [[int ], int ], Callable [[], int ])
365
365
self .assertNotEqual (Callable [[int ], int ], Callable )
366
366
367
- def test_cannot_subclass (self ):
368
- with self .assertRaises (TypeError ):
369
-
370
- class C (Callable ):
371
- pass
372
-
373
- with self .assertRaises (TypeError ):
374
-
375
- class C (type (Callable )):
376
- pass
377
-
378
- with self .assertRaises (TypeError ):
379
-
380
- class C (Callable [[int ], int ]):
381
- pass
382
-
383
367
def test_cannot_instantiate (self ):
384
368
with self .assertRaises (TypeError ):
385
369
Callable ()
@@ -506,6 +490,9 @@ def test_basics(self):
506
490
Y [unicode , unicode ]
507
491
508
492
def test_generic_errors (self ):
493
+ T = TypeVar ('T' )
494
+ with self .assertRaises (TypeError ):
495
+ Generic [T ]()
509
496
with self .assertRaises (TypeError ):
510
497
isinstance ([], List [int ])
511
498
with self .assertRaises (TypeError ):
@@ -683,6 +670,124 @@ class D(C, List[T][U][V]): pass
683
670
self .assertEqual (C .__orig_bases__ , (List [T ][U ][V ],))
684
671
self .assertEqual (D .__orig_bases__ , (C , List [T ][U ][V ]))
685
672
673
+ def test_extended_generic_rules_eq (self ):
674
+ T = TypeVar ('T' )
675
+ U = TypeVar ('U' )
676
+ self .assertEqual (Tuple [T , T ][int ], Tuple [int , int ])
677
+ self .assertEqual (typing .Iterable [Tuple [T , T ]][T ], typing .Iterable [Tuple [T , T ]])
678
+ with self .assertRaises (TypeError ):
679
+ Tuple [T , int ][()]
680
+ with self .assertRaises (TypeError ):
681
+ Tuple [T , U ][T , ...]
682
+
683
+ self .assertEqual (Union [T , int ][int ], int )
684
+ self .assertEqual (Union [T , U ][int , Union [int , str ]], Union [int , str ])
685
+ class Base (object ): pass
686
+ class Derived (Base ): pass
687
+ self .assertEqual (Union [T , Base ][Derived ], Base )
688
+ with self .assertRaises (TypeError ):
689
+ Union [T , int ][1 ]
690
+
691
+ self .assertEqual (Callable [[T ], T ][KT ], Callable [[KT ], KT ])
692
+ self .assertEqual (Callable [..., List [T ]][int ], Callable [..., List [int ]])
693
+ with self .assertRaises (TypeError ):
694
+ Callable [[T ], U ][..., int ]
695
+ with self .assertRaises (TypeError ):
696
+ Callable [[T ], U ][[], int ]
697
+
698
+ def test_extended_generic_rules_repr (self ):
699
+ T = TypeVar ('T' )
700
+ self .assertEqual (repr (Union [Tuple , Callable ]).replace ('typing.' , '' ),
701
+ 'Union[Tuple, Callable]' )
702
+ self .assertEqual (repr (Union [Tuple , Tuple [int ]]).replace ('typing.' , '' ),
703
+ 'Tuple' )
704
+ self .assertEqual (repr (Callable [..., Optional [T ]][int ]).replace ('typing.' , '' ),
705
+ 'Callable[..., Union[int, NoneType]]' )
706
+ self .assertEqual (repr (Callable [[], List [T ]][int ]).replace ('typing.' , '' ),
707
+ 'Callable[[], List[int]]' )
708
+
709
+ def test_generic_forvard_ref (self ):
710
+ LLT = List [List ['T' ]]
711
+ T = TypeVar ('T' )
712
+ self .assertEqual (typing ._eval_type (LLT , globals (), locals ()), List [List [T ]])
713
+ TTE = Tuple [T , ...]
714
+ self .assertIs (typing ._eval_type (TTE , globals (), locals ()), Tuple [T , ...])
715
+
716
+ def test_extended_generic_rules_subclassing (self ):
717
+ class T1 (Tuple [T , KT ]): pass
718
+ class T2 (Tuple [T , ...]): pass
719
+ class C1 (Callable [[T ], T ]): pass
720
+ class C2 (Callable [..., int ]):
721
+ def __call__ (self ):
722
+ return None
723
+
724
+ self .assertEqual (T1 .__parameters__ , (T , KT ))
725
+ self .assertEqual (T1 [int , str ].__args__ , (int , str ))
726
+ self .assertEqual (T1 [int , T ].__origin__ , T1 )
727
+
728
+ self .assertEqual (T2 .__parameters__ , (T ,))
729
+ with self .assertRaises (TypeError ):
730
+ T1 [int ]
731
+ with self .assertRaises (TypeError ):
732
+ T2 [int , str ]
733
+
734
+ self .assertEqual (repr (C1 [int ]).split ('.' )[- 1 ], 'C1[int]' )
735
+ self .assertEqual (C2 .__parameters__ , ())
736
+ self .assertIsInstance (C2 (), collections_abc .Callable )
737
+ self .assertIsSubclass (C2 , collections_abc .Callable )
738
+ self .assertIsSubclass (C1 , collections_abc .Callable )
739
+ self .assertIsInstance (T1 (), tuple )
740
+ self .assertIsSubclass (T2 , tuple )
741
+ self .assertIsSubclass (Tuple [int , ...], typing .Sequence )
742
+ self .assertIsSubclass (Tuple [int , ...], typing .Iterable )
743
+
744
+ def test_fail_with_bare_union (self ):
745
+ with self .assertRaises (TypeError ):
746
+ List [Union ]
747
+ with self .assertRaises (TypeError ):
748
+ Tuple [Optional ]
749
+ with self .assertRaises (TypeError ):
750
+ ClassVar [ClassVar ]
751
+ with self .assertRaises (TypeError ):
752
+ List [ClassVar [int ]]
753
+
754
+ def test_fail_with_bare_generic (self ):
755
+ T = TypeVar ('T' )
756
+ with self .assertRaises (TypeError ):
757
+ List [Generic ]
758
+ with self .assertRaises (TypeError ):
759
+ Tuple [Generic [T ]]
760
+ with self .assertRaises (TypeError ):
761
+ List [typing ._Protocol ]
762
+
763
+ def test_type_erasure_special (self ):
764
+ T = TypeVar ('T' )
765
+ class MyTup (Tuple [T , T ]): pass
766
+ self .assertIs (MyTup [int ]().__class__ , MyTup )
767
+ self .assertIs (MyTup [int ]().__orig_class__ , MyTup [int ])
768
+ class MyCall (Callable [..., T ]):
769
+ def __call__ (self ): return None
770
+ self .assertIs (MyCall [T ]().__class__ , MyCall )
771
+ self .assertIs (MyCall [T ]().__orig_class__ , MyCall [T ])
772
+ class MyDict (typing .Dict [T , T ]): pass
773
+ self .assertIs (MyDict [int ]().__class__ , MyDict )
774
+ self .assertIs (MyDict [int ]().__orig_class__ , MyDict [int ])
775
+ class MyDef (typing .DefaultDict [str , T ]): pass
776
+ self .assertIs (MyDef [int ]().__class__ , MyDef )
777
+ self .assertIs (MyDef [int ]().__orig_class__ , MyDef [int ])
778
+
779
+ def test_all_repr_eq_any (self ):
780
+ objs = (getattr (typing , el ) for el in typing .__all__ )
781
+ for obj in objs :
782
+ self .assertNotEqual (repr (obj ), '' )
783
+ self .assertEqual (obj , obj )
784
+ if getattr (obj , '__parameters__' , None ) and len (obj .__parameters__ ) == 1 :
785
+ self .assertEqual (obj [Any ].__args__ , (Any ,))
786
+ if isinstance (obj , type ):
787
+ for base in obj .__mro__ :
788
+ self .assertNotEqual (repr (base ), '' )
789
+ self .assertEqual (base , base )
790
+
686
791
def test_pickle (self ):
687
792
global C # pickle wants to reference the class by name
688
793
T = TypeVar ('T' )
@@ -702,6 +807,24 @@ class C(B[int]):
702
807
self .assertEqual (x .foo , 42 )
703
808
self .assertEqual (x .bar , 'abc' )
704
809
self .assertEqual (x .__dict__ , {'foo' : 42 , 'bar' : 'abc' })
810
+ simples = [Any , Union , Tuple , Callable , ClassVar , List , typing .Iterable ]
811
+ for s in simples :
812
+ for proto in range (pickle .HIGHEST_PROTOCOL + 1 ):
813
+ z = pickle .dumps (s , proto )
814
+ x = pickle .loads (z )
815
+ self .assertEqual (s , x )
816
+
817
+ def test_copy_and_deepcopy (self ):
818
+ T = TypeVar ('T' )
819
+ class Node (Generic [T ]): pass
820
+ things = [Any , Union [T , int ], Tuple [T , int ], Callable [..., T ], Callable [[int ], int ],
821
+ Tuple [Any , Any ], Node [T ], Node [int ], Node [Any ], typing .Iterable [T ],
822
+ typing .Iterable [Any ], typing .Iterable [int ], typing .Dict [int , str ],
823
+ typing .Dict [T , Any ], ClassVar [int ], ClassVar [List [T ]], Tuple ['T' , 'T' ],
824
+ Union ['T' , int ], List ['T' ], typing .Mapping ['T' , int ]]
825
+ for t in things :
826
+ self .assertEqual (t , deepcopy (t ))
827
+ self .assertEqual (t , copy (t ))
705
828
706
829
def test_errors (self ):
707
830
with self .assertRaises (TypeError ):
@@ -724,7 +847,7 @@ class C(Generic[T]):
724
847
X = C [int ]
725
848
self .assertEqual (X .__module__ , __name__ )
726
849
if not PY32 :
727
- self .assertEqual (X .__qualname__ , 'C' )
850
+ self .assertTrue (X .__qualname__ . endswith ( '.<locals>.C' ) )
728
851
self .assertEqual (repr (X ).split ('.' )[- 1 ], 'C[int]' )
729
852
730
853
class Y (C [int ]):
0 commit comments