|
22 | 22 | from typing import is_typeddict
|
23 | 23 | from typing import no_type_check, no_type_check_decorator
|
24 | 24 | from typing import Type
|
25 |
| -from typing import NewType |
26 | 25 | from typing import NamedTuple, TypedDict
|
27 | 26 | from typing import IO, TextIO, BinaryIO
|
28 | 27 | from typing import Pattern, Match
|
@@ -4393,6 +4392,93 @@ class Cat(Animal):
|
4393 | 4392 | 'voice': str,
|
4394 | 4393 | }
|
4395 | 4394 |
|
| 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 | + |
4396 | 4482 | def test_is_typeddict(self):
|
4397 | 4483 | assert is_typeddict(Point2D) is True
|
4398 | 4484 | assert is_typeddict(Union[str, int]) is False
|
|
0 commit comments