| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent d32e8d6 commit 7b1f0f2
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2388,6 +2388,14 @@ These are not used in annotations. They are building blocks for declaring types. | |||
| 2388 | 2388 | .. versionchanged:: 3.13 | |
| 2389 | 2389 | Removed support for the keyword-argument method of creating ``TypedDict``\ s. | |
| 2390 | 2390 | ||
| 2391 | + .. deprecated-removed:: 3.13 3.15 | ||
| 2392 | + When using the functional syntax to create a TypedDict class, failing to | ||
| 2393 | + pass a value to the 'fields' parameter (``TD = TypedDict("TD")``) is | ||
| 2394 | + deprecated. Passing ``None`` to the 'fields' parameter | ||
| 2395 | + (``TD = TypedDict("TD", None)``) is also deprecated. Both will be | ||
| 2396 | + disallowed in Python 3.15. To create a TypedDict class with 0 fields, | ||
| 2397 | + use ``class TD(TypedDict): pass`` or ``TD = TypedDict("TD", {})``. | ||
| 2398 | + | ||
| 2391 | 2399 | Protocols | |
| 2392 | 2400 | --------- | |
| 2393 | 2401 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -146,12 +146,15 @@ Deprecated | |||
| 146 | 146 | be disallowed in Python 3.15. Use the class-based syntax or the functional | |
| 147 | 147 | syntax instead. (Contributed by Alex Waygood in :gh:`105566`.) | |
| 148 | 148 | * When using the functional syntax to create a :class:`typing.NamedTuple` | |
| 149 | - class, failing to pass a value to the 'fields' parameter | ||
| 150 | - (``NT = NamedTuple("NT")``) is deprecated. Passing ``None`` to the 'fields' | ||
| 151 | - parameter (``NT = NamedTuple("NT", None)``) is also deprecated. Both will be | ||
| 152 | - disallowed in Python 3.15. To create a NamedTuple class with 0 fields, use | ||
| 153 | - ``class NT(NamedTuple): pass`` or ``NT = NamedTuple("NT", [])``. | ||
| 154 | - (Contributed by Alex Waygood in :gh:`105566`.) | ||
| 149 | + class or a :class:`typing.TypedDict` class, failing to pass a value to the | ||
| 150 | + 'fields' parameter (``NT = NamedTuple("NT")`` or ``TD = TypedDict("TD")``) is | ||
| 151 | + deprecated. Passing ``None`` to the 'fields' parameter | ||
| 152 | + (``NT = NamedTuple("NT", None)`` or ``TD = TypedDict("TD", None)``) is also | ||
| 153 | + deprecated. Both will be disallowed in Python 3.15. To create a NamedTuple | ||
| 154 | + class with 0 fields, use ``class NT(NamedTuple): pass`` or | ||
| 155 | + ``NT = NamedTuple("NT", [])``. To create a TypedDict class with 0 fields, use | ||
| 156 | + ``class TD(TypedDict): pass`` or ``TD = TypedDict("TD", {})``. | ||
| 157 | + (Contributed by Alex Waygood in :gh:`105566` and :gh:`105570`.) | ||
| 155 | 158 | ||
| 156 | 159 | * :mod:`array`'s ``'u'`` format code, deprecated in docs since Python 3.3, | |
| 157 | 160 | emits :exc:`DeprecationWarning` since 3.13 | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7823,6 +7823,40 @@ class MultipleGenericBases(GenericParent[int], GenericParent[float]): | |||
| 7823 | 7823 | self.assertEqual(MultipleGenericBases.__orig_bases__, (GenericParent[int], GenericParent[float])) | |
| 7824 | 7824 | self.assertEqual(CallTypedDict.__orig_bases__, (TypedDict,)) | |
| 7825 | 7825 | ||
| 7826 | + def test_zero_fields_typeddicts(self): | ||
| 7827 | + T1 = TypedDict("T1", {}) | ||
| 7828 | + class T2(TypedDict): pass | ||
| 7829 | + class T3[tvar](TypedDict): pass | ||
| 7830 | + S = TypeVar("S") | ||
| 7831 | + class T4(TypedDict, Generic[S]): pass | ||
| 7832 | + | ||
| 7833 | + expected_warning = re.escape( | ||
| 7834 | + "Failing to pass a value for the 'fields' parameter is deprecated " | ||
| 7835 | + "and will be disallowed in Python 3.15. " | ||
| 7836 | + "To create a TypedDict class with 0 fields " | ||
| 7837 | + "using the functional syntax, " | ||
| 7838 | + "pass an empty dictionary, e.g. `T5 = TypedDict('T5', {})`." | ||
| 7839 | + ) | ||
| 7840 | + with self.assertWarnsRegex(DeprecationWarning, fr"^{expected_warning}$"): | ||
| 7841 | + T5 = TypedDict('T5') | ||
| 7842 | + | ||
| 7843 | + expected_warning = re.escape( | ||
| 7844 | + "Passing `None` as the 'fields' parameter is deprecated " | ||
| 7845 | + "and will be disallowed in Python 3.15. " | ||
| 7846 | + "To create a TypedDict class with 0 fields " | ||
| 7847 | + "using the functional syntax, " | ||
| 7848 | + "pass an empty dictionary, e.g. `T6 = TypedDict('T6', {})`." | ||
| 7849 | + ) | ||
| 7850 | + with self.assertWarnsRegex(DeprecationWarning, fr"^{expected_warning}$"): | ||
| 7851 | + T6 = TypedDict('T6', None) | ||
| 7852 | + | ||
| 7853 | + for klass in T1, T2, T3, T4, T5, T6: | ||
| 7854 | + with self.subTest(klass=klass.__name__): | ||
| 7855 | + self.assertEqual(klass.__annotations__, {}) | ||
| 7856 | + self.assertEqual(klass.__required_keys__, set()) | ||
| 7857 | + self.assertEqual(klass.__optional_keys__, set()) | ||
| 7858 | + self.assertIsInstance(klass(), dict) | ||
| 7859 | + | ||
| 7826 | 7860 | ||
| 7827 | 7861 | class RequiredTests(BaseTestCase): | |
| 7828 | 7862 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2908,7 +2908,7 @@ def __subclasscheck__(cls, other): | |||
| 2908 | 2908 | __instancecheck__ = __subclasscheck__ | |
| 2909 | 2909 | ||
| 2910 | 2910 | ||
| 2911 | - def TypedDict(typename, fields=None, /, *, total=True): | ||
| 2911 | + def TypedDict(typename, fields=_sentinel, /, *, total=True): | ||
| 2912 | 2912 | """A simple typed namespace. At runtime it is equivalent to a plain dict. | |
| 2913 | 2913 | ||
| 2914 | 2914 | TypedDict creates a dictionary type such that a type checker will expect all | |
@@ -2955,7 +2955,22 @@ class Point2D(TypedDict): | |||
| 2955 | 2955 | ||
| 2956 | 2956 | See PEP 655 for more details on Required and NotRequired. | |
| 2957 | 2957 | """ | |
| 2958 | - if fields is None: | ||
| 2958 | + if fields is _sentinel or fields is None: | ||
| 2959 | + import warnings | ||
| 2960 | + | ||
| 2961 | + if fields is _sentinel: | ||
| 2962 | + deprecated_thing = "Failing to pass a value for the 'fields' parameter" | ||
| 2963 | + else: | ||
| 2964 | + deprecated_thing = "Passing `None` as the 'fields' parameter" | ||
| 2965 | + | ||
| 2966 | + example = f"`{typename} = TypedDict({typename!r}, {{{{}}}})`" | ||
| 2967 | + deprecation_msg = ( | ||
| 2968 | + "{name} is deprecated and will be disallowed in Python {remove}. " | ||
| 2969 | + "To create a TypedDict class with 0 fields " | ||
| 2970 | + "using the functional syntax, " | ||
| 2971 | + "pass an empty dictionary, e.g. " | ||
| 2972 | + ) + example + "." | ||
| 2973 | + warnings._deprecated(deprecated_thing, message=deprecation_msg, remove=(3, 15)) | ||
| 2959 | 2974 | fields = {} | |
| 2960 | 2975 | ||
| 2961 | 2976 | ns = {'__annotations__': dict(fields)} | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,5 @@ | |||
| 1 | + Deprecate two methods of creating :class:`typing.TypedDict` classes with 0 | ||
| 2 | + fields using the functional syntax: ``TD = TypedDict("TD")`` and | ||
| 3 | + ``TD = TypedDict("TD", None)``. Both will be disallowed in Python 3.15. To create a | ||
| 4 | + ``TypedDict`` class with 0 fields, either use ``class TD(TypedDict): pass`` | ||
| 5 | + or ``TD = TypedDict("TD", {})``. | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments