Model extension refactor

This commit is contained in:
p1c2u 2018-07-28 20:05:02 +01:00
parent 11f0233ef2
commit af07200b7b
6 changed files with 76 additions and 40 deletions

View file

@ -4,9 +4,15 @@ from openapi_core.extensions.models.models import BaseModel
class ModelFactory(object): class ModelFactory(object):
def create(self, properties, name=None): base_class = BaseModel
model = BaseModel default_name = 'Model'
if name is not None:
model = type(name, (BaseModel, ), {})
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)

View file

@ -1,17 +1,5 @@
"""OpenAPI X-Model extension models module""" """OpenAPI X-Model extension models module"""
class BaseModel(dict): class BaseModel(object):
"""Base class for OpenAPI X-Model.""" """Base class for OpenAPI models."""
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)
)

View file

@ -169,7 +169,11 @@ class Schema(object):
else: else:
properties = self._unmarshal_properties(value) 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): def _unmarshal_properties(self, value, one_of_schema=None):
all_props = self.get_all_properties() all_props = self.get_all_properties()

View 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'

View file

@ -638,7 +638,7 @@ class TestPetstore(object):
response_result = response_validator.validate(request, response) response_result = response_validator.validate(request, response)
assert response_result.errors == [] 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): def test_get_pet_not_found(self, spec, response_validator):
host_url = 'http://petstore.swagger.io/v1' host_url = 'http://petstore.swagger.io/v1'

View file

@ -268,22 +268,3 @@ class TestResponseValidator(object):
assert type(result.errors[0]) == InvalidMediaTypeValue assert type(result.errors[0]) == InvalidMediaTypeValue
assert result.data is None assert result.data is None
assert result.headers == {} 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 == {}