From ff9dfbde61047a1fb5e3839f17498fe3fba5f005 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 5 Mar 2024 14:26:14 +0300 Subject: [PATCH 1/5] Make sure that `ReadOnly` is removed when using `get_type_hints(include_extra=False)` --- src/test_typing_extensions.py | 14 ++++++++++++++ src/typing_extensions.py | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py index 79c1b881..9b5a2130 100644 --- a/src/test_typing_extensions.py +++ b/src/test_typing_extensions.py @@ -4199,6 +4199,20 @@ class AllTheThings(TypedDict): self.assertEqual(AllTheThings.__readonly_keys__, frozenset({'a', 'b', 'c'})) self.assertEqual(AllTheThings.__mutable_keys__, frozenset({'d'})) + self.assertEqual( + get_type_hints(AllTheThings, include_extras=False), + {'a': int, 'b': int, 'c': int, 'd': int}, + ) + self.assertEqual( + get_type_hints(AllTheThings, include_extras=True), + { + 'a': typing.Annotated[typing.Required[typing.ReadOnly[int]], 'why not'], + 'b': typing.Required[typing.Annotated[typing.ReadOnly[int], 'why not']], + 'c': typing.ReadOnly[typing.NotRequired[typing.Annotated[int, 'why not']]], + 'd': typing.NotRequired[typing.Annotated[int, 'why not']], + }, + ) + def test_extra_keys_non_readonly(self): class Base(TypedDict, closed=True): __extra_items__: str diff --git a/src/typing_extensions.py b/src/typing_extensions.py index f3132ea4..6c04e151 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -1130,7 +1130,7 @@ def _strip_extras(t): """Strips Annotated, Required and NotRequired from a given type.""" if isinstance(t, _AnnotatedAlias): return _strip_extras(t.__origin__) - if hasattr(t, "__origin__") and t.__origin__ in (Required, NotRequired): + if hasattr(t, "__origin__") and t.__origin__ in (Required, NotRequired, ReadOnly): return _strip_extras(t.__args__[0]) if isinstance(t, typing._GenericAlias): stripped_args = tuple(_strip_extras(a) for a in t.__args__) From 726ecc68baf350e6b92b4258cf3d94c65150a93d Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 5 Mar 2024 14:28:23 +0300 Subject: [PATCH 2/5] Typo --- src/test_typing_extensions.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py index 9b5a2130..d48880ff 100644 --- a/src/test_typing_extensions.py +++ b/src/test_typing_extensions.py @@ -4206,10 +4206,10 @@ class AllTheThings(TypedDict): self.assertEqual( get_type_hints(AllTheThings, include_extras=True), { - 'a': typing.Annotated[typing.Required[typing.ReadOnly[int]], 'why not'], - 'b': typing.Required[typing.Annotated[typing.ReadOnly[int], 'why not']], - 'c': typing.ReadOnly[typing.NotRequired[typing.Annotated[int, 'why not']]], - 'd': typing.NotRequired[typing.Annotated[int, 'why not']], + 'a': Annotated[Required[ReadOnly[int]], 'why not'], + 'b': Required[Annotated[ReadOnly[int], 'why not']], + 'c': ReadOnly[NotRequired[Annotated[int, 'why not']]], + 'd': NotRequired[Annotated[int, 'why not']], }, ) From fac5aab8787bf42e890c9f05b5592ce05e3b922a Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 5 Mar 2024 14:31:45 +0300 Subject: [PATCH 3/5] Change the version availability --- src/typing_extensions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/typing_extensions.py b/src/typing_extensions.py index 6c04e151..4499c616 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -1122,9 +1122,9 @@ def greet(name: str) -> None: return val -if hasattr(typing, "Required"): # 3.11+ +if hasattr(typing, "ReadOnly"): # 3.13+ get_type_hints = typing.get_type_hints -else: # <=3.10 +else: # <=3.13 # replaces _strip_annotations() def _strip_extras(t): """Strips Annotated, Required and NotRequired from a given type.""" From e7b726390702f3cc376d68b98b66b115e16900bd Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Wed, 6 Mar 2024 10:57:33 +0300 Subject: [PATCH 4/5] Update index.rst --- doc/index.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/index.rst b/doc/index.rst index 63082ddd..bdf94c75 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -760,6 +760,11 @@ Functions Interaction with :data:`Required` and :data:`NotRequired`. + .. versionchanged:: 4.11.0 + + When ``include_extra=False``, ``get_type_hints()`` now strips + :data:`ReadOnly` from the annotation. + .. function:: is_protocol(tp) Determine if a type is a :class:`Protocol`. This works with protocols From d7494c854e0d4105ef2d40894a4b4b802b51100c Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Wed, 6 Mar 2024 10:58:46 +0300 Subject: [PATCH 5/5] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07fc328d..a545e25b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# Release 4.11.0 (WIP) + +- When `include_extra=False`, `get_type_hints()` now strips `ReadOnly` from the annotation. + # Release 4.10.0 (February 24, 2024) This feature release adds support for PEP 728 (TypedDict with extra