Merge pull request #305 from p1c2u/refactor/schema-content-refactor

Schema content refactor
This commit is contained in:
A 2021-03-30 11:58:07 +01:00 committed by GitHub
commit f6efa8410d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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""" """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 from openapi_core.schema.parameters.models import Parameter
@ -25,9 +27,19 @@ class ParameterFactory(object):
if schema_spec: if schema_spec:
schema, _ = self.schemas_registry.get_or_create(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( return Parameter(
parameter_name, parameter_in, parameter_name, parameter_in,
schema=schema, required=required, schema=schema, required=required,
allow_empty_value=allow_empty_value, 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__( def __init__(
self, name, location, schema=None, required=False, self, name, location, schema=None, required=False,
deprecated=False, allow_empty_value=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.name = name
self.location = ParameterLocation(location) self.location = ParameterLocation(location)
self.schema = schema self.schema = schema
@ -30,6 +30,7 @@ class Parameter(object):
self.items = items self.items = items
self.style = ParameterStyle(style or self.default_style) self.style = ParameterStyle(style or self.default_style)
self.explode = self.default_explode if explode is None else explode self.explode = self.default_explode if explode is None else explode
self.content = content
@property @property
def aslist(self): def aslist(self):

View file

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

View file

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

View file

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

View file

@ -231,6 +231,36 @@ class TestPetstore(object):
assert parameter.schema.required == schema_spec.get( assert parameter.schema.required == schema_spec.get(
'required', []) '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') request_body_spec = operation_spec.get('requestBody')
assert bool(request_body_spec) == bool(operation.request_body) 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) api_key_bytes_enc = b64encode(api_key_bytes)
return text_type(api_key_bytes_enc, 'utf8') return text_type(api_key_bytes_enc, 'utf8')
@pytest.fixture @pytest.fixture(scope='module')
def spec_uri(self): def spec_uri(self):
return "file://tests/integration/data/v3.0/petstore.yaml" return "file://tests/integration/data/v3.0/petstore.yaml"
@pytest.fixture @pytest.fixture(scope='module')
def spec_dict(self, factory): def spec_dict(self, factory):
return factory.spec_from_file("data/v3.0/petstore.yaml") return factory.spec_from_file("data/v3.0/petstore.yaml")
@pytest.fixture @pytest.fixture(scope='module')
def spec(self, spec_dict, spec_uri): def spec(self, spec_dict, spec_uri):
return create_spec(spec_dict, spec_uri) return create_spec(spec_dict, spec_uri)
@pytest.fixture @pytest.fixture(scope='module')
def request_validator(self, spec): def request_validator(self, spec):
return RequestValidator(spec) return RequestValidator(spec)
@pytest.fixture @pytest.fixture(scope='module')
def response_validator(self, spec): def response_validator(self, spec):
return ResponseValidator(spec) return ResponseValidator(spec)