Beispiel #1
0
def test_default_conversion_type_name():
    assert (
        print_schema(graphql_schema(query=[b]))
        == """\
type Query {
  b: B!
}

type B {
  a: Int!
}
"""
    )
    assert serialization_schema(B, all_refs=True) == {
        "$ref": "#/$defs/B",
        "$defs": {
            "B": {"$ref": "#/$defs/A"},
            "A": {
                "type": "object",
                "properties": {"a": {"type": "integer"}},
                "required": ["a"],
                "additionalProperties": False,
            },
        },
        "$schema": "http://json-schema.org/draft/2019-09/schema#",
    }
    assert serialization_schema(B) == {
        "type": "object",
        "properties": {"a": {"type": "integer"}},
        "required": ["a"],
        "additionalProperties": False,
        "$schema": "http://json-schema.org/draft/2019-09/schema#",
    }
Beispiel #2
0
def test_flattened_serialized():
    assert (serialization_schema(Base) == serialization_schema(WithFlattened)
            == base_schema)
    assert (serialize(Base, Base()) == serialize(WithFlattened,
                                                 WithFlattened()) == {
                                                     "serialized": 0
                                                 })
Beispiel #3
0
def test_inherited_serialized():
    assert (serialization_schema(Base) == serialization_schema(Inherited) ==
            serialization_schema(InheritedOverriden) == base_schema)
    assert (serialize(Base, Base()) == serialize(Inherited, Inherited()) == {
        "serialized": 0
    })
    assert serialize(InheritedOverriden, InheritedOverriden()) == {
        "serialized": 1
    }
Beispiel #4
0
def test_flattened_converted_error():
    with raises(TypeError):
        deserialize(Data3, {"attr": 0})
    with raises(TypeError):
        serialize(Data3, Data3(Field2(0)))
    with raises(TypeError):
        deserialization_schema(Data3)
    with raises(TypeError):
        serialization_schema(Data3)
    with raises(TypeError):
        graphql_schema(query=[get_data3])
Beispiel #5
0
def test_annotated_schema():
    assert (deserialization_schema(A) == serialization_schema(A) == {
        "$schema": "http://json-schema.org/draft/2019-09/schema#",
        "type": "object",
        "properties": {
            "a": {
                "type": "integer",
                "maximum": 10,
                "minimum": 0,
                "description": "field description",
            }
        },
        "required": ["a"],
        "additionalProperties": False,
    })
    assert (deserialization_schema(A, all_refs=True) == serialization_schema(
        A, all_refs=True) == {
            "$schema": "http://json-schema.org/draft/2019-09/schema#",
            "$ref": "#/$defs/A",
            "$defs": {
                "A": {
                    "additionalProperties": False,
                    "properties": {
                        "a": {
                            "$ref": "#/$defs/someInt",
                            "description": "field description",
                            "minimum": 0,
                        }
                    },
                    "required": ["a"],
                    "type": "object",
                },
                "someInt": {
                    "description": "type description",
                    "maximum": 10,
                    "type": "integer",
                },
            },
        })
    assert (print_schema(graphql_schema(query=[a])) == '''\
type Query {
  a: A!
}

type A {
  """field description"""
  a: someInt!
}

"""type description"""
scalar someInt
''')
Beispiel #6
0
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/2019-09/schema#",
    })
    assert deserialize(TD3, {
        "Key2": 0,
        "Key3": True
    }, aliaser=str.capitalize) == {
        "key2": 0,
        "key3": True,
    }
    with raises(ValidationError):
        assert deserialize(TD3, {})
    assert serialize(TD1, {"key1": ""}) == {"key1": ""}
Beispiel #7
0
def test_simple_dataclass_model(d_conv, s_conv, alias):
    assert deserialize(Data, {alias: 0}, conversion=d_conv) == Data(0)
    assert serialize(Data, Data(0), conversion=s_conv) == {alias: 0}
    assert (deserialization_schema(Data, conversion=d_conv) ==
            serialization_schema(Data, conversion=s_conv) == {
                "$schema": "http://json-schema.org/draft/2019-09/schema#",
                "type": "object",
                "properties": {
                    alias: {
                        "type": "integer"
                    }
                },
                "required": [alias],
                "additionalProperties": False,
            })
