@@ -2254,6 +2254,52 @@ def test_asynccontextmanager_type_params(self):
22542254 cm2 = typing_extensions .AsyncContextManager [int , None ]
22552255 self .assertEqual (get_args (cm2 ), (int , NoneType ))
22562256
2257+ def test_setattr (self ):
2258+ if hasattr (typing_extensions , "_SpecialGenericAlias" ):
2259+ mod = typing_extensions
2260+ else :
2261+ mod = typing
2262+ class Foo :
2263+ _name = "Foo"
2264+ Alias = mod ._SpecialGenericAlias (Foo , 1 )
2265+
2266+ # Attribute assignment on generic alias sets attribute on origin
2267+ Alias .foo = 1
2268+ self .assertEqual (Alias .foo , 1 )
2269+ self .assertEqual (Foo .foo , 1 )
2270+
2271+ # Except for dunders...
2272+ Alias .__dunder__ = 2
2273+ self .assertEqual (Alias .__dunder__ , 2 )
2274+ with self .assertRaises (AttributeError ):
2275+ Foo .__dunder__
2276+
2277+ # ...and certain known attributes
2278+ Alias ._name = "NewName"
2279+ self .assertEqual (Alias ._name , "NewName" )
2280+ self .assertEqual (Foo ._name , "Foo" )
2281+
2282+ def test_invalid_specialization (self ):
2283+ if hasattr (typing_extensions , "_SpecialGenericAlias" ):
2284+ mod = typing_extensions
2285+ else :
2286+ mod = typing
2287+ class Foo : ...
2288+ Alias = mod ._SpecialGenericAlias (Foo , 2 )
2289+
2290+ msg = re .escape ("Too few arguments for typing.Foo; actual 1, expected 2" )
2291+ with self .assertRaisesRegex (TypeError , msg ):
2292+ Alias [int ]
2293+
2294+ msg = re .escape ("Too many arguments for typing.Foo; actual 3, expected 2" )
2295+ with self .assertRaisesRegex (TypeError , msg ):
2296+ Alias [int , int , int ]
2297+
2298+ Alias0 = mod ._SpecialGenericAlias (Foo , 0 )
2299+ msg = re .escape ("typing.Foo is not a generic class" )
2300+ with self .assertRaisesRegex (TypeError , msg ):
2301+ Alias0 [int ]
2302+
22572303
22582304class TypeTests (BaseTestCase ):
22592305
@@ -2379,6 +2425,16 @@ def test_error_message_when_subclassing(self):
23792425 class ProUserId (UserId ):
23802426 ...
23812427
2428+ def test_module_with_incomplete_sys (self ):
2429+ def does_not_exist (* args ):
2430+ raise AttributeError
2431+ with (
2432+ patch ("sys._getframemodulename" , does_not_exist , create = True ),
2433+ patch ("sys._getframe" , does_not_exist , create = True ),
2434+ ):
2435+ X = NewType ("X" , int )
2436+ self .assertEqual (X .__module__ , None )
2437+
23822438
23832439class Coordinate (Protocol ):
23842440 x : int
@@ -5499,6 +5555,25 @@ def foobar(x: List['X']): ...
54995555 get_type_hints (foobar , globals (), locals (), include_extras = True ),
55005556 {'x' : List [Annotated [int , (1 , 10 )]]}
55015557 )
5558+ def foobar2 (x : list ['X' ]): ...
5559+ if sys .version_info >= (3 , 11 ):
5560+ self .assertEqual (
5561+ get_type_hints (foobar2 , globals (), locals ()),
5562+ {'x' : list [int ]}
5563+ )
5564+ self .assertEqual (
5565+ get_type_hints (foobar2 , globals (), locals (), include_extras = True ),
5566+ {'x' : list [Annotated [int , (1 , 10 )]]}
5567+ )
5568+ else : # TODO: evaluate nested forward refs in Python < 3.11
5569+ self .assertEqual (
5570+ get_type_hints (foobar2 , globals (), locals ()),
5571+ {'x' : list ['X' ]}
5572+ )
5573+ self .assertEqual (
5574+ get_type_hints (foobar2 , globals (), locals (), include_extras = True ),
5575+ {'x' : list ['X' ]}
5576+ )
55025577 BA = Tuple [Annotated [T , (1 , 0 )], ...]
55035578 def barfoo (x : BA ): ...
55045579 self .assertEqual (get_type_hints (barfoo , globals (), locals ())['x' ], Tuple [T , ...])
@@ -5973,6 +6048,15 @@ def run():
59736048 # The actual test:
59746049 self .assertEqual (result1 , result2 )
59756050
6051+ def test_subclass (self ):
6052+ if sys .version_info >= (3 , 10 ):
6053+ with self .assertRaises (TypeError ):
6054+ class MyParamSpec (ParamSpec ):
6055+ pass
6056+ else :
6057+ class MyParamSpec (ParamSpec ): # Does not raise
6058+ pass
6059+
59766060
59776061class ConcatenateTests (BaseTestCase ):
59786062 def test_basics (self ):
@@ -6382,6 +6466,14 @@ def test_pickle(self):
63826466 pickled = pickle .dumps (Self , protocol = proto )
63836467 self .assertIs (Self , pickle .loads (pickled ))
63846468
6469+ @skipUnless (TYPING_3_10_0 , "PEP 604 has yet to be" )
6470+ def test_or (self ):
6471+ self .assertEqual (Self | int , Union [Self , int ])
6472+ self .assertEqual (int | Self , Union [int , Self ])
6473+
6474+ self .assertEqual (get_args (Self | int ), (Self , int ))
6475+ self .assertEqual (get_args (int | Self ), (int , Self ))
6476+
63856477
63866478class UnpackTests (BaseTestCase ):
63876479 def test_basic_plain (self ):
@@ -7749,6 +7841,45 @@ def test_immutable(self):
77497841 type (NoDefault ).foo
77507842
77517843
7844+ class NoExtraItemsTests (BaseTestCase ):
7845+ def test_pickling (self ):
7846+ for proto in range (pickle .HIGHEST_PROTOCOL + 1 ):
7847+ s = pickle .dumps (NoExtraItems , proto )
7848+ loaded = pickle .loads (s )
7849+ self .assertIs (NoExtraItems , loaded )
7850+
7851+ def test_doc (self ):
7852+ self .assertIsInstance (NoExtraItems .__doc__ , str )
7853+
7854+ def test_constructor (self ):
7855+ self .assertIs (NoExtraItems , type (NoExtraItems )())
7856+ with self .assertRaises (TypeError ):
7857+ type (NoExtraItems )(1 )
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" )
7865+
7866+ def test_no_call (self ):
7867+ with self .assertRaises (TypeError ):
7868+ NoExtraItems ()
7869+
7870+ def test_immutable (self ):
7871+ with self .assertRaises (AttributeError ):
7872+ NoExtraItems .foo = 'bar'
7873+ with self .assertRaises (AttributeError ):
7874+ NoExtraItems .foo
7875+
7876+ # TypeError is consistent with the behavior of NoneType
7877+ with self .assertRaises (TypeError ):
7878+ type(NoExtraItems ).foo = 3
7879+ with self .assertRaises (AttributeError ):
7880+ type (NoExtraItems ).foo
7881+
7882+
77527883class TypeVarInferVarianceTests (BaseTestCase ):
77537884 def test_typevar (self ):
77547885 T = typing_extensions .TypeVar ('T' )
0 commit comments