@@ -531,6 +531,14 @@ def test_pickle(self):
531531 pickled = pickle .dumps (self .bottom_type , protocol = proto )
532532 self .assertIs (self .bottom_type , pickle .loads (pickled ))
533533
534+ @skipUnless (TYPING_3_10_0 , "PEP 604 has yet to be" )
535+ def test_or (self ):
536+ self .assertEqual (self .bottom_type | int , Union [self .bottom_type , int ])
537+ self .assertEqual (int | self .bottom_type , Union [int , self .bottom_type ])
538+
539+ self .assertEqual (get_args (self .bottom_type | int ), (self .bottom_type , int ))
540+ self .assertEqual (get_args (int | self .bottom_type ), (int , self .bottom_type ))
541+
534542
535543class NoReturnTests (BottomTypeTestsMixin , BaseTestCase ):
536544 bottom_type = NoReturn
@@ -2210,6 +2218,39 @@ def test_or_and_ror(self):
22102218 Union [typing_extensions .Generator , typing .Deque ]
22112219 )
22122220
2221+ def test_setattr (self ):
2222+ origin = collections .abc .Generator
2223+ alias = typing_extensions .Generator
2224+ original_name = alias ._name
2225+
2226+ def cleanup ():
2227+ for obj in origin , alias :
2228+ for attr in 'foo' , '__dunder__' :
2229+ try :
2230+ delattr (obj , attr )
2231+ except Exception :
2232+ pass
2233+ try :
2234+ alias ._name = original_name
2235+ except Exception :
2236+ pass
2237+
2238+ self .addCleanup (cleanup )
2239+
2240+ # Attribute assignment on generic alias sets attribute on origin
2241+ alias .foo = 1
2242+ self .assertEqual (alias .foo , 1 )
2243+ self .assertEqual (origin .foo , 1 )
2244+ # Except for dunders...
2245+ alias .__dunder__ = 2
2246+ self .assertEqual (alias .__dunder__ , 2 )
2247+ self .assertRaises (AttributeError , lambda : origin .__dunder__ )
2248+
2249+ # ...and certain known attributes
2250+ alias ._name = "NewName"
2251+ self .assertEqual (alias ._name , "NewName" )
2252+ self .assertRaises (AttributeError , lambda : origin ._name )
2253+
22132254
22142255class OtherABCTests (BaseTestCase ):
22152256
@@ -2379,6 +2420,16 @@ def test_error_message_when_subclassing(self):
23792420 class ProUserId (UserId ):
23802421 ...
23812422
2423+ def test_module_with_incomplete_sys (self ):
2424+ def does_not_exist (* args ):
2425+ raise AttributeError
2426+ with (
2427+ patch ("sys._getframemodulename" , does_not_exist , create = True ),
2428+ patch ("sys._getframe" , does_not_exist , create = True ),
2429+ ):
2430+ X = NewType ("X" , int )
2431+ self .assertEqual (X .__module__ , None )
2432+
23822433
23832434class Coordinate (Protocol ):
23842435 x : int
@@ -5297,6 +5348,17 @@ class A(TypedDict):
52975348 def test_dunder_dict (self ):
52985349 self .assertIsInstance (TypedDict .__dict__ , dict )
52995350
5351+ @skipUnless (TYPING_3_10_0 , "PEP 604 has yet to be" )
5352+ def test_or (self ):
5353+ class TD (TypedDict ):
5354+ a : int
5355+
5356+ self .assertEqual (TD | int , Union [TD , int ])
5357+ self .assertEqual (int | TD , Union [int , TD ])
5358+
5359+ self .assertEqual (get_args (TD | int ), (TD , int ))
5360+ self .assertEqual (get_args (int | TD ), (int , TD ))
5361+
53005362class AnnotatedTests (BaseTestCase ):
53015363
53025364 def test_repr (self ):
@@ -5519,6 +5581,19 @@ def barfoo3(x: BA2): ...
55195581 BA2
55205582 )
55215583
5584+ @skipUnless (TYPING_3_11_0 , "TODO: evaluate nested forward refs in Python < 3.11" )
5585+ def test_get_type_hints_genericalias (self ):
5586+ def foobar (x : list ['X' ]): ...
5587+ X = Annotated [int , (1 , 10 )]
5588+ self .assertEqual (
5589+ get_type_hints (foobar , globals (), locals ()),
5590+ {'x' : list [int ]}
5591+ )
5592+ self .assertEqual (
5593+ get_type_hints (foobar , globals (), locals (), include_extras = True ),
5594+ {'x' : list [Annotated [int , (1 , 10 )]]}
5595+ )
5596+
55225597 def test_get_type_hints_refs (self ):
55235598
55245599 Const = Annotated [T , "Const" ]
@@ -5973,6 +6048,11 @@ def run():
59736048 # The actual test:
59746049 self .assertEqual (result1 , result2 )
59756050
6051+ def test_subclass (self ):
6052+ with self .assertRaises (TypeError ):
6053+ class MyParamSpec (ParamSpec ):
6054+ pass
6055+
59766056
59776057class ConcatenateTests (BaseTestCase ):
59786058 def test_basics (self ):
@@ -6335,6 +6415,14 @@ def test_pickle(self):
63356415 pickled = pickle .dumps (LiteralString , protocol = proto )
63366416 self .assertIs (LiteralString , pickle .loads (pickled ))
63376417
6418+ @skipUnless (TYPING_3_10_0 , "PEP 604 has yet to be" )
6419+ def test_or (self ):
6420+ self .assertEqual (LiteralString | int , Union [LiteralString , int ])
6421+ self .assertEqual (int | LiteralString , Union [int , LiteralString ])
6422+
6423+ self .assertEqual (get_args (LiteralString | int ), (LiteralString , int ))
6424+ self .assertEqual (get_args (int | LiteralString ), (int , LiteralString ))
6425+
63386426
63396427class SelfTests (BaseTestCase ):
63406428 def test_basics (self ):
@@ -6382,6 +6470,14 @@ def test_pickle(self):
63826470 pickled = pickle .dumps (Self , protocol = proto )
63836471 self .assertIs (Self , pickle .loads (pickled ))
63846472
6473+ @skipUnless (TYPING_3_10_0 , "PEP 604 has yet to be" )
6474+ def test_or (self ):
6475+ self .assertEqual (Self | int , Union [Self , int ])
6476+ self .assertEqual (int | Self , Union [int , Self ])
6477+
6478+ self .assertEqual (get_args (Self | int ), (Self , int ))
6479+ self .assertEqual (get_args (int | Self ), (int , Self ))
6480+
63856481
63866482class UnpackTests (BaseTestCase ):
63876483 def test_basic_plain (self ):
@@ -7711,42 +7807,61 @@ class A(Generic[T, P, U]): ...
77117807 self .assertEqual (A [float , [range ], int ].__args__ , (float , (range ,), int ))
77127808
77137809
7714- class NoDefaultTests ( BaseTestCase ) :
7810+ class SentinelTestsMixin :
77157811 @skip_if_py313_beta_1
77167812 def test_pickling (self ):
77177813 for proto in range (pickle .HIGHEST_PROTOCOL + 1 ):
7718- s = pickle .dumps (NoDefault , proto )
7814+ s = pickle .dumps (self . sentinel_type , proto )
77197815 loaded = pickle .loads (s )
7720- self .assertIs (NoDefault , loaded )
7816+ self .assertIs (self . sentinel_type , loaded )
77217817
77227818 @skip_if_py313_beta_1
77237819 def test_doc (self ):
7724- self .assertIsInstance (NoDefault .__doc__ , str )
7820+ self .assertIsInstance (self . sentinel_type .__doc__ , str )
77257821
77267822 def test_constructor (self ):
7727- self .assertIs (NoDefault , type (NoDefault )())
7823+ self .assertIs (self . sentinel_type , type (self . sentinel_type )())
77287824 with self .assertRaises (TypeError ):
7729- type (NoDefault )(1 )
7730-
7731- def test_repr (self ):
7732- self .assertRegex (repr (NoDefault ), r'typing(_extensions)?\.NoDefault' )
7825+ type (self .sentinel_type )(1 )
77337826
77347827 def test_no_call (self ):
77357828 with self .assertRaises (TypeError ):
7736- NoDefault ()
7829+ self . sentinel_type ()
77377830
77387831 @skip_if_py313_beta_1
77397832 def test_immutable (self ):
77407833 with self .assertRaises (AttributeError ):
7741- NoDefault .foo = 'bar'
7834+ self . sentinel_type .foo = 'bar'
77427835 with self .assertRaises (AttributeError ):
7743- NoDefault .foo
7836+ self . sentinel_type .foo
77447837
77457838 # TypeError is consistent with the behavior of NoneType
77467839 with self .assertRaises (TypeError ):
7747- type(NoDefault ).foo = 3
7840+ type(self . sentinel_type ).foo = 3
77487841 with self .assertRaises (AttributeError ):
7749- type (NoDefault ).foo
7842+ type (self .sentinel_type ).foo
7843+
7844+
7845+ class NoDefaultTests (SentinelTestsMixin , BaseTestCase ):
7846+ sentinel_type = NoDefault
7847+
7848+ def test_repr (self ):
7849+ if hasattr (typing , 'NoDefault' ):
7850+ mod_name = 'typing'
7851+ else :
7852+ mod_name = "typing_extensions"
7853+ self .assertEqual (repr (NoDefault ), f"{ mod_name } .NoDefault" )
7854+
7855+
7856+ class NoExtraItemsTests (SentinelTestsMixin , BaseTestCase ):
7857+ sentinel_type = NoExtraItems
7858+
7859+ def test_repr (self ):
7860+ if hasattr (typing , 'NoExtraItems' ):
7861+ mod_name = 'typing'
7862+ else :
7863+ mod_name = "typing_extensions"
7864+ self .assertEqual (repr (NoExtraItems ), f"{ mod_name } .NoExtraItems" )
77507865
77517866
77527867class TypeVarInferVarianceTests (BaseTestCase ):
0 commit comments