2
2
import collections
3
3
import collections .abc
4
4
from collections import defaultdict
5
- from functools import lru_cache , wraps
5
+ from functools import lru_cache , wraps , reduce
6
6
import gc
7
7
import inspect
8
8
import itertools
9
+ import operator
9
10
import pickle
10
11
import re
11
12
import sys
@@ -1769,6 +1770,26 @@ def test_union_union(self):
1769
1770
v = Union [u , Employee ]
1770
1771
self .assertEqual (v , Union [int , float , Employee ])
1771
1772
1773
+ def test_union_of_unhashable (self ):
1774
+ class UnhashableMeta (type ):
1775
+ __hash__ = None
1776
+
1777
+ class A (metaclass = UnhashableMeta ): ...
1778
+ class B (metaclass = UnhashableMeta ): ...
1779
+
1780
+ self .assertEqual (Union [A , B ].__args__ , (A , B ))
1781
+ union1 = Union [A , B ]
1782
+ with self .assertRaises (TypeError ):
1783
+ hash (union1 )
1784
+
1785
+ union2 = Union [int , B ]
1786
+ with self .assertRaises (TypeError ):
1787
+ hash (union2 )
1788
+
1789
+ union3 = Union [A , int ]
1790
+ with self .assertRaises (TypeError ):
1791
+ hash (union3 )
1792
+
1772
1793
def test_repr (self ):
1773
1794
self .assertEqual (repr (Union ), 'typing.Union' )
1774
1795
u = Union [Employee , int ]
@@ -5506,10 +5527,8 @@ def some(self):
5506
5527
self .assertFalse (hasattr (WithOverride .some , "__override__" ))
5507
5528
5508
5529
def test_multiple_decorators (self ):
5509
- import functools
5510
-
5511
5530
def with_wraps (f ): # similar to `lru_cache` definition
5512
- @functools . wraps (f )
5531
+ @wraps (f )
5513
5532
def wrapper (* args , ** kwargs ):
5514
5533
return f (* args , ** kwargs )
5515
5534
return wrapper
@@ -8524,6 +8543,76 @@ def test_flatten(self):
8524
8543
self .assertEqual (A .__metadata__ , (4 , 5 ))
8525
8544
self .assertEqual (A .__origin__ , int )
8526
8545
8546
+ def test_deduplicate_from_union (self ):
8547
+ # Regular:
8548
+ self .assertEqual (get_args (Annotated [int , 1 ] | int ),
8549
+ (Annotated [int , 1 ], int ))
8550
+ self .assertEqual (get_args (Union [Annotated [int , 1 ], int ]),
8551
+ (Annotated [int , 1 ], int ))
8552
+ self .assertEqual (get_args (Annotated [int , 1 ] | Annotated [int , 2 ] | int ),
8553
+ (Annotated [int , 1 ], Annotated [int , 2 ], int ))
8554
+ self .assertEqual (get_args (Union [Annotated [int , 1 ], Annotated [int , 2 ], int ]),
8555
+ (Annotated [int , 1 ], Annotated [int , 2 ], int ))
8556
+ self .assertEqual (get_args (Annotated [int , 1 ] | Annotated [str , 1 ] | int ),
8557
+ (Annotated [int , 1 ], Annotated [str , 1 ], int ))
8558
+ self .assertEqual (get_args (Union [Annotated [int , 1 ], Annotated [str , 1 ], int ]),
8559
+ (Annotated [int , 1 ], Annotated [str , 1 ], int ))
8560
+
8561
+ # Duplicates:
8562
+ self .assertEqual (Annotated [int , 1 ] | Annotated [int , 1 ] | int ,
8563
+ Annotated [int , 1 ] | int )
8564
+ self .assertEqual (Union [Annotated [int , 1 ], Annotated [int , 1 ], int ],
8565
+ Union [Annotated [int , 1 ], int ])
8566
+
8567
+ # Unhashable metadata:
8568
+ self .assertEqual (get_args (str | Annotated [int , {}] | Annotated [int , set ()] | int ),
8569
+ (str , Annotated [int , {}], Annotated [int , set ()], int ))
8570
+ self .assertEqual (get_args (Union [str , Annotated [int , {}], Annotated [int , set ()], int ]),
8571
+ (str , Annotated [int , {}], Annotated [int , set ()], int ))
8572
+ self .assertEqual (get_args (str | Annotated [int , {}] | Annotated [str , {}] | int ),
8573
+ (str , Annotated [int , {}], Annotated [str , {}], int ))
8574
+ self .assertEqual (get_args (Union [str , Annotated [int , {}], Annotated [str , {}], int ]),
8575
+ (str , Annotated [int , {}], Annotated [str , {}], int ))
8576
+
8577
+ self .assertEqual (get_args (Annotated [int , 1 ] | str | Annotated [str , {}] | int ),
8578
+ (Annotated [int , 1 ], str , Annotated [str , {}], int ))
8579
+ self .assertEqual (get_args (Union [Annotated [int , 1 ], str , Annotated [str , {}], int ]),
8580
+ (Annotated [int , 1 ], str , Annotated [str , {}], int ))
8581
+
8582
+ import dataclasses
8583
+ @dataclasses .dataclass
8584
+ class ValueRange :
8585
+ lo : int
8586
+ hi : int
8587
+ v = ValueRange (1 , 2 )
8588
+ self .assertEqual (get_args (Annotated [int , v ] | None ),
8589
+ (Annotated [int , v ], types .NoneType ))
8590
+ self .assertEqual (get_args (Union [Annotated [int , v ], None ]),
8591
+ (Annotated [int , v ], types .NoneType ))
8592
+ self .assertEqual (get_args (Optional [Annotated [int , v ]]),
8593
+ (Annotated [int , v ], types .NoneType ))
8594
+
8595
+ # Unhashable metadata duplicated:
8596
+ self .assertEqual (Annotated [int , {}] | Annotated [int , {}] | int ,
8597
+ Annotated [int , {}] | int )
8598
+ self .assertEqual (Annotated [int , {}] | Annotated [int , {}] | int ,
8599
+ int | Annotated [int , {}])
8600
+ self .assertEqual (Union [Annotated [int , {}], Annotated [int , {}], int ],
8601
+ Union [Annotated [int , {}], int ])
8602
+ self .assertEqual (Union [Annotated [int , {}], Annotated [int , {}], int ],
8603
+ Union [int , Annotated [int , {}]])
8604
+
8605
+ def test_order_in_union (self ):
8606
+ expr1 = Annotated [int , 1 ] | str | Annotated [str , {}] | int
8607
+ for args in itertools .permutations (get_args (expr1 )):
8608
+ with self .subTest (args = args ):
8609
+ self .assertEqual (expr1 , reduce (operator .or_ , args ))
8610
+
8611
+ expr2 = Union [Annotated [int , 1 ], str , Annotated [str , {}], int ]
8612
+ for args in itertools .permutations (get_args (expr2 )):
8613
+ with self .subTest (args = args ):
8614
+ self .assertEqual (expr2 , Union [args ])
8615
+
8527
8616
def test_specialize (self ):
8528
8617
L = Annotated [List [T ], "my decoration" ]
8529
8618
LI = Annotated [List [int ], "my decoration" ]
@@ -8544,6 +8633,16 @@ def test_hash_eq(self):
8544
8633
{Annotated [int , 4 , 5 ], Annotated [int , 4 , 5 ], Annotated [T , 4 , 5 ]},
8545
8634
{Annotated [int , 4 , 5 ], Annotated [T , 4 , 5 ]}
8546
8635
)
8636
+ # Unhashable `metadata` raises `TypeError`:
8637
+ a1 = Annotated [int , []]
8638
+ with self .assertRaises (TypeError ):
8639
+ hash (a1 )
8640
+
8641
+ class A :
8642
+ __hash__ = None
8643
+ a2 = Annotated [int , A ()]
8644
+ with self .assertRaises (TypeError ):
8645
+ hash (a2 )
8547
8646
8548
8647
def test_instantiate (self ):
8549
8648
class C :
0 commit comments