mirror of
https://github.com/correl/openapi-core.git
synced 2024-11-21 19:18:41 +00:00
Model extension refactor
This commit is contained in:
parent
11f0233ef2
commit
af07200b7b
6 changed files with 76 additions and 40 deletions
|
@ -4,9 +4,15 @@ from openapi_core.extensions.models.models import BaseModel
|
|||
|
||||
class ModelFactory(object):
|
||||
|
||||
def create(self, properties, name=None):
|
||||
model = BaseModel
|
||||
if name is not None:
|
||||
model = type(name, (BaseModel, ), {})
|
||||
base_class = BaseModel
|
||||
default_name = 'Model'
|
||||
|
||||
return model(**properties)
|
||||
def __init__(self, name=None):
|
||||
self.name = name or self.default_name
|
||||
|
||||
def __call__(self, **properties):
|
||||
model_class = self._get_model_class(**properties)
|
||||
return model_class()
|
||||
|
||||
def _get_model_class(self, **attrs):
|
||||
return type(self.name, (self.base_class, ), attrs)
|
||||
|
|
|
@ -1,17 +1,5 @@
|
|||
"""OpenAPI X-Model extension models module"""
|
||||
|
||||
|
||||
class BaseModel(dict):
|
||||
"""Base class for OpenAPI X-Model."""
|
||||
|
||||
def __getattr__(self, attr_name):
|
||||
"""Only search through properties if attribute not found normally.
|
||||
:type attr_name: str
|
||||
"""
|
||||
try:
|
||||
return self[attr_name]
|
||||
except KeyError:
|
||||
raise AttributeError(
|
||||
'type object {0!r} has no attribute {1!r}'
|
||||
.format(type(self).__name__, attr_name)
|
||||
)
|
||||
class BaseModel(object):
|
||||
"""Base class for OpenAPI models."""
|
||||
|
|
|
@ -169,7 +169,11 @@ class Schema(object):
|
|||
else:
|
||||
properties = self._unmarshal_properties(value)
|
||||
|
||||
return ModelFactory().create(properties, name=self.model)
|
||||
return self.model_factory(**properties)
|
||||
|
||||
@property
|
||||
def model_factory(self):
|
||||
return ModelFactory(self.model)
|
||||
|
||||
def _unmarshal_properties(self, value, one_of_schema=None):
|
||||
all_props = self.get_all_properties()
|
||||
|
|
57
tests/integration/test_models.py
Normal file
57
tests/integration/test_models.py
Normal file
|
@ -0,0 +1,57 @@
|
|||
import json
|
||||
import pytest
|
||||
|
||||
from openapi_core.extensions.models.models import BaseModel
|
||||
from openapi_core.schema.media_types.exceptions import (
|
||||
InvalidContentType, InvalidMediaTypeValue,
|
||||
)
|
||||
from openapi_core.schema.operations.exceptions import InvalidOperation
|
||||
from openapi_core.schema.parameters.exceptions import MissingRequiredParameter
|
||||
from openapi_core.schema.request_bodies.exceptions import MissingRequestBody
|
||||
from openapi_core.schema.responses.exceptions import (
|
||||
MissingResponseContent, InvalidResponse,
|
||||
)
|
||||
from openapi_core.schema.servers.exceptions import InvalidServer
|
||||
from openapi_core.shortcuts import create_spec
|
||||
from openapi_core.validation.request.validators import RequestValidator
|
||||
from openapi_core.validation.response.validators import ResponseValidator
|
||||
from openapi_core.wrappers.mock import MockRequest, MockResponse
|
||||
|
||||
|
||||
class TestModelsExtension(object):
|
||||
|
||||
host_url = 'http://petstore.swagger.io'
|
||||
|
||||
@pytest.fixture
|
||||
def spec_dict(self, factory):
|
||||
return factory.spec_from_file("data/v3.0/petstore.yaml")
|
||||
|
||||
@pytest.fixture
|
||||
def spec(self, spec_dict):
|
||||
return create_spec(spec_dict)
|
||||
|
||||
@pytest.fixture
|
||||
def validator(self, spec):
|
||||
return ResponseValidator(spec)
|
||||
|
||||
def test_get_pets(self, validator):
|
||||
request = MockRequest(self.host_url, 'get', '/v1/pets')
|
||||
response_json = {
|
||||
'data': [
|
||||
{
|
||||
'id': 1,
|
||||
'name': 'Sparky'
|
||||
},
|
||||
],
|
||||
}
|
||||
response_data = json.dumps(response_json)
|
||||
response = MockResponse(response_data)
|
||||
|
||||
result = validator.validate(request, response)
|
||||
|
||||
assert result.errors == []
|
||||
assert list(result.data.keys()) == ['data', ]
|
||||
assert len(result.data['data']) == 1
|
||||
assert isinstance(result.data['data'][0], BaseModel)
|
||||
assert result.data['data'][0].id == 1
|
||||
assert result.data['data'][0].name == 'Sparky'
|
|
@ -638,7 +638,7 @@ class TestPetstore(object):
|
|||
response_result = response_validator.validate(request, response)
|
||||
|
||||
assert response_result.errors == []
|
||||
assert response_result.data == data_json
|
||||
assert list(response_result.data.keys()) == ['data', ]
|
||||
|
||||
def test_get_pet_not_found(self, spec, response_validator):
|
||||
host_url = 'http://petstore.swagger.io/v1'
|
||||
|
|
|
@ -268,22 +268,3 @@ class TestResponseValidator(object):
|
|||
assert type(result.errors[0]) == InvalidMediaTypeValue
|
||||
assert result.data is None
|
||||
assert result.headers == {}
|
||||
|
||||
def test_get_pets(self, validator):
|
||||
request = MockRequest(self.host_url, 'get', '/v1/pets')
|
||||
response_json = {
|
||||
'data': [
|
||||
{
|
||||
'id': 1,
|
||||
'name': 'Sparky'
|
||||
},
|
||||
],
|
||||
}
|
||||
response_data = json.dumps(response_json)
|
||||
response = MockResponse(response_data)
|
||||
|
||||
result = validator.validate(request, response)
|
||||
|
||||
assert result.errors == []
|
||||
assert result.data == response_json
|
||||
assert result.headers == {}
|
||||
|
|
Loading…
Reference in a new issue