@@ -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