Skip to content

Commit 1fb2c64

Browse files
committed
Better error handling and skip compat test cases in 3.13+.
This also fixes the lint errors. Signed-off-by: Zixuan James Li <[email protected]>
1 parent 572531b commit 1fb2c64

File tree

2 files changed

+32
-18
lines changed

2 files changed

+32
-18
lines changed

src/test_typing_extensions.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@
5252
# 3.12 changes the representation of Unpack[] (PEP 692)
5353
TYPING_3_12_0 = sys.version_info[:3] >= (3, 12, 0)
5454

55+
# 3.13 drops support for the keyword argument syntax of TypedDict
56+
TYPING_3_13_0 = sys.version_info[:3] >= (3, 13, 0)
57+
5558
# https://github.com/python/cpython/pull/27017 was backported into some 3.9 and 3.10
5659
# versions, but not all
5760
HAS_FORWARD_MODULE = "module" in inspect.signature(typing._type_check).parameters
@@ -3822,10 +3825,10 @@ class ChildWithInlineAndOptional(Untotal, Inline):
38223825

38233826
class Closed(TypedDict, closed=True):
38243827
__extra_items__: None
3825-
3828+
38263829
class Unclosed(TypedDict, closed=False):
38273830
...
3828-
3831+
38293832
class ChildUnclosed(Closed, Unclosed):
38303833
...
38313834

@@ -3834,7 +3837,7 @@ class ChildUnclosed(Closed, Unclosed):
38343837

38353838
class ChildClosed(Unclosed, Closed):
38363839
...
3837-
3840+
38383841
self.assertFalse(ChildClosed.__closed__)
38393842
self.assertEqual(ChildClosed.__extra_items__, type(None))
38403843

@@ -4195,14 +4198,14 @@ class AllTheThings(TypedDict):
41954198
self.assertEqual(AllTheThings.__optional_keys__, frozenset({'c', 'd'}))
41964199
self.assertEqual(AllTheThings.__readonly_keys__, frozenset({'a', 'b', 'c'}))
41974200
self.assertEqual(AllTheThings.__mutable_keys__, frozenset({'d'}))
4198-
4201+
41994202
def test_extra_keys_non_readonly(self):
42004203
class Base(TypedDict, closed=True):
42014204
__extra_items__: str
4202-
4205+
42034206
class Child(Base):
42044207
a: NotRequired[int]
4205-
4208+
42064209
self.assertEqual(Child.__required_keys__, frozenset({}))
42074210
self.assertEqual(Child.__optional_keys__, frozenset({'a'}))
42084211
self.assertEqual(Child.__readonly_keys__, frozenset({}))
@@ -4211,28 +4214,28 @@ class Child(Base):
42114214
def test_extra_keys_readonly(self):
42124215
class Base(TypedDict, closed=True):
42134216
__extra_items__: ReadOnly[str]
4214-
4217+
42154218
class Child(Base):
42164219
a: NotRequired[str]
4217-
4220+
42184221
self.assertEqual(Child.__required_keys__, frozenset({}))
42194222
self.assertEqual(Child.__optional_keys__, frozenset({'a'}))
42204223
self.assertEqual(Child.__readonly_keys__, frozenset({}))
42214224
self.assertEqual(Child.__mutable_keys__, frozenset({'a'}))
4222-
4225+
42234226
def test_extra_key_required(self):
42244227
with self.assertRaisesRegex(
42254228
TypeError,
4226-
"Special key __extra_items__ does not support Required and NotRequired"
4229+
"Special key __extra_items__ does not support Required"
42274230
):
42284231
TypedDict("A", {"__extra_items__": Required[int]}, closed=True)
42294232

42304233
with self.assertRaisesRegex(
42314234
TypeError,
4232-
"Special key __extra_items__ does not support Required and NotRequired"
4235+
"Special key __extra_items__ does not support NotRequired"
42334236
):
42344237
TypedDict("A", {"__extra_items__": NotRequired[int]}, closed=True)
4235-
4238+
42364239
def test_regular_extra_items(self):
42374240
class ExtraReadOnly(TypedDict):
42384241
__extra_items__: ReadOnly[str]
@@ -4263,7 +4266,7 @@ class ExtraNotRequired(TypedDict):
42634266
self.assertEqual(ExtraNotRequired.__mutable_keys__, frozenset({'__extra_items__'}))
42644267
self.assertEqual(ExtraNotRequired.__extra_items__, None)
42654268
self.assertFalse(ExtraNotRequired.__closed__)
4266-
4269+
42674270
def test_closed_inheritance(self):
42684271
class Base(TypedDict, closed=True):
42694272
__extra_items__: ReadOnly[Union[str, None]]
@@ -4298,7 +4301,7 @@ class GrandChild(Child, closed=True):
42984301
self.assertEqual(GrandChild.__annotations__, {"__extra_items__": int, "a": int})
42994302
self.assertEqual(GrandChild.__extra_items__, str)
43004303
self.assertTrue(GrandChild.__closed__)
4301-
4304+
43024305
def test_implicit_extra_items(self):
43034306
class Base(TypedDict):
43044307
a: int
@@ -4318,6 +4321,11 @@ class ChildB(Base, closed=True):
43184321
self.assertEqual(ChildB.__extra_items__, type(None))
43194322
self.assertTrue(ChildB.__closed__)
43204323

4324+
@skipIf(
4325+
TYPING_3_13_0,
4326+
"The keyword argument alternative to define a "
4327+
"TypedDict type using the functional syntax is no longer supported"
4328+
)
43214329
def test_backwards_compatibility(self):
43224330
with self.assertWarns(DeprecationWarning):
43234331
TD = TypedDict("TD", closed=int)

src/typing_extensions.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -930,18 +930,24 @@ def __new__(cls, name, bases, ns, *, total=True, closed=False):
930930
optional_keys.update(base_dict.get('__optional_keys__', ()))
931931
readonly_keys.update(base_dict.get('__readonly_keys__', ()))
932932
mutable_keys.update(base_dict.get('__mutable_keys__', ()))
933-
if (base_extra_items_type := base_dict.get('__extra_items__', None)) is not None:
933+
base_extra_items_type = base_dict.get('__extra_items__', None)
934+
if base_extra_items_type is not None:
934935
extra_items_type = base_extra_items_type
935-
936+
936937
if closed and extra_items_type is None:
937938
extra_items_type = Never
938939
if closed and "__extra_items__" in own_annotations:
939940
annotation_type = own_annotations.pop("__extra_items__")
940941
qualifiers = set(_get_typeddict_qualifiers(annotation_type))
941-
if Required in qualifiers or NotRequired in qualifiers:
942+
if Required in qualifiers:
943+
raise TypeError(
944+
"Special key __extra_items__ does not support "
945+
"Required"
946+
)
947+
if NotRequired in qualifiers:
942948
raise TypeError(
943949
"Special key __extra_items__ does not support "
944-
"Required and NotRequired"
950+
"NotRequired"
945951
)
946952
extra_items_type = annotation_type
947953

0 commit comments

Comments
 (0)