gh-116127: PEP-705: Add ReadOnly support for TypedDict (#116350)

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
This commit is contained in:
Nikita Sobolev 2024-03-12 17:49:39 +03:00 committed by GitHub
parent 3265087c07
commit df4784b3b7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 182 additions and 11 deletions

View file

@ -31,7 +31,7 @@ from typing import reveal_type
from typing import dataclass_transform
from typing import no_type_check, no_type_check_decorator
from typing import Type
from typing import NamedTuple, NotRequired, Required, TypedDict
from typing import NamedTuple, NotRequired, Required, ReadOnly, TypedDict
from typing import IO, TextIO, BinaryIO
from typing import Pattern, Match
from typing import Annotated, ForwardRef
@ -8322,6 +8322,69 @@ class TypedDictTests(BaseTestCase):
self.assertEqual(klass.__optional_keys__, set())
self.assertIsInstance(klass(), dict)
def test_readonly_inheritance(self):
class Base1(TypedDict):
a: ReadOnly[int]
class Child1(Base1):
b: str
self.assertEqual(Child1.__readonly_keys__, frozenset({'a'}))
self.assertEqual(Child1.__mutable_keys__, frozenset({'b'}))
class Base2(TypedDict):
a: ReadOnly[int]
class Child2(Base2):
b: str
self.assertEqual(Child1.__readonly_keys__, frozenset({'a'}))
self.assertEqual(Child1.__mutable_keys__, frozenset({'b'}))
def test_cannot_make_mutable_key_readonly(self):
class Base(TypedDict):
a: int
with self.assertRaises(TypeError):
class Child(Base):
a: ReadOnly[int]
def test_can_make_readonly_key_mutable(self):
class Base(TypedDict):
a: ReadOnly[int]
class Child(Base):
a: int
self.assertEqual(Child.__readonly_keys__, frozenset())
self.assertEqual(Child.__mutable_keys__, frozenset({'a'}))
def test_combine_qualifiers(self):
class AllTheThings(TypedDict):
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"]]
self.assertEqual(AllTheThings.__required_keys__, frozenset({'a', 'b'}))
self.assertEqual(AllTheThings.__optional_keys__, frozenset({'c', 'd'}))
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': 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']],
},
)
class RequiredTests(BaseTestCase):