|
19 | 19 | from typing import is_typeddict
|
20 | 20 | from typing import no_type_check, no_type_check_decorator
|
21 | 21 | from typing import Type
|
22 |
| -from typing import NewType |
23 | 22 | from typing import NamedTuple, TypedDict
|
24 | 23 | from typing import IO, TextIO, BinaryIO
|
25 | 24 | from typing import Pattern, Match
|
@@ -4302,6 +4301,93 @@ class Cat(Animal):
|
4302 | 4301 | 'voice': str,
|
4303 | 4302 | }
|
4304 | 4303 |
|
| 4304 | + def test_multiple_inheritance(self): |
| 4305 | + class One(TypedDict): |
| 4306 | + one: int |
| 4307 | + class Two(TypedDict): |
| 4308 | + two: str |
| 4309 | + class Untotal(TypedDict, total=False): |
| 4310 | + untotal: str |
| 4311 | + Inline = TypedDict('Inline', {'inline': bool}) |
| 4312 | + class Regular: |
| 4313 | + pass |
| 4314 | + |
| 4315 | + class Child(One, Two): |
| 4316 | + child: bool |
| 4317 | + self.assertEqual( |
| 4318 | + Child.__required_keys__, |
| 4319 | + frozenset(['one', 'two', 'child']), |
| 4320 | + ) |
| 4321 | + self.assertEqual( |
| 4322 | + Child.__optional_keys__, |
| 4323 | + frozenset([]), |
| 4324 | + ) |
| 4325 | + self.assertEqual( |
| 4326 | + Child.__annotations__, |
| 4327 | + {'one': int, 'two': str, 'child': bool}, |
| 4328 | + ) |
| 4329 | + |
| 4330 | + class ChildWithOptional(One, Untotal): |
| 4331 | + child: bool |
| 4332 | + self.assertEqual( |
| 4333 | + ChildWithOptional.__required_keys__, |
| 4334 | + frozenset(['one', 'child']), |
| 4335 | + ) |
| 4336 | + self.assertEqual( |
| 4337 | + ChildWithOptional.__optional_keys__, |
| 4338 | + frozenset(['untotal']), |
| 4339 | + ) |
| 4340 | + self.assertEqual( |
| 4341 | + ChildWithOptional.__annotations__, |
| 4342 | + {'one': int, 'untotal': str, 'child': bool}, |
| 4343 | + ) |
| 4344 | + |
| 4345 | + class ChildWithTotalFalse(One, Untotal, total=False): |
| 4346 | + child: bool |
| 4347 | + self.assertEqual( |
| 4348 | + ChildWithTotalFalse.__required_keys__, |
| 4349 | + frozenset(['one']), |
| 4350 | + ) |
| 4351 | + self.assertEqual( |
| 4352 | + ChildWithTotalFalse.__optional_keys__, |
| 4353 | + frozenset(['untotal', 'child']), |
| 4354 | + ) |
| 4355 | + self.assertEqual( |
| 4356 | + ChildWithTotalFalse.__annotations__, |
| 4357 | + {'one': int, 'untotal': str, 'child': bool}, |
| 4358 | + ) |
| 4359 | + |
| 4360 | + class ChildWithInlineAndOptional(Untotal, Inline): |
| 4361 | + child: bool |
| 4362 | + self.assertEqual( |
| 4363 | + ChildWithInlineAndOptional.__required_keys__, |
| 4364 | + frozenset(['inline', 'child']), |
| 4365 | + ) |
| 4366 | + self.assertEqual( |
| 4367 | + ChildWithInlineAndOptional.__optional_keys__, |
| 4368 | + frozenset(['untotal']), |
| 4369 | + ) |
| 4370 | + self.assertEqual( |
| 4371 | + ChildWithInlineAndOptional.__annotations__, |
| 4372 | + {'inline': bool, 'untotal': str, 'child': bool}, |
| 4373 | + ) |
| 4374 | + |
| 4375 | + wrong_bases = [ |
| 4376 | + (One, Regular), |
| 4377 | + (Regular, One), |
| 4378 | + (One, Two, Regular), |
| 4379 | + (Inline, Regular), |
| 4380 | + (Untotal, Regular), |
| 4381 | + ] |
| 4382 | + for bases in wrong_bases: |
| 4383 | + with self.subTest(bases=bases): |
| 4384 | + with self.assertRaisesRegex( |
| 4385 | + TypeError, |
| 4386 | + 'cannot inherit from both a TypedDict type and a non-TypedDict', |
| 4387 | + ): |
| 4388 | + class Wrong(*bases): |
| 4389 | + pass |
| 4390 | + |
4305 | 4391 | def test_is_typeddict(self):
|
4306 | 4392 | assert is_typeddict(Point2D) is True
|
4307 | 4393 | assert is_typeddict(Union[str, int]) is False
|
|
0 commit comments