oggit/packages/flask-restx/opengnsys-flask-restx-1.3.0/tests/test_model.py

696 lines
18 KiB
Python

import copy
import pytest
from collections import OrderedDict
from flask_restx import fields, Model, OrderedModel, SchemaModel
class ModelTest(object):
def test_model_as_flat_dict(self):
model = Model(
"Person",
{
"name": fields.String,
"age": fields.Integer,
"birthdate": fields.DateTime,
},
)
assert isinstance(model, dict)
assert not isinstance(model, OrderedDict)
assert model.__schema__ == {
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"birthdate": {"type": "string", "format": "date-time"},
},
"type": "object",
}
def test_model_as_ordered_dict(self):
model = OrderedModel(
"Person",
[
("name", fields.String),
("age", fields.Integer),
("birthdate", fields.DateTime),
],
)
assert isinstance(model, OrderedDict)
assert model.__schema__ == {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"birthdate": {"type": "string", "format": "date-time"},
},
}
def test_model_as_nested_dict(self):
address = Model(
"Address",
{
"road": fields.String,
},
)
person = Model(
"Person",
{
"name": fields.String,
"age": fields.Integer,
"birthdate": fields.DateTime,
"address": fields.Nested(address),
},
)
assert person.__schema__ == {
# 'required': ['address'],
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"birthdate": {"type": "string", "format": "date-time"},
"address": {
"$ref": "#/definitions/Address",
},
},
"type": "object",
}
assert address.__schema__ == {
"properties": {
"road": {"type": "string"},
},
"type": "object",
}
def test_model_as_dict_with_list(self):
model = Model(
"Person",
{
"name": fields.String,
"age": fields.Integer,
"tags": fields.List(fields.String),
},
)
assert model.__schema__ == {
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"tags": {"type": "array", "items": {"type": "string"}},
},
"type": "object",
}
def test_model_as_nested_dict_with_list(self):
address = Model(
"Address",
{
"road": fields.String,
},
)
person = Model(
"Person",
{
"name": fields.String,
"age": fields.Integer,
"birthdate": fields.DateTime,
"addresses": fields.List(fields.Nested(address)),
},
)
assert person.__schema__ == {
# 'required': ['address'],
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"birthdate": {"type": "string", "format": "date-time"},
"addresses": {
"type": "array",
"items": {
"$ref": "#/definitions/Address",
},
},
},
"type": "object",
}
assert address.__schema__ == {
"properties": {
"road": {"type": "string"},
},
"type": "object",
}
def test_model_with_required(self):
model = Model(
"Person",
{
"name": fields.String(required=True),
"age": fields.Integer,
"birthdate": fields.DateTime(required=True),
},
)
assert model.__schema__ == {
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"birthdate": {"type": "string", "format": "date-time"},
},
"required": ["birthdate", "name"],
"type": "object",
}
def test_model_as_nested_dict_and_required(self):
address = Model(
"Address",
{
"road": fields.String,
},
)
person = Model(
"Person",
{
"name": fields.String,
"age": fields.Integer,
"birthdate": fields.DateTime,
"address": fields.Nested(address, required=True),
},
)
assert person.__schema__ == {
"required": ["address"],
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"birthdate": {"type": "string", "format": "date-time"},
"address": {
"$ref": "#/definitions/Address",
},
},
"type": "object",
}
assert address.__schema__ == {
"properties": {
"road": {"type": "string"},
},
"type": "object",
}
def test_model_with_discriminator(self):
model = Model(
"Person",
{
"name": fields.String(discriminator=True),
"age": fields.Integer,
},
)
assert model.__schema__ == {
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
},
"discriminator": "name",
"required": ["name"],
"type": "object",
}
def test_model_with_discriminator_override_require(self):
model = Model(
"Person",
{
"name": fields.String(discriminator=True, required=False),
"age": fields.Integer,
},
)
assert model.__schema__ == {
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
},
"discriminator": "name",
"required": ["name"],
"type": "object",
}
def test_model_deepcopy(self):
parent = Model(
"Person",
{
"name": fields.String,
"age": fields.Integer(description="foo"),
},
)
child = parent.inherit(
"Child",
{
"extra": fields.String,
},
)
parent_copy = copy.deepcopy(parent)
assert parent_copy["age"].description == "foo"
parent_copy["age"].description = "bar"
assert parent["age"].description == "foo"
assert parent_copy["age"].description == "bar"
child = parent.inherit(
"Child",
{
"extra": fields.String,
},
)
child_copy = copy.deepcopy(child)
assert child_copy.__parents__[0] == parent
def test_clone_from_instance(self):
parent = Model(
"Parent",
{
"name": fields.String,
"age": fields.Integer,
"birthdate": fields.DateTime,
},
)
child = parent.clone(
"Child",
{
"extra": fields.String,
},
)
assert child.__schema__ == {
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"birthdate": {"type": "string", "format": "date-time"},
"extra": {"type": "string"},
},
"type": "object",
}
def test_clone_from_class(self):
parent = Model(
"Parent",
{
"name": fields.String,
"age": fields.Integer,
"birthdate": fields.DateTime,
},
)
child = Model.clone(
"Child",
parent,
{
"extra": fields.String,
},
)
assert child.__schema__ == {
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"birthdate": {"type": "string", "format": "date-time"},
"extra": {"type": "string"},
},
"type": "object",
}
def test_clone_from_instance_with_multiple_parents(self):
grand_parent = Model(
"GrandParent",
{
"grand_parent": fields.String,
},
)
parent = Model(
"Parent",
{
"name": fields.String,
"age": fields.Integer,
"birthdate": fields.DateTime,
},
)
child = grand_parent.clone(
"Child",
parent,
{
"extra": fields.String,
},
)
assert child.__schema__ == {
"properties": {
"grand_parent": {"type": "string"},
"name": {"type": "string"},
"age": {"type": "integer"},
"birthdate": {"type": "string", "format": "date-time"},
"extra": {"type": "string"},
},
"type": "object",
}
def test_clone_from_class_with_multiple_parents(self):
grand_parent = Model(
"GrandParent",
{
"grand_parent": fields.String,
},
)
parent = Model(
"Parent",
{
"name": fields.String,
"age": fields.Integer,
"birthdate": fields.DateTime,
},
)
child = Model.clone(
"Child",
grand_parent,
parent,
{
"extra": fields.String,
},
)
assert child.__schema__ == {
"properties": {
"grand_parent": {"type": "string"},
"name": {"type": "string"},
"age": {"type": "integer"},
"birthdate": {"type": "string", "format": "date-time"},
"extra": {"type": "string"},
},
"type": "object",
}
def test_inherit_from_instance(self):
parent = Model(
"Parent",
{
"name": fields.String,
"age": fields.Integer,
},
)
child = parent.inherit(
"Child",
{
"extra": fields.String,
},
)
assert parent.__schema__ == {
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
},
"type": "object",
}
assert child.__schema__ == {
"allOf": [
{"$ref": "#/definitions/Parent"},
{"properties": {"extra": {"type": "string"}}, "type": "object"},
]
}
def test_inherit_from_class(self):
parent = Model(
"Parent",
{
"name": fields.String,
"age": fields.Integer,
},
)
child = Model.inherit(
"Child",
parent,
{
"extra": fields.String,
},
)
assert parent.__schema__ == {
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
},
"type": "object",
}
assert child.__schema__ == {
"allOf": [
{"$ref": "#/definitions/Parent"},
{"properties": {"extra": {"type": "string"}}, "type": "object"},
]
}
def test_inherit_from_class_from_multiple_parents(self):
grand_parent = Model(
"GrandParent",
{
"grand_parent": fields.String,
},
)
parent = Model(
"Parent",
{
"name": fields.String,
"age": fields.Integer,
},
)
child = Model.inherit(
"Child",
grand_parent,
parent,
{
"extra": fields.String,
},
)
assert child.__schema__ == {
"allOf": [
{"$ref": "#/definitions/GrandParent"},
{"$ref": "#/definitions/Parent"},
{"properties": {"extra": {"type": "string"}}, "type": "object"},
]
}
def test_inherit_from_instance_from_multiple_parents(self):
grand_parent = Model(
"GrandParent",
{
"grand_parent": fields.String,
},
)
parent = Model(
"Parent",
{
"name": fields.String,
"age": fields.Integer,
},
)
child = grand_parent.inherit(
"Child",
parent,
{
"extra": fields.String,
},
)
assert child.__schema__ == {
"allOf": [
{"$ref": "#/definitions/GrandParent"},
{"$ref": "#/definitions/Parent"},
{"properties": {"extra": {"type": "string"}}, "type": "object"},
]
}
# def test_inherit_inline(self):
# parent = Model('Person', {
# 'name': fields.String,
# 'age': fields.Integer,
# })
#
# child = self.api.inherit('Child', parent, {
# 'extra': fields.String,
# })
#
# Model('Output', {
# 'child': fields.Nested(child),
# 'children': fields.List(fields.Nested(child))
# })
#
# self.assertIn('Person', Models)
# self.assertIn('Child', Models)
def test_polymorph_inherit_common_ancestor(self):
class Child1:
pass
class Child2:
pass
parent = Model(
"Person",
{
"name": fields.String,
"age": fields.Integer,
},
)
child1 = parent.inherit(
"Child1",
{
"extra1": fields.String,
},
)
child2 = parent.inherit(
"Child2",
{
"extra2": fields.String,
},
)
mapping = {
Child1: child1,
Child2: child2,
}
output = Model("Output", {"child": fields.Polymorph(mapping)})
# Should use the common ancestor
assert output.__schema__ == {
"properties": {
"child": {"$ref": "#/definitions/Person"},
},
"type": "object",
}
def test_validate(self):
from jsonschema import FormatChecker
from werkzeug.exceptions import BadRequest
class IPAddress(fields.Raw):
__schema_type__ = "string"
__schema_format__ = "ipv4"
data = {"ip": "192.168.1"}
model = Model("MyModel", {"ip": IPAddress()})
# Test that validate without a FormatChecker does not check if a
# primitive type conforms to the defined format property
assert model.validate(data) is None
# Test that validate with a FormatChecker enforces the check of the
# format property and throws an error if invalid
with pytest.raises(BadRequest):
model.validate(data, format_checker=FormatChecker())
class ModelSchemaTestCase(object):
def test_model_schema(self):
address = SchemaModel(
"Address",
{
"properties": {
"road": {"type": "string"},
},
"type": "object",
},
)
person = SchemaModel(
"Person",
{
# 'required': ['address'],
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"birthdate": {"type": "string", "format": "date-time"},
"address": {
"$ref": "#/definitions/Address",
},
},
"type": "object",
},
)
assert person.__schema__ == {
# 'required': ['address'],
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"birthdate": {"type": "string", "format": "date-time"},
"address": {
"$ref": "#/definitions/Address",
},
},
"type": "object",
}
assert address.__schema__ == {
"properties": {
"road": {"type": "string"},
},
"type": "object",
}
class ModelDeprecattionsTest(object):
def test_extend_is_deprecated(self):
parent = Model(
"Parent",
{
"name": fields.String,
"age": fields.Integer,
"birthdate": fields.DateTime,
},
)
with pytest.warns(DeprecationWarning):
child = parent.extend(
"Child",
{
"extra": fields.String,
},
)
assert child.__schema__ == {
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"birthdate": {"type": "string", "format": "date-time"},
"extra": {"type": "string"},
},
"type": "object",
}