def test_data_key(self): registry = ConverterRegistry() registry.register_types(ALL_CONVERTERS) class Foo(m.Schema): a = m.fields.Integer(data_key="b", required=True) schema = Foo() json_schema = registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": {"b": {"type": "integer"}}, "required": ["b"], }, )
def test_load_from(self): registry = ConverterRegistry(direction=IN) registry.register_types(ALL_CONVERTERS) class Foo(m.Schema): a = m.fields.Integer(load_from='b', required=True) schema = Foo() json_schema = registry.convert(schema) self.assertEqual( json_schema, { 'type': 'object', 'title': 'Foo', 'properties': { 'b': { 'type': 'integer' } }, 'required': ['b'] })
def setUp(self): self.registry = ConverterRegistry() self.registry.register_types(ALL_CONVERTERS)
class TestConverterRegistry(unittest.TestCase): def setUp(self): self.registry = ConverterRegistry() self.registry.register_types(ALL_CONVERTERS) def test_primitive_types(self): for field, result in [ (m.fields.Integer(), { 'type': 'integer' }), (m.fields.String(), { 'type': 'string' }), (m.fields.Number(), { 'type': 'number' }), (m.fields.DateTime(), { 'type': 'string', 'format': 'date-time' }), (m.fields.Date(), { 'type': 'string', 'format': 'date' }), (m.fields.UUID(), { 'type': 'string', 'format': 'uuid' }), (m.fields.Boolean(), { 'type': 'boolean' }), (m.fields.URL(), { 'type': 'string' }), (m.fields.Email(), { 'type': 'string' }), (m.fields.Constant('foo'), { 'enum': ['foo'], 'default': 'foo' }), (m.fields.Integer(missing=5), { 'type': 'integer', 'default': 5 }), (m.fields.Integer(missing=lambda: 5), { 'type': 'integer' }), (m.fields.Integer(allow_none=True), { 'type': 'integer', 'x-nullable': True }), (m.fields.List(m.fields.Integer()), { 'type': 'array', 'items': { 'type': 'integer' } }), (m.fields.List(m.fields.Integer), { 'type': 'array', 'items': { 'type': 'integer' } }), (m.fields.Integer(description='blam!'), { 'type': 'integer', 'description': 'blam!' }), (QueryParamList(m.fields.Integer()), { 'type': 'array', 'items': { 'type': 'integer' }, 'collectionFormat': 'multi' }), (CommaSeparatedList(m.fields.Integer()), { 'type': 'array', 'items': { 'type': 'integer' }, 'collectionFormat': 'csv' }), (m.fields.Integer(validate=v.Range(min=1)), { 'type': 'integer', 'minimum': 1 }), (m.fields.Integer(validate=v.Range(max=9)), { 'type': 'integer', 'maximum': 9 }), (m.fields.List(m.fields.Integer(), validate=v.Length(min=1)), { 'type': 'array', 'items': { 'type': 'integer' }, 'minItems': 1 }), (m.fields.List(m.fields.Integer(), validate=v.Length(max=9)), { 'type': 'array', 'items': { 'type': 'integer' }, 'maxItems': 9 }), (m.fields.String(validate=v.Length(min=1)), { 'type': 'string', 'minLength': 1 }), (m.fields.String(validate=v.Length(max=9)), { 'type': 'string', 'maxLength': 9 }), (m.fields.String(validate=v.OneOf(['a', 'b'])), { 'type': 'string', 'enum': ['a', 'b'] }), (m.fields.Dict(), { 'type': 'object' }), (m.fields.Method(serialize='x', deserialize='y', swagger_type='integer'), { 'type': 'integer' }), (m.fields.Function(serialize=lambda _: _, deserialize=lambda _: _, swagger_type='string'), { 'type': 'string' }), (m.fields.Integer(validate=lambda value: True), { 'type': 'integer' }), ]: class Foo(m.Schema): a = field schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual(json_schema, { 'type': 'object', 'title': 'Foo', 'properties': { 'a': result } }) def test_dump_to(self): class Foo(m.Schema): a = m.fields.Integer(dump_to='b', required=True) schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { 'type': 'object', 'title': 'Foo', 'properties': { 'b': { 'type': 'integer' } }, 'required': ['b'] }) def test_load_from(self): registry = ConverterRegistry(direction=IN) registry.register_types(ALL_CONVERTERS) class Foo(m.Schema): a = m.fields.Integer(load_from='b', required=True) schema = Foo() json_schema = registry.convert(schema) self.assertEqual( json_schema, { 'type': 'object', 'title': 'Foo', 'properties': { 'b': { 'type': 'integer' } }, 'required': ['b'] }) def test_required(self): class Foo(m.Schema): a = m.fields.Integer(required=True) schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { 'type': 'object', 'title': 'Foo', 'properties': { 'a': { 'type': 'integer' } }, 'required': ['a'] }) def test_object_description(self): class Foo(m.Schema): """I'm the description!""" a = m.fields.Integer() schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { 'type': 'object', 'title': 'Foo', 'description': "I'm the description!", 'properties': { 'a': { 'type': 'integer' } } }) def test_nested(self): class Bar(m.Schema): a = m.fields.Integer() class Foo(m.Schema): a = m.fields.Nested(Bar) schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { 'type': 'object', 'title': 'Foo', 'properties': { 'a': { 'type': 'object', 'title': 'Bar', 'properties': { 'a': { 'type': 'integer' } } } } }) def test_many(self): class Foo(m.Schema): a = m.fields.Integer() schema = Foo(many=True) json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { 'type': 'array', 'items': { 'type': 'object', 'title': 'Foo', 'properties': { 'a': { 'type': 'integer' } } } }) def test_nested_many(self): class Bar(m.Schema): a = m.fields.Integer() class Foo(m.Schema): a = m.fields.Nested(Bar, many=True) schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { 'type': 'object', 'title': 'Foo', 'properties': { 'a': { 'type': 'array', 'items': { 'type': 'object', 'title': 'Bar', 'properties': { 'a': { 'type': 'integer' } } } } } }) def test_inheritance(self): class Foo(m.Schema): a = m.fields.Integer() class Bar(Foo): b = m.fields.Integer() schema = Bar() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { 'type': 'object', 'title': 'Bar', 'properties': { 'a': { 'type': 'integer' }, 'b': { 'type': 'integer' } } }) def test_converters_are_checked_up_the_mro_chain(self): class CustomString(m.fields.String): pass class Foo(m.Schema): a = CustomString() schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { 'type': 'object', 'title': 'Foo', 'properties': { 'a': { 'type': 'string' } } }) def test_additional_properties(self): class Foo(DisallowExtraFieldsMixin, m.Schema): a = m.fields.Integer() schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { 'type': 'object', 'title': 'Foo', 'properties': { 'a': { 'type': 'integer' } }, 'additionalProperties': False })
class TestConverterRegistry(unittest.TestCase): def setUp(self): self.registry = ConverterRegistry() self.registry.register_types(ALL_CONVERTERS) def test_primitive_types(self): for field, result in [ (m.fields.Integer(), { "type": "integer" }), (m.fields.String(), { "type": "string" }), (m.fields.Number(), { "type": "number" }), (m.fields.DateTime(), { "type": "string", "format": "date-time" }), (m.fields.Date(), { "type": "string", "format": "date" }), (m.fields.UUID(), { "type": "string", "format": "uuid" }), (m.fields.Boolean(), { "type": "boolean" }), (m.fields.URL(), { "type": "string" }), (m.fields.Email(), { "type": "string" }), (m.fields.Constant("foo"), { "enum": ["foo"], "default": "foo" }), (m.fields.Integer(missing=5), { "type": "integer", "default": 5 }), (m.fields.Integer(dump_only=True), { "type": "integer", "readOnly": True }), (m.fields.Integer(missing=lambda: 5), { "type": "integer" }), ( m.fields.Integer(allow_none=True), { "type": "integer", "x-nullable": True }, ), ( m.fields.List(m.fields.Integer()), { "type": "array", "items": { "type": "integer" } }, ), ( m.fields.List(m.fields.Integer), { "type": "array", "items": { "type": "integer" } }, ), ( m.fields.Integer(description="blam!"), { "type": "integer", "description": "blam!" }, ), ( QueryParamList(m.fields.Integer()), { "type": "array", "items": { "type": "integer" }, "collectionFormat": "multi", }, ), ( CommaSeparatedList(m.fields.Integer()), { "type": "array", "items": { "type": "integer" }, "collectionFormat": "csv", }, ), ( m.fields.Integer(validate=v.Range(min=1)), { "type": "integer", "minimum": 1 }, ), ( m.fields.Integer(validate=v.Range(max=9)), { "type": "integer", "maximum": 9 }, ), ( m.fields.List(m.fields.Integer(), validate=v.Length(min=1)), { "type": "array", "items": { "type": "integer" }, "minItems": 1 }, ), ( m.fields.List(m.fields.Integer(), validate=v.Length(max=9)), { "type": "array", "items": { "type": "integer" }, "maxItems": 9 }, ), ( m.fields.String(validate=v.Length(min=1)), { "type": "string", "minLength": 1 }, ), ( m.fields.String(validate=v.Length(max=9)), { "type": "string", "maxLength": 9 }, ), ( m.fields.String(validate=v.OneOf(["a", "b"])), { "type": "string", "enum": ["a", "b"] }, ), (m.fields.Dict(), { "type": "object" }), ( m.fields.Method(serialize="x", deserialize="y", swagger_type="integer"), { "type": "integer" }, ), ( m.fields.Function( serialize=lambda _: _, deserialize=lambda _: _, swagger_type="string", ), { "type": "string" }, ), (m.fields.Integer(validate=lambda value: True), { "type": "integer" }), ]: class Foo(m.Schema): a = field schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": { "a": result } }, ) @skip_if_marshmallow_not_v2 def test_dump_to(self): class Foo(m.Schema): a = m.fields.Integer(dump_to="b", required=True) schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": { "b": { "type": "integer" } }, "required": ["b"], }, ) @skip_if_marshmallow_not_v2 def test_load_from(self): registry = ConverterRegistry() registry.register_types(ALL_CONVERTERS) class Foo(m.Schema): a = m.fields.Integer(load_from="b", required=True) schema = Foo() json_schema = registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": { "b": { "type": "integer" } }, "required": ["b"], }, ) @skip_if_marshmallow_not_v3 def test_data_key(self): registry = ConverterRegistry() registry.register_types(ALL_CONVERTERS) class Foo(m.Schema): a = m.fields.Integer(data_key="b", required=True) schema = Foo() json_schema = registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": { "b": { "type": "integer" } }, "required": ["b"], }, ) def test_required(self): class Foo(m.Schema): a = m.fields.Integer(required=True) schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": { "a": { "type": "integer" } }, "required": ["a"], }, ) def test_object_description(self): class Foo(m.Schema): """I'm the description!""" a = m.fields.Integer() schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "description": "I'm the description!", "properties": { "a": { "type": "integer" } }, }, ) def test_nested(self): class Bar(m.Schema): a = m.fields.Integer() class Foo(m.Schema): a = m.fields.Nested(Bar) schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": { "a": { "type": "object", "title": "Bar", "properties": { "a": { "type": "integer" } }, } }, }, ) def test_many(self): class Foo(m.Schema): a = m.fields.Integer() schema = Foo(many=True) json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "array", "items": { "type": "object", "title": "Foo", "properties": { "a": { "type": "integer" } }, }, }, ) def test_nested_many(self): class Bar(m.Schema): a = m.fields.Integer() class Foo(m.Schema): a = m.fields.Nested(Bar, many=True) schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": { "a": { "type": "array", "items": { "type": "object", "title": "Bar", "properties": { "a": { "type": "integer" } }, }, } }, }, ) def test_inheritance(self): class Foo(m.Schema): a = m.fields.Integer() class Bar(Foo): b = m.fields.Integer() schema = Bar() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Bar", "properties": { "a": { "type": "integer" }, "b": { "type": "integer" } }, }, ) def test_converters_are_checked_up_the_mro_chain(self): class CustomString(m.fields.String): pass class Foo(m.Schema): a = CustomString() schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": { "a": { "type": "string" } } }, ) def test_additional_properties(self): class Foo(DisallowExtraFieldsMixin, m.Schema): a = m.fields.Integer() schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": { "a": { "type": "integer" } }, "additionalProperties": False, }, )
class TestConverterRegistry(unittest.TestCase): def setUp(self): self.registry = ConverterRegistry() self.registry.register_types(ALL_CONVERTERS) def do_nothing(self): pass def test_primitive_types(self): for field, result in [ (m.fields.Integer(), {"type": "integer"}), (m.fields.String(), {"type": "string"}), (m.fields.Number(), {"type": "number"}), (m.fields.DateTime(), {"type": "string", "format": "date-time"}), (m.fields.Date(), {"type": "string", "format": "date"}), (m.fields.UUID(), {"type": "string", "format": "uuid"}), (m.fields.Boolean(), {"type": "boolean"}), (m.fields.URL(), {"type": "string"}), (m.fields.Email(), {"type": "string"}), (m.fields.Constant("foo"), {"enum": ["foo"], "default": "foo"}), (m.fields.Integer(missing=5), {"type": "integer", "default": 5}), (m.fields.Integer(dump_only=True), {"type": "integer", "readOnly": True}), (m.fields.Integer(missing=lambda: 5), {"type": "integer"}), ( m.fields.Integer(allow_none=True), {"type": "integer", "x-nullable": True}, ), ( m.fields.List(m.fields.Integer()), {"type": "array", "items": {"type": "integer"}}, ), ( m.fields.List(m.fields.Integer), {"type": "array", "items": {"type": "integer"}}, ), ( m.fields.Integer(description="blam!"), {"type": "integer", "description": "blam!"}, ), ( QueryParamList(m.fields.Integer()), { "type": "array", "items": {"type": "integer"}, "collectionFormat": "multi", }, ), ( CommaSeparatedList(m.fields.Integer()), { "type": "array", "items": {"type": "integer"}, "collectionFormat": "csv", }, ), ( m.fields.Integer(validate=v.Range(min=1)), {"type": "integer", "minimum": 1}, ), ( m.fields.Integer(validate=v.Range(max=9)), {"type": "integer", "maximum": 9}, ), ( m.fields.List(m.fields.Integer(), validate=v.Length(min=1)), {"type": "array", "items": {"type": "integer"}, "minItems": 1}, ), ( m.fields.List(m.fields.Integer(), validate=v.Length(max=9)), {"type": "array", "items": {"type": "integer"}, "maxItems": 9}, ), ( m.fields.String(validate=v.Length(min=1)), {"type": "string", "minLength": 1}, ), ( m.fields.String(validate=v.Length(max=9)), {"type": "string", "maxLength": 9}, ), ( m.fields.String(validate=v.OneOf(["a", "b"])), {"type": "string", "enum": ["a", "b"]}, ), (m.fields.Dict(), {"type": "object"}), ( m.fields.Method(serialize="x", deserialize="y", swagger_type="integer"), {"type": "integer"}, ), ( m.fields.Function( serialize=lambda _: _, deserialize=lambda _: _, swagger_type="string", ), {"type": "string"}, ), (m.fields.Integer(validate=lambda value: True), {"type": "integer"}), ]: class Foo(m.Schema): a = field # in marshmallow >= 3.11.x, if the 'serialize' / 'deserialize' functions for # a field.Method aren't defined, an exception will be raised. x = self.do_nothing y = self.do_nothing schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, {"type": "object", "title": "Foo", "properties": {"a": result}}, ) def test_primitive_types_openapi_v3(self): for field, result in [ (m.fields.Integer(allow_none=True), {"type": "integer", "nullable": True}), ( QueryParamList(m.fields.Integer()), {"type": "array", "items": {"type": "integer"}, "explode": True}, ), ( CommaSeparatedList(m.fields.Integer()), {"type": "array", "items": {"type": "integer"}, "style": "simple"}, ), ]: class Foo(m.Schema): a = field schema = Foo() json_schema = self.registry.convert(schema, openapi_version=3) self.assertEqual( json_schema, {"type": "object", "title": "Foo", "properties": {"a": result}}, ) def test_data_key(self): registry = ConverterRegistry() registry.register_types(ALL_CONVERTERS) class Foo(m.Schema): a = m.fields.Integer(data_key="b", required=True) schema = Foo() json_schema = registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": {"b": {"type": "integer"}}, "required": ["b"], }, ) def test_required(self): class Foo(m.Schema): b = m.fields.Integer(required=True) a = m.fields.Integer(required=True) c = m.fields.Integer() schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": { "b": {"type": "integer"}, "a": {"type": "integer"}, "c": {"type": "integer"}, }, "required": ["a", "b"], }, ) def test_ordered_required(self): class Foo(m.Schema): b = m.fields.Integer(required=True) a = m.fields.Integer(required=True) c = m.fields.Integer() class Meta: ordered = True schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": { "b": {"type": "integer"}, "a": {"type": "integer"}, "c": {"type": "integer"}, }, "required": ["b", "a"], }, ) def test_partial(self): class Foo(m.Schema): b = m.fields.Integer(required=True) a = m.fields.Integer(required=True) c = m.fields.Integer() schema = Foo(partial=["b"]) json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": { "b": {"type": "integer"}, "a": {"type": "integer"}, "c": {"type": "integer"}, }, "required": ["a"], }, ) def test_partial_all(self): class Foo(m.Schema): b = m.fields.Integer(required=True) a = m.fields.Integer(required=True) c = m.fields.Integer() schema = Foo(partial=True) json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": { "b": {"type": "integer"}, "a": {"type": "integer"}, "c": {"type": "integer"}, }, }, ) def test_object_description(self): class Foo(m.Schema): """I'm the description!""" a = m.fields.Integer() schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "description": "I'm the description!", "properties": {"a": {"type": "integer"}}, }, ) def test_nested(self): class Bar(m.Schema): a = m.fields.Integer() class Foo(m.Schema): a = m.fields.Nested(Bar) schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": { "a": { "type": "object", "title": "Bar", "properties": {"a": {"type": "integer"}}, } }, }, ) def test_self_referential_nested(self): # Issue 90 # note for Marshmallow >= 3.3, preferred format is e.g.,: # m.fields.Nested(lambda: Foo(only=("d", "b"))) # and passing "self" as a string is deprecated # but that doesn't work in < 3.3, so until 4.x we'll keep supporting/testing with "self" class Foo(m.Schema): a = m.fields.Nested("self", exclude=("a",)) b = m.fields.Integer() c = m.fields.Nested("self", only=("d", "b")) d = m.fields.Email() schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "properties": { "a": { "properties": { "b": {"type": "integer"}, "c": { "properties": { "b": {"type": "integer"}, "d": {"type": "string"}, }, "title": "Foo", "type": "object", }, "d": {"type": "string"}, }, "title": "Foo", "type": "object", }, "b": {"type": "integer"}, "c": { "properties": { "b": {"type": "integer"}, "d": {"type": "string"}, }, "title": "Foo", "type": "object", }, "d": {"type": "string"}, }, "title": "Foo", "type": "object", }, ) def test_many(self): class Foo(m.Schema): a = m.fields.Integer() schema = Foo(many=True) json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "array", "items": { "type": "object", "title": "Foo", "properties": {"a": {"type": "integer"}}, }, }, ) def test_nested_many(self): class Bar(m.Schema): a = m.fields.Integer() class Foo(m.Schema): a = m.fields.Nested(Bar, many=True) schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": { "a": { "type": "array", "items": { "type": "object", "title": "Bar", "properties": {"a": {"type": "integer"}}, }, } }, }, ) def test_inheritance(self): class Foo(m.Schema): a = m.fields.Integer() class Bar(Foo): b = m.fields.Integer() schema = Bar() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Bar", "properties": {"a": {"type": "integer"}, "b": {"type": "integer"}}, }, ) def test_converters_are_checked_up_the_mro_chain(self): class CustomString(m.fields.String): pass class Foo(m.Schema): a = CustomString() schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, {"type": "object", "title": "Foo", "properties": {"a": {"type": "string"}}}, ) def test_additional_properties(self): class Foo(DisallowExtraFieldsMixin, m.Schema): a = m.fields.Integer() schema = Foo() json_schema = self.registry.convert(schema) self.assertEqual( json_schema, { "type": "object", "title": "Foo", "properties": {"a": {"type": "integer"}}, "additionalProperties": False, }, )