Skip to content

Commit 65b88d5

Browse files
authored
bpo-46445: Cover multiple inheritance of TypedDict in test_typing (GH-30719)
1 parent 881a763 commit 65b88d5

File tree

1 file changed

+87
-1
lines changed

1 file changed

+87
-1
lines changed

Lib/test/test_typing.py

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
from typing import is_typeddict
2323
from typing import no_type_check, no_type_check_decorator
2424
from typing import Type
25-
from typing import NewType
2625
from typing import NamedTuple, TypedDict
2726
from typing import IO, TextIO, BinaryIO
2827
from typing import Pattern, Match
@@ -4393,6 +4392,93 @@ class Cat(Animal):
43934392
'voice': str,
43944393
}
43954394

4395+
def test_multiple_inheritance(self):
4396+
class One(TypedDict):
4397+
one: int
4398+
class Two(TypedDict):
4399+
two: str
4400+
class Untotal(TypedDict, total=False):
4401+
untotal: str
4402+
Inline = TypedDict('Inline', {'inline': bool})
4403+
class Regular:
4404+
pass
4405+
4406+
class Child(One, Two):
4407+
child: bool
4408+
self.assertEqual(
4409+
Child.__required_keys__,
4410+
frozenset(['one', 'two', 'child']),
4411+
)
4412+
self.assertEqual(
4413+
Child.__optional_keys__,
4414+
frozenset([]),
4415+
)
4416+
self.assertEqual(
4417+
Child.__annotations__,
4418+
{'one': int, 'two': str, 'child': bool},
4419+
)
4420+
4421+
class ChildWithOptional(One, Untotal):
4422+
child: bool
4423+
self.assertEqual(
4424+
ChildWithOptional.__required_keys__,
4425+
frozenset(['one', 'child']),
4426+
)
4427+
self.assertEqual(
4428+
ChildWithOptional.__optional_keys__,
4429+
frozenset(['untotal']),
4430+
)
4431+
self.assertEqual(
4432+
ChildWithOptional.__annotations__,
4433+
{'one': int, 'untotal': str, 'child': bool},
4434+
)
4435+
4436+
class ChildWithTotalFalse(One, Untotal, total=False):
4437+
child: bool
4438+
self.assertEqual(
4439+
ChildWithTotalFalse.__required_keys__,
4440+
frozenset(['one']),
4441+
)
4442+
self.assertEqual(
4443+
ChildWithTotalFalse.__optional_keys__,
4444+
frozenset(['untotal', 'child']),
4445+
)
4446+
self.assertEqual(
4447+
ChildWithTotalFalse.__annotations__,
4448+
{'one': int, 'untotal': str, 'child': bool},
4449+
)
4450+
4451+
class ChildWithInlineAndOptional(Untotal, Inline):
4452+
child: bool
4453+
self.assertEqual(
4454+
ChildWithInlineAndOptional.__required_keys__,
4455+
frozenset(['inline', 'child']),
4456+
)
4457+
self.assertEqual(
4458+
ChildWithInlineAndOptional.__optional_keys__,
4459+
frozenset(['untotal']),
4460+
)
4461+
self.assertEqual(
4462+
ChildWithInlineAndOptional.__annotations__,
4463+
{'inline': bool, 'untotal': str, 'child': bool},
4464+
)
4465+
4466+
wrong_bases = [
4467+
(One, Regular),
4468+
(Regular, One),
4469+
(One, Two, Regular),
4470+
(Inline, Regular),
4471+
(Untotal, Regular),
4472+
]
4473+
for bases in wrong_bases:
4474+
with self.subTest(bases=bases):
4475+
with self.assertRaisesRegex(
4476+
TypeError,
4477+
'cannot inherit from both a TypedDict type and a non-TypedDict',
4478+
):
4479+
class Wrong(*bases):
4480+
pass
4481+
43964482
def test_is_typeddict(self):
43974483
assert is_typeddict(Point2D) is True
43984484
assert is_typeddict(Union[str, int]) is False

0 commit comments

Comments
 (0)