Beispiel #8
0
def test_field_generic_conversion():
    assert serialize(Foo[str], Foo({1: "a", 0: "b"})) == {"values": ["b", "a"]}
    assert serialization_schema(Foo[str]) == {
        "type": "object",
        "properties": {
            "values": {
                "type": "array",
                "items": {
                    "type": "string"
                }
            }
        },
        "required": ["values"],
        "additionalProperties": False,
        "$schema": "http://json-schema.org/draft/2019-09/schema#",
    }
Beispiel #9
0
def test_flattened_converted():
    data2 = deserialize(Data2, {"attr": 0})
    assert isinstance(data2.data_field2,
                      Field2) and data2.data_field2.attr == 0
    assert serialize(Data2, data2) == {"attr": 0}
    assert (deserialization_schema(Data) == serialization_schema(Data) == {
        "$schema":
        "http://json-schema.org/draft/2019-09/schema#",
        "type":
        "object",
        "allOf": [
            {
                "type": "object",
                "additionalProperties": False
            },
            {
                "type": "object",
                "properties": {
                    "attr": {
                        "type": "integer"
                    }
                },
                "required": ["attr"],
                "additionalProperties": False,
            },
        ],
        "unevaluatedProperties":
        False,
    })
    schema = graphql_schema(query=[get_data2])
    assert graphql_sync(schema, "{getData2{attr}}").data == {
        "getData2": {
            "attr": 0
        }
    }
    assert (print_schema(schema) == """\
type Query {
  getData2: Data2!
}

type Data2 {
  attr: Int!
}
""")
Beispiel #10
0
def test_resolver_position():
    assert serialization_schema(B) == {
        "type": "object",
        "properties": {
            "a": {
                "type": "integer"
            },
            "b": {
                "type": "integer"
            },
            "c": {
                "type": "integer"
            },
            "d": {
                "type": "integer"
            },
            "e": {
                "type": "integer"
            },
        },
        "required": ["a", "b", "c", "d", "e"],
        "additionalProperties": False,
        "$schema": "http://json-schema.org/draft/2019-09/schema#",
    }
    assert (print_schema(graphql_schema(query=[query])) == """\
type Query {
  query: B!
}

type B {
  a: Int!
  b: Int!
  c: Int!
  d: Int!
  e: Int!
}
""")
Beispiel #11
0
    pass


@dataclass
class Bar:
    pass


def foo_to_bar(_: Foo) -> Bar:
    return Bar()


type_name("Bars")(list[Bar])

