1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
|
import sys
from datetime import date
from typing import Any, Dict, Mapping, TypedDict
import pytest
from apischema import ValidationError, deserialize, serialize
from apischema.json_schema import deserialization_schema, serialization_schema
from apischema.metadata import flatten
from apischema.typing import Annotated
if sys.version_info < (3, 9):
from typing_extensions import TypedDict # type: ignore # noqa
class MyDict(dict):
pass
@pytest.mark.parametrize(
"tp", [dict, Dict[int, Any], pytest.param(MyDict, marks=pytest.mark.xfail), Mapping]
)
def test_dict(tp):
with pytest.raises(ValueError, match="string-convertible keys"):
deserialization_schema(tp)
with pytest.raises(ValueError, match="string-convertible keys"):
serialization_schema(tp)
class TD1(TypedDict, total=False):
key1: str
class TD2(TypedDict):
key2: int
class TD3(TD1, TD2, total=False):
key3: bool
def test_typed_dict():
assert (
deserialization_schema(TD3)
== serialization_schema(TD3)
== {
"type": "object",
"properties": {
"key1": {"type": "string"},
"key2": {"type": "integer"},
"key3": {"type": "boolean"},
},
"required": ["key2"],
"additionalProperties": False,
"$schema": "http://json-schema.org/draft/2020-12/schema#",
}
)
assert deserialize(TD3, {"Key2": 0, "Key3": True}, aliaser=str.capitalize) == {
"key2": 0,
"key3": True,
}
with pytest.raises(ValidationError):
assert deserialize(TD3, {})
assert serialize(TD1, {"key1": ""}) == {"key1": ""}
class SimpleAdditional(TypedDict):
key: str
class ComplexAdditional(TypedDict):
key: date
class AggregateAdditional(TypedDict):
simple: Annotated[SimpleAdditional, flatten]
@pytest.mark.parametrize(
"cls", [SimpleAdditional, ComplexAdditional, AggregateAdditional]
)
def test_additional_properties(cls):
data = {"key": "1970-01-01", "additional": 42}
with pytest.raises(ValidationError):
deserialize(cls, data)
typed_dict = deserialize(cls, data, additional_properties=True)
assert typed_dict["additional"] == 42
assert "additional" not in serialize(cls, typed_dict)
assert serialize(cls, typed_dict, additional_properties=True)["additional"] == 42
|