|
18 | 18 | import desert |
19 | 19 |
|
20 | 20 |
|
| 21 | +typed_dict_classes: t.List[t.Any] = [typing_extensions.TypedDict] |
| 22 | +if sys.version_info >= (3, 8): |
| 23 | + typed_dict_classes.append(t.TypedDict) |
| 24 | + |
| 25 | + |
21 | 26 | @attr.frozen(order=False) |
22 | 27 | class DataclassModule: |
23 | 28 | """Implementation of a dataclass module like attr or dataclasses.""" |
@@ -45,6 +50,13 @@ def dataclass_param(request: _pytest.fixtures.SubRequest) -> DataclassModule: |
45 | 50 | return module |
46 | 51 |
|
47 | 52 |
|
| 53 | +@pytest.fixture( |
| 54 | + params=typed_dict_classes, ids=[x.__module__ for x in typed_dict_classes] |
| 55 | +) |
| 56 | +def typed_dict_class(request: _pytest.fixtures.SubRequest) -> t.Any: |
| 57 | + return request.param |
| 58 | + |
| 59 | + |
48 | 60 | class AssertLoadDumpProtocol(typing_extensions.Protocol): |
49 | 61 | def __call__( |
50 | 62 | self, schema: marshmallow.Schema, loaded: t.Any, dumped: t.Dict[t.Any, t.Any] |
@@ -437,6 +449,27 @@ class A: |
437 | 449 | assert_dump_load(schema=schema, loaded=loaded, dumped=dumped) |
438 | 450 |
|
439 | 451 |
|
| 452 | +def test_typed_dict( |
| 453 | + module: DataclassModule, |
| 454 | + assert_dump_load: AssertLoadDumpProtocol, |
| 455 | + typed_dict_class: t.Type[t.Any], |
| 456 | +) -> None: |
| 457 | + """Test dataclasses with basic TypedDict support""" |
| 458 | + |
| 459 | + class B(typed_dict_class): # type: ignore[valid-type, misc] |
| 460 | + x: int |
| 461 | + |
| 462 | + @module.dataclass |
| 463 | + class A: |
| 464 | + x: B |
| 465 | + |
| 466 | + schema = desert.schema_class(A)() |
| 467 | + dumped = {"x": {"x": 1}} |
| 468 | + loaded = A(x={"x": 1}) # type: ignore[call-arg] |
| 469 | + |
| 470 | + assert_dump_load(schema=schema, loaded=loaded, dumped=dumped) |
| 471 | + |
| 472 | + |
440 | 473 | @pytest.mark.xfail( |
441 | 474 | strict=True, |
442 | 475 | reason=( |
|
0 commit comments