@@ -3820,6 +3820,24 @@ class ChildWithInlineAndOptional(Untotal, Inline):
3820
3820
{'inline' : bool , 'untotal' : str , 'child' : bool },
3821
3821
)
3822
3822
3823
+ class Closed (TypedDict , closed = True ):
3824
+ __extra_items__ : None
3825
+
3826
+ class Unclosed (TypedDict , closed = False ):
3827
+ ...
3828
+
3829
+ class ChildUnclosed (Closed , Unclosed ):
3830
+ ...
3831
+
3832
+ self .assertFalse (ChildUnclosed .__closed__ )
3833
+ self .assertEqual (ChildUnclosed .__extra_items__ , type (None ))
3834
+
3835
+ class ChildClosed (Unclosed , Closed ):
3836
+ ...
3837
+
3838
+ self .assertFalse (ChildClosed .__closed__ )
3839
+ self .assertEqual (ChildClosed .__extra_items__ , type (None ))
3840
+
3823
3841
wrong_bases = [
3824
3842
(One , Regular ),
3825
3843
(Regular , One ),
@@ -4219,79 +4237,92 @@ def test_regular_extra_items(self):
4219
4237
class ExtraReadOnly (TypedDict ):
4220
4238
__extra_items__ : ReadOnly [str ]
4221
4239
4222
- class ExtraRequired (TypedDict ):
4223
- __extra_items__ : Required [str ]
4224
-
4225
- class ExtraNotRequired (TypedDict ):
4226
- __extra_items__ : NotRequired [str ]
4227
-
4228
4240
self .assertEqual (ExtraReadOnly .__required_keys__ , frozenset ({'__extra_items__' }))
4229
4241
self .assertEqual (ExtraReadOnly .__optional_keys__ , frozenset ({}))
4230
4242
self .assertEqual (ExtraReadOnly .__readonly_keys__ , frozenset ({'__extra_items__' }))
4231
4243
self .assertEqual (ExtraReadOnly .__mutable_keys__ , frozenset ({}))
4244
+ self .assertEqual (ExtraReadOnly .__extra_items__ , None )
4245
+ self .assertFalse (ExtraReadOnly .__closed__ )
4246
+
4247
+ class ExtraRequired (TypedDict ):
4248
+ __extra_items__ : Required [str ]
4232
4249
4233
4250
self .assertEqual (ExtraRequired .__required_keys__ , frozenset ({'__extra_items__' }))
4234
4251
self .assertEqual (ExtraRequired .__optional_keys__ , frozenset ({}))
4235
4252
self .assertEqual (ExtraRequired .__readonly_keys__ , frozenset ({}))
4236
4253
self .assertEqual (ExtraRequired .__mutable_keys__ , frozenset ({'__extra_items__' }))
4254
+ self .assertEqual (ExtraRequired .__extra_items__ , None )
4255
+ self .assertFalse (ExtraRequired .__closed__ )
4256
+
4257
+ class ExtraNotRequired (TypedDict ):
4258
+ __extra_items__ : NotRequired [str ]
4237
4259
4238
4260
self .assertEqual (ExtraNotRequired .__required_keys__ , frozenset ({}))
4239
4261
self .assertEqual (ExtraNotRequired .__optional_keys__ , frozenset ({'__extra_items__' }))
4240
4262
self .assertEqual (ExtraNotRequired .__readonly_keys__ , frozenset ({}))
4241
4263
self .assertEqual (ExtraNotRequired .__mutable_keys__ , frozenset ({'__extra_items__' }))
4264
+ self .assertEqual (ExtraNotRequired .__extra_items__ , None )
4265
+ self .assertFalse (ExtraNotRequired .__closed__ )
4242
4266
4243
4267
def test_closed_inheritance (self ):
4244
4268
class Base (TypedDict , closed = True ):
4245
4269
__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
4270
4254
4271
self .assertEqual (Base .__required_keys__ , frozenset ({}))
4255
4272
self .assertEqual (Base .__optional_keys__ , frozenset ({}))
4256
4273
self .assertEqual (Base .__readonly_keys__ , frozenset ({}))
4257
4274
self .assertEqual (Base .__mutable_keys__ , frozenset ({}))
4275
+ self .assertEqual (Base .__annotations__ , {})
4258
4276
self .assertEqual (Base .__extra_items__ , ReadOnly [Union [str , None ]])
4277
+ self .assertTrue (Base .__closed__ )
4278
+
4279
+ class Child (Base ):
4280
+ a : int
4281
+ __extra_items__ : int
4259
4282
4260
4283
self .assertEqual (Child .__required_keys__ , frozenset ({'a' , "__extra_items__" }))
4261
4284
self .assertEqual (Child .__optional_keys__ , frozenset ({}))
4262
4285
self .assertEqual (Child .__readonly_keys__ , frozenset ({}))
4263
4286
self .assertEqual (Child .__mutable_keys__ , frozenset ({'a' , "__extra_items__" }))
4287
+ self .assertEqual (Child .__annotations__ , {"__extra_items__" : int , "a" : int })
4264
4288
self .assertEqual (Child .__extra_items__ , ReadOnly [Union [str , None ]])
4289
+ self .assertFalse (Child .__closed__ )
4290
+
4291
+ class GrandChild (Child , closed = True ):
4292
+ __extra_items__ : str
4265
4293
4266
4294
self .assertEqual (GrandChild .__required_keys__ , frozenset ({'a' , "__extra_items__" }))
4267
4295
self .assertEqual (GrandChild .__optional_keys__ , frozenset ({}))
4268
4296
self .assertEqual (GrandChild .__readonly_keys__ , frozenset ({}))
4269
4297
self .assertEqual (GrandChild .__mutable_keys__ , frozenset ({'a' , "__extra_items__" }))
4270
- self .assertEqual (GrandChild .__extra_items__ , str )
4271
-
4272
- self .assertEqual (Base .__annotations__ , {})
4273
- self .assertEqual (Child .__annotations__ , {"__extra_items__" : int , "a" : int })
4274
4298
self .assertEqual (GrandChild .__annotations__ , {"__extra_items__" : int , "a" : int })
4275
-
4276
- self .assertTrue (Base .__closed__ )
4277
- self .assertFalse (Child .__closed__ )
4299
+ self .assertEqual (GrandChild .__extra_items__ , str )
4278
4300
self .assertTrue (GrandChild .__closed__ )
4279
4301
4280
- def test_absent_extra_items (self ):
4302
+ def test_implicit_extra_items (self ):
4281
4303
class Base (TypedDict ):
4282
4304
a : int
4283
-
4305
+
4306
+ self .assertEqual (Base .__extra_items__ , None )
4307
+ self .assertFalse (Base .__closed__ )
4308
+
4284
4309
class ChildA (Base , closed = True ):
4285
4310
...
4286
4311
4312
+ self .assertEqual (ChildA .__extra_items__ , Never )
4313
+ self .assertTrue (ChildA .__closed__ )
4314
+
4287
4315
class ChildB (Base , closed = True ):
4288
4316
__extra_items__ : None
4289
-
4290
- self .assertNotIn ("__extra_items__" , Base .__dict__ )
4291
- self .assertIn ("__extra_items__" , ChildA .__dict__ )
4292
- self .assertIn ("__extra_items__" , ChildB .__dict__ )
4293
- self .assertEqual (ChildA .__extra_items__ , Never )
4317
+
4294
4318
self .assertEqual (ChildB .__extra_items__ , type (None ))
4319
+ self .assertTrue (ChildB .__closed__ )
4320
+
4321
+ def test_backwards_compatibility (self ):
4322
+ with self .assertWarns (DeprecationWarning ):
4323
+ TD = TypedDict ("TD" , closed = int )
4324
+ self .assertFalse (TD .__closed__ )
4325
+ self .assertEqual (TD .__annotations__ , {"closed" : int })
4295
4326
4296
4327
4297
4328
class AnnotatedTests (BaseTestCase ):
0 commit comments