@@ -7189,18 +7189,47 @@ class Group(NamedTuple):
7189
7189
self .assertEqual (a , (1 , [2 ]))
7190
7190
7191
7191
def test_namedtuple_keyword_usage (self ):
7192
- LocalEmployee = NamedTuple ("LocalEmployee" , name = str , age = int )
7192
+ with self .assertWarnsRegex (
7193
+ DeprecationWarning ,
7194
+ "Creating NamedTuple classes using keyword arguments is deprecated"
7195
+ ):
7196
+ LocalEmployee = NamedTuple ("LocalEmployee" , name = str , age = int )
7197
+
7193
7198
nick = LocalEmployee ('Nick' , 25 )
7194
7199
self .assertIsInstance (nick , tuple )
7195
7200
self .assertEqual (nick .name , 'Nick' )
7196
7201
self .assertEqual (LocalEmployee .__name__ , 'LocalEmployee' )
7197
7202
self .assertEqual (LocalEmployee ._fields , ('name' , 'age' ))
7198
7203
self .assertEqual (LocalEmployee .__annotations__ , dict (name = str , age = int ))
7199
- with self .assertRaises (TypeError ):
7204
+
7205
+ with self .assertRaisesRegex (
7206
+ TypeError ,
7207
+ "Either list of fields or keywords can be provided to NamedTuple, not both"
7208
+ ):
7200
7209
NamedTuple ('Name' , [('x' , int )], y = str )
7201
7210
7211
+ with self .assertRaisesRegex (
7212
+ TypeError ,
7213
+ "Either list of fields or keywords can be provided to NamedTuple, not both"
7214
+ ):
7215
+ NamedTuple ('Name' , [], y = str )
7216
+
7217
+ with self .assertRaisesRegex (
7218
+ TypeError ,
7219
+ (
7220
+ r"Cannot pass `None` as the 'fields' parameter "
7221
+ r"and also specify fields using keyword arguments"
7222
+ )
7223
+ ):
7224
+ NamedTuple ('Name' , None , x = int )
7225
+
7202
7226
def test_namedtuple_special_keyword_names (self ):
7203
- NT = NamedTuple ("NT" , cls = type , self = object , typename = str , fields = list )
7227
+ with self .assertWarnsRegex (
7228
+ DeprecationWarning ,
7229
+ "Creating NamedTuple classes using keyword arguments is deprecated"
7230
+ ):
7231
+ NT = NamedTuple ("NT" , cls = type , self = object , typename = str , fields = list )
7232
+
7204
7233
self .assertEqual (NT .__name__ , 'NT' )
7205
7234
self .assertEqual (NT ._fields , ('cls' , 'self' , 'typename' , 'fields' ))
7206
7235
a = NT (cls = str , self = 42 , typename = 'foo' , fields = [('bar' , tuple )])
@@ -7210,12 +7239,32 @@ def test_namedtuple_special_keyword_names(self):
7210
7239
self .assertEqual (a .fields , [('bar' , tuple )])
7211
7240
7212
7241
def test_empty_namedtuple (self ):
7213
- NT = NamedTuple ('NT' )
7242
+ expected_warning = re .escape (
7243
+ "Failing to pass a value for the 'fields' parameter is deprecated "
7244
+ "and will be disallowed in Python 3.15. "
7245
+ "To create a NamedTuple class with 0 fields "
7246
+ "using the functional syntax, "
7247
+ "pass an empty list, e.g. `NT1 = NamedTuple('NT1', [])`."
7248
+ )
7249
+ with self .assertWarnsRegex (DeprecationWarning , fr"^{ expected_warning } $" ):
7250
+ NT1 = NamedTuple ('NT1' )
7251
+
7252
+ expected_warning = re .escape (
7253
+ "Passing `None` as the 'fields' parameter is deprecated "
7254
+ "and will be disallowed in Python 3.15. "
7255
+ "To create a NamedTuple class with 0 fields "
7256
+ "using the functional syntax, "
7257
+ "pass an empty list, e.g. `NT2 = NamedTuple('NT2', [])`."
7258
+ )
7259
+ with self .assertWarnsRegex (DeprecationWarning , fr"^{ expected_warning } $" ):
7260
+ NT2 = NamedTuple ('NT2' , None )
7261
+
7262
+ NT3 = NamedTuple ('NT2' , [])
7214
7263
7215
7264
class CNT (NamedTuple ):
7216
7265
pass # empty body
7217
7266
7218
- for struct in [ NT , CNT ] :
7267
+ for struct in NT1 , NT2 , NT3 , CNT :
7219
7268
with self .subTest (struct = struct ):
7220
7269
self .assertEqual (struct ._fields , ())
7221
7270
self .assertEqual (struct ._field_defaults , {})
@@ -7225,13 +7274,29 @@ class CNT(NamedTuple):
7225
7274
def test_namedtuple_errors (self ):
7226
7275
with self .assertRaises (TypeError ):
7227
7276
NamedTuple .__new__ ()
7228
- with self .assertRaises (TypeError ):
7277
+
7278
+ with self .assertRaisesRegex (
7279
+ TypeError ,
7280
+ "missing 1 required positional argument"
7281
+ ):
7229
7282
NamedTuple ()
7230
- with self .assertRaises (TypeError ):
7283
+
7284
+ with self .assertRaisesRegex (
7285
+ TypeError ,
7286
+ "takes from 1 to 2 positional arguments but 3 were given"
7287
+ ):
7231
7288
NamedTuple ('Emp' , [('name' , str )], None )
7232
- with self .assertRaises (ValueError ):
7289
+
7290
+ with self .assertRaisesRegex (
7291
+ ValueError ,
7292
+ "Field names cannot start with an underscore"
7293
+ ):
7233
7294
NamedTuple ('Emp' , [('_name' , str )])
7234
- with self .assertRaises (TypeError ):
7295
+
7296
+ with self .assertRaisesRegex (
7297
+ TypeError ,
7298
+ "missing 1 required positional argument: 'typename'"
7299
+ ):
7235
7300
NamedTuple (typename = 'Emp' , name = str , id = int )
7236
7301
7237
7302
def test_copy_and_pickle (self ):
0 commit comments