Skip to content

Commit 9532f11

Browse files
committed
Define _create_typeddict(), change __name__
1 parent 7379a2a commit 9532f11

File tree

2 files changed

+78
-53
lines changed

2 files changed

+78
-53
lines changed

src/test_typing_extensions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5089,7 +5089,7 @@ def test_inlined(self):
50895089
self.assertIsSubclass(TD, typing.MutableMapping)
50905090
self.assertNotIsSubclass(TD, collections.abc.Sequence)
50915091
self.assertTrue(is_typeddict(TD))
5092-
self.assertEqual(TD.__name__, "<inlined TypedDict>")
5092+
self.assertEqual(TD.__name__, "<inline TypedDict>")
50935093
self.assertEqual(TD.__module__, __name__)
50945094
self.assertEqual(TD.__bases__, (dict,))
50955095
self.assertEqual(TD.__total__, True)

src/typing_extensions.py

Lines changed: 77 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,66 @@ def __subclasscheck__(cls, other):
10781078

10791079
_TypedDict = type.__new__(_TypedDictMeta, 'TypedDict', (), {})
10801080

1081+
def _create_typeddict(
1082+
typename,
1083+
fields,
1084+
/,
1085+
*,
1086+
typing_is_inline,
1087+
total,
1088+
closed,
1089+
extra_items,
1090+
**kwargs,
1091+
):
1092+
if fields is _marker or fields is None:
1093+
if fields is _marker:
1094+
deprecated_thing = (
1095+
"Failing to pass a value for the 'fields' parameter"
1096+
)
1097+
else:
1098+
deprecated_thing = "Passing `None` as the 'fields' parameter"
1099+
1100+
example = f"`{typename} = TypedDict({typename!r}, {{}})`"
1101+
deprecation_msg = (
1102+
f"{deprecated_thing} is deprecated and will be disallowed in "
1103+
"Python 3.15. To create a TypedDict class with 0 fields "
1104+
"using the functional syntax, pass an empty dictionary, e.g. "
1105+
) + example + "."
1106+
warnings.warn(deprecation_msg, DeprecationWarning, stacklevel=2)
1107+
# Support a field called "closed"
1108+
if closed is not False and closed is not True and closed is not None:
1109+
kwargs["closed"] = closed
1110+
closed = None
1111+
# Or "extra_items"
1112+
if extra_items is not NoExtraItems:
1113+
kwargs["extra_items"] = extra_items
1114+
extra_items = NoExtraItems
1115+
fields = kwargs
1116+
elif kwargs:
1117+
raise TypeError("TypedDict takes either a dict or keyword arguments,"
1118+
" but not both")
1119+
if kwargs:
1120+
if sys.version_info >= (3, 13):
1121+
raise TypeError("TypedDict takes no keyword arguments")
1122+
warnings.warn(
1123+
"The kwargs-based syntax for TypedDict definitions is deprecated "
1124+
"in Python 3.11, will be removed in Python 3.13, and may not be "
1125+
"understood by third-party type checkers.",
1126+
DeprecationWarning,
1127+
stacklevel=2,
1128+
)
1129+
1130+
ns = {'__annotations__': dict(fields)}
1131+
module = _caller(depth=5 if typing_is_inline else 3)
1132+
if module is not None:
1133+
# Setting correct module is necessary to make typed dict classes
1134+
# pickleable.
1135+
ns['__module__'] = module
1136+
1137+
td = _TypedDictMeta(typename, (), ns, total=total, closed=closed,
1138+
extra_items=extra_items)
1139+
td.__orig_bases__ = (TypedDict,)
1140+
return td
10811141

10821142
class _TypedDictSpecialForm(_ExtensionsSpecialForm, _root=True):
10831143
def __call__(
@@ -1089,58 +1149,17 @@ def __call__(
10891149
total=True,
10901150
closed=None,
10911151
extra_items=NoExtraItems,
1092-
__typing_is_inline__=False,
10931152
**kwargs
10941153
):
1095-
if fields is _marker or fields is None:
1096-
if fields is _marker:
1097-
deprecated_thing = (
1098-
"Failing to pass a value for the 'fields' parameter"
1099-
)
1100-
else:
1101-
deprecated_thing = "Passing `None` as the 'fields' parameter"
1102-
1103-
example = f"`{typename} = TypedDict({typename!r}, {{}})`"
1104-
deprecation_msg = (
1105-
f"{deprecated_thing} is deprecated and will be disallowed in "
1106-
"Python 3.15. To create a TypedDict class with 0 fields "
1107-
"using the functional syntax, pass an empty dictionary, e.g. "
1108-
) + example + "."
1109-
warnings.warn(deprecation_msg, DeprecationWarning, stacklevel=2)
1110-
# Support a field called "closed"
1111-
if closed is not False and closed is not True and closed is not None:
1112-
kwargs["closed"] = closed
1113-
closed = None
1114-
# Or "extra_items"
1115-
if extra_items is not NoExtraItems:
1116-
kwargs["extra_items"] = extra_items
1117-
extra_items = NoExtraItems
1118-
fields = kwargs
1119-
elif kwargs:
1120-
raise TypeError("TypedDict takes either a dict or keyword arguments,"
1121-
" but not both")
1122-
if kwargs:
1123-
if sys.version_info >= (3, 13):
1124-
raise TypeError("TypedDict takes no keyword arguments")
1125-
warnings.warn(
1126-
"The kwargs-based syntax for TypedDict definitions is deprecated "
1127-
"in Python 3.11, will be removed in Python 3.13, and may not be "
1128-
"understood by third-party type checkers.",
1129-
DeprecationWarning,
1130-
stacklevel=2,
1131-
)
1132-
1133-
ns = {'__annotations__': dict(fields)}
1134-
module = _caller(depth=5 if __typing_is_inline__ else 2)
1135-
if module is not None:
1136-
# Setting correct module is necessary to make typed dict classes
1137-
# pickleable.
1138-
ns['__module__'] = module
1139-
1140-
td = _TypedDictMeta(typename, (), ns, total=total, closed=closed,
1141-
extra_items=extra_items)
1142-
td.__orig_bases__ = (TypedDict,)
1143-
return td
1154+
return _create_typeddict(
1155+
typename,
1156+
fields,
1157+
typing_is_inline=False,
1158+
total=total,
1159+
closed=closed,
1160+
extra_items=extra_items,
1161+
**kwargs,
1162+
)
11441163

11451164
@_ensure_subclassable(lambda bases: (_TypedDict,))
11461165
@_TypedDictSpecialForm
@@ -1199,8 +1218,14 @@ class Point2D(TypedDict):
11991218
"TypedDict[...] should be used with a single dict argument"
12001219
)
12011220

1202-
# Delegate to _TypedDictSpecialForm.__call__:
1203-
return self("<inlined TypedDict>", args[0], __typing_is_inline__=True)
1221+
return _create_typeddict(
1222+
"<inline TypedDict>",
1223+
args[0],
1224+
typing_is_inline=True,
1225+
total=True,
1226+
closed=None,
1227+
extra_items=NoExtraItems,
1228+
)
12041229

12051230
_TYPEDDICT_TYPES = (typing._TypedDictMeta, _TypedDictMeta)
12061231

0 commit comments

Comments
 (0)