@@ -4177,7 +4177,103 @@ class AllTheThings(TypedDict):
4177
4177
self .assertEqual (AllTheThings .__optional_keys__ , frozenset ({'c' , 'd' }))
4178
4178
self .assertEqual (AllTheThings .__readonly_keys__ , frozenset ({'a' , 'b' , 'c' }))
4179
4179
self .assertEqual (AllTheThings .__mutable_keys__ , frozenset ({'d' }))
4180
+
4181
+ def test_extra_keys_non_readonly (self ):
4182
+ class Base (TypedDict , closed = True ):
4183
+ __extra_items__ : str
4184
+
4185
+ class Child (Base ):
4186
+ a : int
4187
+
4188
+ self .assertEqual (Child .__required_keys__ , frozenset ({'a' }))
4189
+ self .assertEqual (Child .__optional_keys__ , frozenset ({}))
4190
+ self .assertEqual (Child .__readonly_keys__ , frozenset ({}))
4191
+ self .assertEqual (Child .__mutable_keys__ , frozenset ({'a' }))
4180
4192
4193
+ def test_extra_keys_readonly (self ):
4194
+ class Base (TypedDict , closed = True ):
4195
+ __extra_items__ : ReadOnly [str ]
4196
+
4197
+ class Child (Base ):
4198
+ a : int
4199
+
4200
+ self .assertEqual (Child .__required_keys__ , frozenset ({'a' }))
4201
+ self .assertEqual (Child .__optional_keys__ , frozenset ({}))
4202
+ self .assertEqual (Child .__readonly_keys__ , frozenset ({}))
4203
+ self .assertEqual (Child .__mutable_keys__ , frozenset ({'a' }))
4204
+
4205
+ def test_extra_key_required (self ):
4206
+ with self .assertRaisesRegex (
4207
+ TypeError ,
4208
+ "Special key __extra_items__ does not support Required and NotRequired"
4209
+ ):
4210
+ TypedDict ("A" , {"__extra_items__" : Required [int ]}, closed = True )
4211
+
4212
+ with self .assertRaisesRegex (
4213
+ TypeError ,
4214
+ "Special key __extra_items__ does not support Required and NotRequired"
4215
+ ):
4216
+ TypedDict ("A" , {"__extra_items__" : NotRequired [int ]}, closed = True )
4217
+
4218
+ def test_regular_extra_items (self ):
4219
+ class ExtraReadOnly (TypedDict ):
4220
+ __extra_items__ : ReadOnly [str ]
4221
+
4222
+ class ExtraRequired (TypedDict ):
4223
+ __extra_items__ : Required [str ]
4224
+
4225
+ class ExtraNotRequired (TypedDict ):
4226
+ __extra_items__ : NotRequired [str ]
4227
+
4228
+ self .assertEqual (ExtraReadOnly .__required_keys__ , frozenset ({'__extra_items__' }))
4229
+ self .assertEqual (ExtraReadOnly .__optional_keys__ , frozenset ({}))
4230
+ self .assertEqual (ExtraReadOnly .__readonly_keys__ , frozenset ({'__extra_items__' }))
4231
+ self .assertEqual (ExtraReadOnly .__mutable_keys__ , frozenset ({}))
4232
+
4233
+ self .assertEqual (ExtraRequired .__required_keys__ , frozenset ({'__extra_items__' }))
4234
+ self .assertEqual (ExtraRequired .__optional_keys__ , frozenset ({}))
4235
+ self .assertEqual (ExtraRequired .__readonly_keys__ , frozenset ({}))
4236
+ self .assertEqual (ExtraRequired .__mutable_keys__ , frozenset ({'__extra_items__' }))
4237
+
4238
+ self .assertEqual (ExtraNotRequired .__required_keys__ , frozenset ({}))
4239
+ self .assertEqual (ExtraNotRequired .__optional_keys__ , frozenset ({'__extra_items__' }))
4240
+ self .assertEqual (ExtraNotRequired .__readonly_keys__ , frozenset ({}))
4241
+ self .assertEqual (ExtraNotRequired .__mutable_keys__ , frozenset ({'__extra_items__' }))
4242
+
4243
+ def test_closed_inheritance (self ):
4244
+ class Base (TypedDict , closed = True ):
4245
+ __extra_items__ : ReadOnly [Union [str , None ]]
4246
+
4247
+ class Child (Base ):
4248
+ a : int
4249
+ __extra_items__ : int
4250
+
4251
+ class GrandChild (Child , closed = True ):
4252
+ __extra_items__ : str
4253
+
4254
+ self .assertEqual (Base .__required_keys__ , frozenset ({}))
4255
+ self .assertEqual (Base .__optional_keys__ , frozenset ({}))
4256
+ self .assertEqual (Base .__readonly_keys__ , frozenset ({}))
4257
+ self .assertEqual (Base .__mutable_keys__ , frozenset ({}))
4258
+
4259
+ self .assertEqual (Child .__required_keys__ , frozenset ({'a' , "__extra_items__" }))
4260
+ self .assertEqual (Child .__optional_keys__ , frozenset ({}))
4261
+ self .assertEqual (Child .__readonly_keys__ , frozenset ({}))
4262
+ self .assertEqual (Child .__mutable_keys__ , frozenset ({'a' , "__extra_items__" }))
4263
+
4264
+ self .assertEqual (GrandChild .__required_keys__ , frozenset ({'a' , "__extra_items__" }))
4265
+ self .assertEqual (GrandChild .__optional_keys__ , frozenset ({}))
4266
+ self .assertEqual (GrandChild .__readonly_keys__ , frozenset ({}))
4267
+ self .assertEqual (GrandChild .__mutable_keys__ , frozenset ({'a' , "__extra_items__" }))
4268
+
4269
+ self .assertEqual (Base .__annotations__ , {"__extra_items__" : ReadOnly [Union [str , None ]]})
4270
+ self .assertEqual (Child .__annotations__ , {"__extra_items__" : int , "a" : int })
4271
+ self .assertEqual (GrandChild .__annotations__ , {"__extra_items__" : str , "a" : int })
4272
+
4273
+ self .assertTrue (Base .__closed__ )
4274
+ self .assertFalse (Child .__closed__ )
4275
+ self .assertTrue (GrandChild .__closed__ )
4276
+
4181
4277
4182
4278
class AnnotatedTests (BaseTestCase ):
4183
4279
0 commit comments