From df08fcec5f281ba01266869ec55368819aed0a77 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Sat, 12 Aug 2023 18:27:35 +0100 Subject: [PATCH] Improve `__(r)or__` signatures for TypedDict classes (#10565) --- stdlib/typing.pyi | 10 +++++++++- stdlib/typing_extensions.pyi | 10 +++++++++- stubs/mypy-extensions/mypy_extensions.pyi | 12 ++++++++++-- tests/stubtest_allowlists/py310.txt | 10 ---------- tests/stubtest_allowlists/py311.txt | 10 ---------- tests/stubtest_allowlists/py312.txt | 10 ---------- tests/stubtest_allowlists/py39.txt | 10 ---------- tests/stubtest_allowlists/py3_common.txt | 1 + 8 files changed, 29 insertions(+), 44 deletions(-) diff --git a/stdlib/typing.pyi b/stdlib/typing.pyi index 6a3073686..a9bffdf52 100644 --- a/stdlib/typing.pyi +++ b/stdlib/typing.pyi @@ -900,8 +900,16 @@ class _TypedDict(Mapping[str, object], metaclass=ABCMeta): def keys(self) -> dict_keys[str, object]: ... def values(self) -> dict_values[str, object]: ... if sys.version_info >= (3, 9): + @overload def __or__(self, __value: typing_extensions.Self) -> typing_extensions.Self: ... - def __ior__(self, __value: typing_extensions.Self) -> typing_extensions.Self: ... + @overload + def __or__(self, __value: dict[str, Any]) -> dict[str, object]: ... + @overload + def __ror__(self, __value: typing_extensions.Self) -> typing_extensions.Self: ... + @overload + def __ror__(self, __value: dict[str, Any]) -> dict[str, object]: ... + # supposedly incompatible definitions of __or__ and __ior__ + def __ior__(self, __value: typing_extensions.Self) -> typing_extensions.Self: ... # type: ignore[misc] @_final class ForwardRef: diff --git a/stdlib/typing_extensions.pyi b/stdlib/typing_extensions.pyi index efcc13e42..9320dc50b 100644 --- a/stdlib/typing_extensions.pyi +++ b/stdlib/typing_extensions.pyi @@ -233,8 +233,16 @@ class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): def values(self) -> dict_values[str, object]: ... def __delitem__(self, k: Never) -> None: ... if sys.version_info >= (3, 9): + @overload def __or__(self, __value: Self) -> Self: ... - def __ior__(self, __value: Self) -> Self: ... + @overload + def __or__(self, __value: dict[str, Any]) -> dict[str, object]: ... + @overload + def __ror__(self, __value: Self) -> Self: ... + @overload + def __ror__(self, __value: dict[str, Any]) -> dict[str, object]: ... + # supposedly incompatible definitions of `__ior__` and `__or__`: + def __ior__(self, __value: Self) -> Self: ... # type: ignore[misc] # TypedDict is a (non-subscriptable) special form. TypedDict: object diff --git a/stubs/mypy-extensions/mypy_extensions.pyi b/stubs/mypy-extensions/mypy_extensions.pyi index 8565793c2..ab0e3cf84 100644 --- a/stubs/mypy-extensions/mypy_extensions.pyi +++ b/stubs/mypy-extensions/mypy_extensions.pyi @@ -28,8 +28,16 @@ class _TypedDict(Mapping[str, object], metaclass=abc.ABCMeta): def values(self) -> dict_values[str, object]: ... def __delitem__(self, k: Never) -> None: ... if sys.version_info >= (3, 9): - def __or__(self, __other: Self) -> Self: ... - def __ior__(self, __other: Self) -> Self: ... + @overload + def __or__(self, __value: Self) -> Self: ... + @overload + def __or__(self, __value: dict[str, Any]) -> dict[str, object]: ... + @overload + def __ror__(self, __value: Self) -> Self: ... + @overload + def __ror__(self, __value: dict[str, Any]) -> dict[str, object]: ... + # supposedly incompatible definitions of `__or__` and `__ior__`: + def __ior__(self, __value: Self) -> Self: ... # type: ignore[misc] def TypedDict(typename: str, fields: dict[str, type[Any]], total: bool = ...) -> type[dict[str, Any]]: ... @overload diff --git a/tests/stubtest_allowlists/py310.txt b/tests/stubtest_allowlists/py310.txt index fb8170366..1a8fd567b 100644 --- a/tests/stubtest_allowlists/py310.txt +++ b/tests/stubtest_allowlists/py310.txt @@ -42,16 +42,6 @@ types.GenericAlias.__getattr__ types.GenericAlias.__mro_entries__ types.GenericAlias.__call__ # Would be complicated to fix properly, Any could silence problems. #6392 typing._SpecialForm.__mro_entries__ -typing._TypedDict.__delitem__ -typing._TypedDict.__ior__ -typing._TypedDict.__or__ -typing._TypedDict.copy -typing._TypedDict.items -typing._TypedDict.keys -typing._TypedDict.pop -typing._TypedDict.setdefault -typing._TypedDict.update -typing._TypedDict.values weakref.ProxyType.__reversed__ # Doesn't really exist weakref.WeakValueDictionary.update typing_extensions\.get_original_bases diff --git a/tests/stubtest_allowlists/py311.txt b/tests/stubtest_allowlists/py311.txt index dfcbed1f1..d8834e923 100644 --- a/tests/stubtest_allowlists/py311.txt +++ b/tests/stubtest_allowlists/py311.txt @@ -134,16 +134,6 @@ unittest.case.TestCase.__init_subclass__ # Super-special typing primitives typing\._SpecialForm.* -typing._TypedDict.__delitem__ -typing._TypedDict.__ior__ -typing._TypedDict.__or__ -typing._TypedDict.copy -typing._TypedDict.items -typing._TypedDict.keys -typing._TypedDict.pop -typing._TypedDict.setdefault -typing._TypedDict.update -typing._TypedDict.values typing_extensions\.Final typing\.NamedTuple typing\.LiteralString diff --git a/tests/stubtest_allowlists/py312.txt b/tests/stubtest_allowlists/py312.txt index 468c3057d..c0beeaea9 100644 --- a/tests/stubtest_allowlists/py312.txt +++ b/tests/stubtest_allowlists/py312.txt @@ -227,16 +227,6 @@ unittest.case.TestCase.__init_subclass__ # Super-special typing primitives typing\._SpecialForm.* -typing._TypedDict.__delitem__ -typing._TypedDict.__ior__ -typing._TypedDict.__or__ -typing._TypedDict.copy -typing._TypedDict.items -typing._TypedDict.keys -typing._TypedDict.pop -typing._TypedDict.setdefault -typing._TypedDict.update -typing._TypedDict.values typing_extensions\.Final typing\.NamedTuple typing\.LiteralString diff --git a/tests/stubtest_allowlists/py39.txt b/tests/stubtest_allowlists/py39.txt index def53fd29..f43cfd20a 100644 --- a/tests/stubtest_allowlists/py39.txt +++ b/tests/stubtest_allowlists/py39.txt @@ -63,16 +63,6 @@ tkinter.Tk.split types.CodeType.replace # stubtest thinks default values are None but None doesn't work at runtime types.GenericAlias.__getattr__ types.GenericAlias.__call__ # Would be complicated to fix properly, Any could silence problems. #6392 -typing._TypedDict.__delitem__ -typing._TypedDict.__ior__ -typing._TypedDict.__or__ -typing._TypedDict.copy -typing._TypedDict.items -typing._TypedDict.keys -typing._TypedDict.pop -typing._TypedDict.setdefault -typing._TypedDict.update -typing._TypedDict.values weakref.ProxyType.__reversed__ # Doesn't really exist weakref.WeakValueDictionary.update typing_extensions\.get_original_bases diff --git a/tests/stubtest_allowlists/py3_common.txt b/tests/stubtest_allowlists/py3_common.txt index c38a3b94e..223a350bc 100644 --- a/tests/stubtest_allowlists/py3_common.txt +++ b/tests/stubtest_allowlists/py3_common.txt @@ -385,6 +385,7 @@ typing_extensions\.TypeVar.* typing_extensions\.ParamSpec.* typing(_extensions)?\.Generic typing\.Protocol +(typing\._TypedDict\..+)? typing_extensions\._TypedDict\..* # Special primitives