@@ -846,13 +846,6 @@ def __round__(self, ndigits: int = 0) -> T_co:
846
846
pass
847
847
848
848
849
- def _ensure_subclassable (mro_entries ):
850
- def inner (obj ):
851
- obj .__mro_entries__ = mro_entries
852
- return obj
853
- return inner
854
-
855
-
856
849
_NEEDS_SINGLETONMETA = (
857
850
not hasattr (typing , "NoDefault" ) or not hasattr (typing , "NoExtraItems" )
858
851
)
@@ -1078,17 +1071,94 @@ def __subclasscheck__(cls, other):
1078
1071
1079
1072
_TypedDict = type .__new__ (_TypedDictMeta , 'TypedDict' , (), {})
1080
1073
1081
- @_ensure_subclassable (lambda bases : (_TypedDict ,))
1082
- def TypedDict (
1074
+ def _create_typeddict (
1083
1075
typename ,
1084
- fields = _marker ,
1076
+ fields ,
1085
1077
/ ,
1086
1078
* ,
1087
- total = True ,
1088
- closed = None ,
1089
- extra_items = NoExtraItems ,
1090
- ** kwargs
1079
+ typing_is_inline ,
1080
+ total ,
1081
+ closed ,
1082
+ extra_items ,
1083
+ ** kwargs ,
1091
1084
):
1085
+ if fields is _marker or fields is None :
1086
+ if fields is _marker :
1087
+ deprecated_thing = (
1088
+ "Failing to pass a value for the 'fields' parameter"
1089
+ )
1090
+ else :
1091
+ deprecated_thing = "Passing `None` as the 'fields' parameter"
1092
+
1093
+ example = f"`{ typename } = TypedDict({ typename !r} , {{}})`"
1094
+ deprecation_msg = (
1095
+ f"{ deprecated_thing } is deprecated and will be disallowed in "
1096
+ "Python 3.15. To create a TypedDict class with 0 fields "
1097
+ "using the functional syntax, pass an empty dictionary, e.g. "
1098
+ ) +
10000
example + "."
1099
+ warnings .warn (deprecation_msg , DeprecationWarning , stacklevel = 2 )
1100
+ # Support a field called "closed"
1101
+ if closed is not False and closed is not True and closed is not None :
1102
+ kwargs ["closed" ] = closed
1103
+ closed = None
1104
+ # Or "extra_items"
1105
+ if extra_items is not NoExtraItems :
1106
+ kwargs ["extra_items" ] = extra_items
1107
+ extra_items = NoExtraItems
1108
+ fields = kwargs
1109
+ elif kwargs :
1110
+ raise TypeError ("TypedDict takes either a dict or keyword arguments,"
1111
+ " but not both" )
1112
+ if kwargs :
1113
+ if sys .version_info >= (3 , 13 ):
1114
+ raise TypeError ("TypedDict takes no keyword arguments" )
1115
+ warnings .warn (
1116
+ "The kwargs-based syntax for TypedDict definitions is deprecated "
1117
+ "in Python 3.11, will be removed in Python 3.13, and may not be "
1118
+ "understood by third-party type checkers." ,
1119
+ DeprecationWarning ,
1120
+ stacklevel = 2 ,
1121
+ )
1122
+
1123
+ ns = {'__annotations__' : dict (fields )}
1124
+ module = _caller (depth = 5 if typing_is_inline else 3 )
1125
+ if module is not None :
1126
+ # Setting correct module is necessary to make typed dict classes
1127
+ # pickleable.
1128
+ ns ['__module__' ] = module
1129
+
1130
+ td = _TypedDictMeta (typename , (), ns , total = total , closed = closed ,
1131
+ extra_items = extra_items )
1132
+ td .__orig_bases__ = (TypedDict ,)
1133
+ return td
1134
+
1135
+ class _TypedDictSpecialForm (_ExtensionsSpecialForm , _root = True ):
1136
+ def __call__ (
1137
+ self ,
1138
+ typename ,
1139
+ fields = _marker ,
1140
+ / ,
1141
+ * ,
1142
+ total = True ,
1143
+ closed = None ,
1144
+ extra_items = NoExtraItems ,
1145
+ ** kwargs
1146
+ ):
1147
+ return _create_typeddict (
1148
+ typename ,
1149
+ fields ,
1150
+ typing_is_inline = False ,
1151
+ total = total ,
1152
+ closed = closed ,
1153
+ extra_items = extra_items ,
1154
+ ** kwargs ,
1155
+ )
1156
+
1157
+ def __mro_entries__ (self , bases ):
1158
+ return (_TypedDict ,)
1159
+
1160
+ @_TypedDictSpecialForm
1161
+ def TypedDict (self , args ):
1092
1162
"""A simple typed namespace. At runtime it is equivalent to a plain dict.
1093
1163
1094
1164
TypedDict creates a dictionary type such that a type checker will expect all
@@ -1135,52 +1205,20 @@ class Point2D(TypedDict):
1135
1205
1136
1206
See PEP 655 for more details on Required and NotRequired.
1137
1207
"""
1138
- if fields is _marker or fields is None :
1139
- if fields is _marker :
1140
- deprecated_thing = "Failing to pass a value for the 'fields' parameter"
1141
- else :
1142
- deprecated_thing = "Passing `None` as the 'fields' parameter"
1143
-
1144
- example = f"`{ typename } = TypedDict({ typename !r} , {{}})`"
1145
- deprecation_msg = (
1146
- f"{ deprecated_thing } is deprecated and will be disallowed in "
1147
- "Python 3.15. To create a TypedDict class with 0 fields "
1148
- "using the functional syntax, pass an empty dictionary, e.g. "
1149
- ) + example + "."
1150
- warnings .warn (deprecation_msg , DeprecationWarning , stacklevel = 2 )
1151
- # Support a field called "closed"
1152
- if closed is not False and closed is not True and closed is not None :
1153
- kwargs ["closed" ] = closed
1154
- closed = None
1155
- # Or "extra_items"
1156
- if extra_items is not NoExtraItems :
1157
- kwargs ["extra_items" ] = extra_items
1158
- extra_items = NoExtraItems
1159
- fields = kwargs
1160
- elif kwargs :
1161
- raise TypeError ("TypedDict takes either a dict or keyword arguments,"
1162
- " but not both" )
1163
- if kwargs :
1164
- if sys .version_info >= (3 , 13 ):
1165
- raise TypeError ("TypedDict takes no keyword arguments" )
1166
- warnings .warn (
1167
- "The kwargs-based syntax for TypedDict definitions is deprecated "
1168
- "in Python 3.11, will be removed in Python 3.13, and may not be "
1169
- "understood by third-party type checkers." ,
1170
- DeprecationWarning ,
1171
- stacklevel = 2 ,
1208
+ # This runs when creating inline TypedDicts:
1209
+ if not isinstance (args , dict ):
1210
+ raise TypeError (
<
10000
/td>1211
+ "TypedDict[...] should be used with a single dict argument"
1172
1212
)
1173
1213
1174
- ns = {'__annotations__' : dict (fields )}
1175
- module = _caller ()
1176
- if module is not None :
1177
- # Setting correct module is necessary to make typed dict classes pickleable.
1178
- ns ['__module__' ] = module
1179
-
1180
- td = _TypedDictMeta (typename , (), ns , total = total , closed = closed ,
1181
- extra_items = extra_items )
1182
- td .__orig_bases__ = (TypedDict ,)
1183
- return td
1214
+ return _create_typeddict (
1215
+ "<inline TypedDict>" ,
1216
+ args ,
1217
+ typing_is_inline = True ,
1218
+ total = True ,
1219
+ closed = True ,
1220
+ extra_items = NoExtraItems ,
1221
+ )
1184
1222
1185
1223
_TYPEDDICT_TYPES = (typing ._TypedDictMeta , _TypedDictMeta )
1186
1224
@@ -3194,7 +3232,6 @@ def _namedtuple_mro_entries(bases):
3194
3232
assert NamedTuple in bases
3195
3233
return (_NamedTuple ,)
3196
3234
3197
- @_ensure_subclassable (_namedtuple_mro_entries )
3198
3235
def NamedTuple (typename , fields = _marker , / , ** kwargs ):
3199
3236
"""Typed version of namedtuple.
3200
3237
@@ -3260,6 +3297,8 @@ class Employee(NamedTuple):
3260
3297
nt .__orig_bases__ = (NamedTuple ,)
3261
3298
return nt
3262
3299
3300
+ NamedTuple .__mro_entries__ = _namedtuple_mro_entries
3301
+
3263
3302
3264
3303
if hasattr (collections .abc , "Buffer" ):
3265
3304
Buffer = collections .abc .Buffer