@@ -8080,78 +8080,13 @@ class Group(NamedTuple):
80808080 self .assertIs (type (a ), Group )
80818081 self .assertEqual (a , (1 , [2 ]))
80828082
8083- def test_namedtuple_keyword_usage (self ):
8084- with self .assertWarnsRegex (
8085- DeprecationWarning ,
8086- "Creating NamedTuple classes using keyword arguments is deprecated"
8087- ):
8088- LocalEmployee = NamedTuple ("LocalEmployee" , name = str , age = int )
8089-
8090- nick = LocalEmployee ('Nick' , 25 )
8091- self .assertIsInstance (nick , tuple )
8092- self .assertEqual (nick .name , 'Nick' )
8093- self .assertEqual (LocalEmployee .__name__ , 'LocalEmployee' )
8094- self .assertEqual (LocalEmployee ._fields , ('name' , 'age' ))
8095- self .assertEqual (LocalEmployee .__annotations__ , dict (name = str , age = int ))
8096-
8097- with self .assertRaisesRegex (
8098- TypeError ,
8099- "Either list of fields or keywords can be provided to NamedTuple, not both"
8100- ):
8101- NamedTuple ('Name' , [('x' , int )], y = str )
8102-
8103- with self .assertRaisesRegex (
8104- TypeError ,
8105- "Either list of fields or keywords can be provided to NamedTuple, not both"
8106- ):
8107- NamedTuple ('Name' , [], y = str )
8108-
8109- with self .assertRaisesRegex (
8110- TypeError ,
8111- (
8112- r"Cannot pass `None` as the 'fields' parameter "
8113- r"and also specify fields using keyword arguments"
8114- )
8115- ):
8116- NamedTuple ('Name' , None , x = int )
8117-
8118- def test_namedtuple_special_keyword_names (self ):
8119- with self .assertWarnsRegex (
8120- DeprecationWarning ,
8121- "Creating NamedTuple classes using keyword arguments is deprecated"
8122- ):
8123- NT = NamedTuple ("NT" , cls = type , self = object , typename = str , fields = list )
8124-
8125- self .assertEqual (NT .__name__ , 'NT' )
8126- self .assertEqual (NT ._fields , ('cls' , 'self' , 'typename' , 'fields' ))
8127- a = NT (cls = str , self = 42 , typename = 'foo' , fields = [('bar' , tuple )])
8128- self .assertEqual (a .cls , str )
8129- self .assertEqual (a .self , 42 )
8130- self .assertEqual (a .typename , 'foo' )
8131- self .assertEqual (a .fields , [('bar' , tuple )])
8132-
81338083 def test_empty_namedtuple (self ):
8134- expected_warning = re .escape (
8135- "Failing to pass a value for the 'fields' parameter is deprecated "
8136- "and will be disallowed in Python 3.15. "
8137- "To create a NamedTuple class with 0 fields "
8138- "using the functional syntax, "
8139- "pass an empty list, e.g. `NT1 = NamedTuple('NT1', [])`."
8140- )
8141- with self .assertWarnsRegex (DeprecationWarning , fr"^{ expected_warning } $" ):
8142- NT1 = NamedTuple ('NT1' )
8143-
8144- expected_warning = re .escape (
8145- "Passing `None` as the 'fields' parameter is deprecated "
8146- "and will be disallowed in Python 3.15. "
8147- "To create a NamedTuple class with 0 fields "
8148- "using the functional syntax, "
8149- "pass an empty list, e.g. `NT2 = NamedTuple('NT2', [])`."
8150- )
8151- with self .assertWarnsRegex (DeprecationWarning , fr"^{ expected_warning } $" ):
8152- NT2 = NamedTuple ('NT2' , None )
8084+ with self .assertRaisesRegex (TypeError , "missing.*required.*argument" ):
8085+ BAD = NamedTuple ('BAD' )
81538086
8154- NT3 = NamedTuple ('NT2' , [])
8087+ NT1 = NamedTuple ('NT1' , {})
8088+ NT2 = NamedTuple ('NT2' , ())
8089+ NT3 = NamedTuple ('NT3' , [])
81558090
81568091 class CNT (NamedTuple ):
81578092 pass # empty body
@@ -8166,16 +8101,18 @@ class CNT(NamedTuple):
81668101 def test_namedtuple_errors (self ):
81678102 with self .assertRaises (TypeError ):
81688103 NamedTuple .__new__ ()
8104+ with self .assertRaisesRegex (TypeError , "object is not iterable" ):
8105+ NamedTuple ('Name' , None )
81698106
81708107 with self .assertRaisesRegex (
81718108 TypeError ,
8172- "missing 1 required positional argument "
8109+ "missing 2 required positional arguments "
81738110 ):
81748111 NamedTuple ()
81758112
81768113 with self .assertRaisesRegex (
81778114 TypeError ,
8178- "takes from 1 to 2 positional arguments but 3 were given"
8115+ "takes 2 positional arguments but 3 were given"
81798116 ):
81808117 NamedTuple ('Emp' , [('name' , str )], None )
81818118
@@ -8187,10 +8124,22 @@ def test_namedtuple_errors(self):
81878124
81888125 with self .assertRaisesRegex (
81898126 TypeError ,
8190- "missing 1 required positional argument: 'typename' "
8127+ "got some positional-only arguments passed as keyword arguments "
81918128 ):
81928129 NamedTuple (typename = 'Emp' , name = str , id = int )
81938130
8131+ with self .assertRaisesRegex (
8132+ TypeError ,
8133+ "got an unexpected keyword argument"
8134+ ):
8135+ NamedTuple ('Name' , [('x' , int )], y = str )
8136+
8137+ with self .assertRaisesRegex (
8138+ TypeError ,
8139+ "got an unexpected keyword argument"
8140+ ):
8141+ NamedTuple ('Name' , [], y = str )
8142+
81948143 def test_copy_and_pickle (self ):
81958144 global Emp # pickle wants to reference the class by name
81968145 Emp = NamedTuple ('Emp' , [('name' , str ), ('cool' , int )])
@@ -8904,39 +8853,27 @@ class MultipleGenericBases(GenericParent[int], GenericParent[float]):
89048853 self .assertEqual (CallTypedDict .__orig_bases__ , (TypedDict ,))
89058854
89068855 def test_zero_fields_typeddicts (self ):
8907- T1 = TypedDict ("T1" , {})
8856+ T1a = TypedDict ("T1a" , {})
8857+ T1b = TypedDict ("T1b" , [])
8858+ T1c = TypedDict ("T1c" , ())
89088859 class T2 (TypedDict ): pass
89098860 class T3 [tvar ](TypedDict ): pass
89108861 S = TypeVar ("S" )
89118862 class T4 (TypedDict , Generic [S ]): pass
89128863
8913- expected_warning = re .escape (
8914- "Failing to pass a value for the 'fields' parameter is deprecated "
8915- "and will be disallowed in Python 3.15. "
8916- "To create a TypedDict class with 0 fields "
8917- "using the functional syntax, "
8918- "pass an empty dictionary, e.g. `T5 = TypedDict('T5', {})`."
8919- )
8920- with self .assertWarnsRegex (DeprecationWarning , fr"^{ expected_warning } $" ):
8921- T5 = TypedDict ('T5' )
8922-
8923- expected_warning = re .escape (
8924- "Passing `None` as the 'fields' parameter is deprecated "
8925- "and will be disallowed in Python 3.15. "
8926- "To create a TypedDict class with 0 fields "
8927- "using the functional syntax, "
8928- "pass an empty dictionary, e.g. `T6 = TypedDict('T6', {})`."
8929- )
8930- with self .assertWarnsRegex (DeprecationWarning , fr"^{ expected_warning } $" ):
8931- T6 = TypedDict ('T6' , None )
8932-
8933- for klass in T1 , T2 , T3 , T4 , T5 , T6 :
8864+ for klass in T1a , T1b , T1c , T2 , T3 , T4 :
89348865 with self .subTest (klass = klass .__name__ ):
89358866 self .assertEqual (klass .__annotations__ , {})
89368867 self .assertEqual (klass .__required_keys__ , set ())
89378868 self .assertEqual (klass .__optional_keys__ , set ())
89388869 self .assertIsInstance (klass (), dict )
89398870
8871+ def test_errors (self ):
8872+ with self .assertRaisesRegex (TypeError , "missing 1 required.*argument" ):
8873+ TypedDict ('TD' )
8874+ with self .assertRaisesRegex (TypeError , "object is not iterable" ):
8875+ TypedDict ('TD' , None )
8876+
89408877 def test_readonly_inheritance (self ):
89418878 class Base1 (TypedDict ):
89428879 a : ReadOnly [int ]
0 commit comments