assert serialization_schema(
    list[Foo], conversion=foo_to_bar, all_refs=True
) == {
    "$schema": "http://json-schema.org/draft/2019-09/schema#",
    "$ref": "#/$defs/Bars",
    "$defs": {
        # Bars is present because `list[Foo]` is dynamically converted to `list[Bar]`
        "Bars": {
            "type": "array",
            "items": {
                "$ref": "#/$defs/Bar"
            }
        },
        "Bar": {
            "type": "object",
            "additionalProperties": False
        },
Beispiel #12
0
def query_to_scalar(q: Query[T]) -> Optional[T]:
    ...


@dataclass
class FooModel:
    bar: int


class Foo:
    def serialize(self) -> FooModel:
        ...


assert serialization_schema(
    Query[Foo],
    conversion=Conversion(query_to_list, sub_conversion=Foo.serialize)) == {
        # We get an array of Foo
        "type": "array",
        "items": {
            "type": "object",
            "properties": {
                "bar": {
                    "type": "integer"
                }
            },
            "required": ["bar"],
            "additionalProperties": False,
        },
        "$schema": "http://json-schema.org/draft/2019-09/schema#",
    }
Beispiel #13
0
from enum import Enum

from apischema import deserialize, serialize
from apischema.conversions import as_names
from apischema.json_schema import deserialization_schema, serialization_schema


@as_names
class MyEnum(Enum):
    FOO = object()
    BAR = object()


assert deserialize(MyEnum, "FOO") == MyEnum.FOO
assert serialize(MyEnum, MyEnum.FOO) == "FOO"
assert (
    deserialization_schema(MyEnum)
    == serialization_schema(MyEnum)
    == {
        "$schema": "http://json-schema.org/draft/2019-09/schema#",
        "type": "string",
        "enum": ["FOO", "BAR"],
    }
)
Beispiel #14
0
from apischema.json_schema import deserialization_schema, serialization_schema
from apischema.tagged_unions import Tagged, TaggedUnion


@dataclass
class Bar:
    field: str


class Foo(TaggedUnion):
    bar: Tagged[Bar]
    baz: Tagged[int]


assert (deserialization_schema(Foo) == serialization_schema(Foo) == {
    "$schema": "http://json-schema.org/draft/2019-09/schema#",
    "type": "object",
    "properties": {
        "bar": {
            "type": "object",
            "properties": {
                "field": {
                    "type": "string"
                }
            },
            "required": ["field"],
            "additionalProperties": False,
        },
        "baz": {
            "type": "integer"
Beispiel #15
0
        )


@dataclass
class Foo(Base):
    foo: int


@dataclass
class Bar(Base):
    bar: str


assert (
    deserialization_schema(Base)
    == serialization_schema(Base)
    == {
        "anyOf": [
            {
                "type": "object",
                "properties": {"foo": {"type": "integer"}},
                "required": ["foo"],
                "additionalProperties": False,
            },
            {
                "type": "object",
                "properties": {"bar": {"type": "string"}},
                "required": ["bar"],
                "additionalProperties": False,
            },
        ],
Beispiel #16
0
from typing import TypeVar

from apischema import serialize
from apischema.json_schema import serialization_schema

T = TypeVar("T")
Priority = int


def sort_by_priority(
        values_with_priority: Mapping[T, Priority]) -> Sequence[T]:
    return [
        k for k, _ in sorted(values_with_priority.items(), key=itemgetter(1))
    ]


assert serialize(dict[str, Priority], {
    "a": 1,
    "b": 0
},
                 conversion=sort_by_priority) == ["b", "a"]
assert serialization_schema(dict[str, Priority],
                            conversion=sort_by_priority) == {
                                "$schema":
                                "http://json-schema.org/draft/2019-09/schema#",
                                "type": "array",
                                "items": {
                                    "type": "string"
                                },
                            }
Beispiel #17
0
def test_recursive_conversion_without_ref():
    tmp = None
    conversion = Conversion(rec_converter, sub_conversion=LazyConversion(lambda: tmp))
    tmp = conversion
    with raises(TypeError, match=r"Recursive type <.*> need a ref"):
        serialization_schema(RecConv, conversion=conversion)
Beispiel #18
0
    @property
    def value(self) -> T:
        if isinstance(self._value, RecoverableRaw):
            raise self._value
        return self._value

    @value.setter
    def value(self, value: T):
        self._value = value


deserializer(Recoverable)
serializer(Recoverable.value)

assert deserialize(Recoverable[int], 0).value == 0
with raises(RecoverableRaw) as err:
    _ = deserialize(Recoverable[int], "bad").value
assert err.value.raw == "bad"

assert serialize(Recoverable[int], Recoverable(0)) == 0
with raises(RecoverableRaw) as err:
    serialize(Recoverable[int], Recoverable(RecoverableRaw("bad")))
assert err.value.raw == "bad"

assert (deserialization_schema(Recoverable[int]) == serialization_schema(
    Recoverable[int]) == {
        "$schema": "http://json-schema.org/draft/2019-09/schema#",
        "type": "integer"
    })
    def value(self, value: T):
        self._value = value


deserializer(
    Recoverable,
    Union[T, Annotated[RecoverableRaw, Skip(schema_only=True)]],
    Recoverable[T],
)


@serializer
def serialize_recoverable(recoverable: Recoverable[T]) -> T:
    return recoverable.value


assert deserialize(Recoverable[int], 0).value == 0
with raises(RecoverableRaw) as err:
    assert deserialize(Recoverable[int], "bad").value
assert err.value.raw == "bad"

assert serialize(Recoverable(0)) == 0
with raises(RecoverableRaw) as err:
    assert serialize(Recoverable(RecoverableRaw("bad")))
assert err.value.raw == "bad"

assert (deserialization_schema(Recoverable[int]) == {
    "$schema": "http://json-schema.org/draft/2019-09/schema#",
    "type": "integer"
} == serialization_schema(Recoverable[int]))
Beispiel #20
0
from dataclasses import dataclass, field
from typing import Optional

from pytest import raises

from apischema import ValidationError, deserialize, serialize
from apischema.json_schema import deserialization_schema, serialization_schema
from apischema.metadata import none_as_undefined


@dataclass
class Foo:
    bar: Optional[str] = field(default=None, metadata=none_as_undefined)


assert (
    deserialization_schema(Foo)
    == serialization_schema(Foo)
    == {
        "$schema": "http://json-schema.org/draft/2019-09/schema#",
        "type": "object",
        "properties": {"bar": {"type": "string"}},
        "additionalProperties": False,
    }
)
with raises(ValidationError):
    deserialize(Foo, {"bar": None})
assert serialize(Foo, Foo(None)) == {}
from pytest import raises

from apischema import ValidationError, deserialize, deserializer, serialize, serializer
from apischema.json_schema import deserialization_schema, serialization_schema

T = TypeVar("T")


class Wrapper(Generic[T]):
    def __init__(self, wrapped: T):
        self.wrapped = wrapped

    # serializer methods of generic class are not handled in Python 3.6
    def unwrap(self) -> T:
        return self.wrapped


serializer(Wrapper.unwrap, Wrapper[T], T)
deserializer(Wrapper, T, Wrapper[T])


assert deserialize(Wrapper[list[int]], [0, 1]).wrapped == [0, 1]
with raises(ValidationError):
    deserialize(Wrapper[int], "wrapped")
assert serialize(Wrapper("wrapped")) == "wrapped"
assert (
    deserialization_schema(Wrapper[int])
    == {"$schema": "http://json-schema.org/draft/2019-09/schema#", "type": "integer"}
    == serialization_schema(Wrapper[int])
)
Beispiel #22
0
@schema(pattern=r"^#[0-9a-fA-F]{6}$")
@dataclass
class RGB:
    red: int
    green: int
    blue: int

    @serializer
    @property
    def hexa(self) -> str:
        return f"#{self.red:02x}{self.green:02x}{self.blue:02x}"


# serializer can also be called with methods/properties outside of the class
# For example, `serializer(RGB.hexa)` would have the same effect as the decorator above


@deserializer
def from_hexa(hexa: str) -> RGB:
    return RGB(int(hexa[1:3], 16), int(hexa[3:5], 16), int(hexa[5:7], 16))


assert deserialize(RGB, "#000000") == RGB(0, 0, 0)
assert serialize(RGB, RGB(0, 0, 42)) == "#00002a"
assert (deserialization_schema(RGB) == serialization_schema(RGB) == {
    "$schema": "http://json-schema.org/draft/2019-09/schema#",
    "type": "string",
    "pattern": "^#[0-9a-fA-F]{6}$",
})
Beispiel #23
0
def test_merged_serialized():
    assert serialization_schema(Base) == serialization_schema(
        WithMerged) == base_schema
    assert serialize(Base()) == serialize(WithMerged()) == {"serialized": 0}
Beispiel #24
0
from dataclasses import dataclass, field
from typing import Any

from apischema.json_schema import deserialization_schema, serialization_schema
from apischema.metadata import skip


@dataclass
class Foo:
    bar: Any
    deserialization_only: Any = field(metadata=skip(serialization=True))
    serialization_only: Any = field(default=None, metadata=skip(deserialization=True))
    baz: Any = field(default=None, metadata=skip)


assert deserialization_schema(Foo) == {
    "$schema": "http://json-schema.org/draft/2019-09/schema#",
    "type": "object",
    "properties": {"bar": {}, "deserialization_only": {}},
    "required": ["bar", "deserialization_only"],
    "additionalProperties": False,
}
assert serialization_schema(Foo) == {
    "$schema": "http://json-schema.org/draft/2019-09/schema#",
    "type": "object",
    "properties": {"bar": {}, "serialization_only": {}},
    "required": ["bar", "serialization_only"],
    "additionalProperties": False,
}
Beispiel #25
0
        ...


serialized(Foo.bar)


@serialized
def baz(foo: Foo[U]) -> U:
    ...


@dataclass
class FooInt(Foo[int]):
    ...


assert (serialization_schema(Foo[int]) == serialization_schema(FooInt) == {
    "$schema": "http://json-schema.org/draft/2019-09/schema#",
    "type": "object",
    "properties": {
        "bar": {
            "type": "integer"
        },
        "baz": {
            "type": "integer"
        }
    },
    "required": ["bar", "baz"],
    "additionalProperties": False,
})