Schema content refactor

This commit is contained in:
p1c2u 2021-03-30 11:12:36 +01:00
parent cfe4a7ce4e
commit e128fd59f1
8 changed files with 92 additions and 15 deletions

View file

@ -0,0 +1,21 @@
"""OpenAPI core content factories module"""
from openapi_core.compat import lru_cache
from openapi_core.schema.content.models import Content
from openapi_core.schema.media_types.generators import MediaTypeGenerator
class ContentFactory(object):
def __init__(self, dereferencer, schemas_registry):
self.dereferencer = dereferencer
self.schemas_registry = schemas_registry
def create(self, content_spec):
media_types = self.media_types_generator.generate(content_spec)
return Content(media_types)
@property
@lru_cache()
def media_types_generator(self):
return MediaTypeGenerator(self.dereferencer, self.schemas_registry)

View file

@ -1,4 +1,6 @@
"""OpenAPI core parameters factories module"""
from openapi_core.compat import lru_cache
from openapi_core.schema.content.factories import ContentFactory
from openapi_core.schema.parameters.models import Parameter
@ -25,9 +27,19 @@ class ParameterFactory(object):
if schema_spec:
schema, _ = self.schemas_registry.get_or_create(schema_spec)
content_spec = parameter_deref.get('content', None)
content = None
if content_spec:
content = self.content_factory.create(content_spec)
return Parameter(
parameter_name, parameter_in,
schema=schema, required=required,
allow_empty_value=allow_empty_value,
style=style, explode=explode,
style=style, explode=explode, content=content,
)
@property
@lru_cache()
def content_factory(self):
return ContentFactory(self.dereferencer, self.schemas_registry)

View file

@ -15,7 +15,7 @@ class Parameter(object):
def __init__(
self, name, location, schema=None, required=False,
deprecated=False, allow_empty_value=False,
items=None, style=None, explode=None):
items=None, style=None, explode=None, content=None):
self.name = name
self.location = ParameterLocation(location)
self.schema = schema
@ -30,6 +30,7 @@ class Parameter(object):
self.items = items
self.style = ParameterStyle(style or self.default_style)
self.explode = self.default_explode if explode is None else explode
self.content = content
@property
def aslist(self):

View file

@ -1,7 +1,7 @@
"""OpenAPI core request bodies factories module"""
from openapi_core.compat import lru_cache
from openapi_core.schema.content.factories import ContentFactory
from openapi_core.schema.extensions.generators import ExtensionsGenerator
from openapi_core.schema.media_types.generators import MediaTypeGenerator
from openapi_core.schema.request_bodies.models import RequestBody
@ -14,21 +14,21 @@ class RequestBodyFactory(object):
def create(self, request_body_spec):
request_body_deref = self.dereferencer.dereference(
request_body_spec)
content = request_body_deref['content']
media_types = self.media_types_generator.generate(content)
content_spec = request_body_deref['content']
content = self.content_factory.create(content_spec)
required = request_body_deref.get('required', False)
extensions = self.extensions_generator.generate(request_body_deref)
return RequestBody(
media_types,
content,
required=required, extensions=extensions,
)
@property
@lru_cache()
def media_types_generator(self):
return MediaTypeGenerator(self.dereferencer, self.schemas_registry)
def content_factory(self):
return ContentFactory(self.dereferencer, self.schemas_registry)
@property
@lru_cache()

View file

@ -1,6 +1,5 @@
"""OpenAPI core request bodies models module"""
from openapi_core.schema.content.exceptions import MimeTypeNotFound
from openapi_core.schema.content.models import Content
from openapi_core.schema.media_types.exceptions import InvalidContentType
@ -8,7 +7,7 @@ class RequestBody(object):
"""Represents an OpenAPI RequestBody."""
def __init__(self, content, required=False, extensions=None):
self.content = Content(content)
self.content = content
self.required = required
self.extensions = extensions and dict(extensions) or {}

View file

@ -67,6 +67,20 @@ paths:
items:
$ref: "#/components/schemas/Tag"
explode: false
- name: coordinates
in: query
content:
application/json:
schema:
type: object
required:
- lat
- long
properties:
lat:
type: number
long:
type: number
responses:
'200':
$ref: "#/components/responses/PetsResponse"

View file

@ -231,6 +231,36 @@ class TestPetstore(object):
assert parameter.schema.required == schema_spec.get(
'required', [])
content_spec = parameter_spec.get('content')
assert bool(content_spec) == bool(parameter.content)
if not content_spec:
continue
for mimetype, media_type in iteritems(
parameter.content):
assert type(media_type) == MediaType
assert media_type.mimetype == mimetype
media_spec = parameter_spec['content'][mimetype]
schema_spec = media_spec.get('schema')
assert bool(schema_spec) == bool(media_type.schema)
if not schema_spec:
continue
# @todo: test with defererence
if '$ref' in schema_spec:
continue
assert type(media_type.schema) == Schema
assert media_type.schema.type.value ==\
schema_spec['type']
assert media_type.schema.format ==\
schema_spec.get('format')
assert media_type.schema.required == \
schema_spec.get('required', False)
request_body_spec = operation_spec.get('requestBody')
assert bool(request_body_spec) == bool(operation.request_body)

View file

@ -40,23 +40,23 @@ class TestPetstore(object):
api_key_bytes_enc = b64encode(api_key_bytes)
return text_type(api_key_bytes_enc, 'utf8')
@pytest.fixture
@pytest.fixture(scope='module')
def spec_uri(self):
return "file://tests/integration/data/v3.0/petstore.yaml"
@pytest.fixture
@pytest.fixture(scope='module')
def spec_dict(self, factory):
return factory.spec_from_file("data/v3.0/petstore.yaml")
@pytest.fixture
@pytest.fixture(scope='module')
def spec(self, spec_dict, spec_uri):
return create_spec(spec_dict, spec_uri)
@pytest.fixture
@pytest.fixture(scope='module')
def request_validator(self, spec):
return RequestValidator(spec)
@pytest.fixture
@pytest.fixture(scope='module')
def response_validator(self, spec):
return ResponseValidator(spec)