import typing from marshmallow import fields, missing from marshmallow_annotations.converter import BaseConverter class SomeType: id: int name: typing.Optional[str] points: typing.List[float] def test_convert_from_typehint(registry_): converter = BaseConverter(registry=registry_) field = converter.convert(typing.Optional[int]) assert isinstance(field, fields.Integer) assert field.allow_none def test_pulls_options_from_passed_options(registry_): options = {"default": "it wasn't here"} converter = BaseConverter(registry=registry_) field = converter.convert(typing.Optional[str], options) assert isinstance(field, fields.String) assert field.default == "it wasn't here" def test_convert_all_generates_schema_fields_from_type(registry_): converter = BaseConverter(registry=registry_) generated_fields = converter.convert_all(SomeType) assert set(generated_fields.keys()) == {"id", "name", "points"} assert isinstance(generated_fields["id"], fields.Integer) assert isinstance(generated_fields["name"], fields.String) assert isinstance(generated_fields["points"], fields.List) assert isinstance(generated_fields["points"].container, fields.Float) def test_convert_all_generates_field_options_from_named_configs(registry_): converter = BaseConverter(registry=registry_) named_options = {"name": {"default": "it wasn't here"}} generated_fields = converter.convert_all(SomeType, configs=named_options) assert generated_fields["name"].default == "it wasn't here" def test_ignores_fields_passed_to_it_in_convert_all(registry_): converter = BaseConverter(registry=registry_) generated_fields = converter.convert_all(SomeType, ignore={"id", "name"}) assert (generated_fields.keys() & {"id", "name"}) == set() assert set(generated_fields.keys()) == {"points"} def test_ignores_classvar_when_generating_fields(registry_): class SomeOtherType(SomeType): frob: typing.ClassVar[int] = 0 converter = BaseConverter(registry=registry_) generated_fields = converter.convert_all(SomeOtherType) assert "frob" not in generated_fields def test_passes_interior_options_to_list_subtype(registry_): converter = BaseConverter(registry=registry_) opts = {"_interior": {"as_string": True}} field = converter.convert(typing.List[int], opts) assert field.container.as_string def test_defaults_missing(registry_): class FieldDefaultConverter(BaseConverter): def _get_field_defaults(self, item): return {"points": [1.0, 2.0]} converter = FieldDefaultConverter(registry=registry_) generated_fields = converter.convert_all(SomeType) assert generated_fields["id"].missing == missing assert generated_fields["name"].missing is None assert generated_fields["points"].missing == [1.0, 2.0] def test_override_missing(registry_): converter = BaseConverter(registry=registry_) named_options = {"points": {"missing": list}, "name": {"missing": "a"}} generated_fields = converter.convert_all(SomeType, configs=named_options) assert generated_fields["id"].missing == missing assert generated_fields["name"].missing == "a" assert generated_fields["points"].missing == list def test_can_convert_Dict_type_to_DictField(registry_): class HasDictField: mapping: typing.Dict[int, str] converter = BaseConverter(registry=registry_) generated_fields = converter.convert_all(HasDictField) assert isinstance(generated_fields["mapping"], fields.Dict)