Skip to content

Commit f6efa84

Browse files
authored
Merge pull request #305 from p1c2u/refactor/schema-content-refactor
Schema content refactor
2 parents cfe4a7c + e128fd5 commit f6efa84

File tree

8 files changed

+92
-15
lines changed

8 files changed

+92
-15
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""OpenAPI core content factories module"""
2+
from openapi_core.compat import lru_cache
3+
from openapi_core.schema.content.models import Content
4+
from openapi_core.schema.media_types.generators import MediaTypeGenerator
5+
6+
7+
class ContentFactory(object):
8+
9+
def __init__(self, dereferencer, schemas_registry):
10+
self.dereferencer = dereferencer
11+
self.schemas_registry = schemas_registry
12+
13+
def create(self, content_spec):
14+
media_types = self.media_types_generator.generate(content_spec)
15+
16+
return Content(media_types)
17+
18+
@property
19+
@lru_cache()
20+
def media_types_generator(self):
21+
return MediaTypeGenerator(self.dereferencer, self.schemas_registry)

openapi_core/schema/parameters/factories.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
"""OpenAPI core parameters factories module"""
2+
from openapi_core.compat import lru_cache
3+
from openapi_core.schema.content.factories import ContentFactory
24
from openapi_core.schema.parameters.models import Parameter
35

46

@@ -25,9 +27,19 @@ def create(self, parameter_spec, parameter_name=None):
2527
if schema_spec:
2628
schema, _ = self.schemas_registry.get_or_create(schema_spec)
2729

30+
content_spec = parameter_deref.get('content', None)
31+
content = None
32+
if content_spec:
33+
content = self.content_factory.create(content_spec)
34+
2835
return Parameter(
2936
parameter_name, parameter_in,
3037
schema=schema, required=required,
3138
allow_empty_value=allow_empty_value,
32-
style=style, explode=explode,
39+
style=style, explode=explode, content=content,
3340
)
41+
42+
@property
43+
@lru_cache()
44+
def content_factory(self):
45+
return ContentFactory(self.dereferencer, self.schemas_registry)

openapi_core/schema/parameters/models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class Parameter(object):
1515
def __init__(
1616
self, name, location, schema=None, required=False,
1717
deprecated=False, allow_empty_value=False,
18-
items=None, style=None, explode=None):
18+
items=None, style=None, explode=None, content=None):
1919
self.name = name
2020
self.location = ParameterLocation(location)
2121
self.schema = schema
@@ -30,6 +30,7 @@ def __init__(
3030
self.items = items
3131
self.style = ParameterStyle(style or self.default_style)
3232
self.explode = self.default_explode if explode is None else explode
33+
self.content = content
3334

3435
@property
3536
def aslist(self):

openapi_core/schema/request_bodies/factories.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""OpenAPI core request bodies factories module"""
22
from openapi_core.compat import lru_cache
3+
from openapi_core.schema.content.factories import ContentFactory
34
from openapi_core.schema.extensions.generators import ExtensionsGenerator
4-
from openapi_core.schema.media_types.generators import MediaTypeGenerator
55
from openapi_core.schema.request_bodies.models import RequestBody
66

77

@@ -14,21 +14,21 @@ def __init__(self, dereferencer, schemas_registry):
1414
def create(self, request_body_spec):
1515
request_body_deref = self.dereferencer.dereference(
1616
request_body_spec)
17-
content = request_body_deref['content']
18-
media_types = self.media_types_generator.generate(content)
17+
content_spec = request_body_deref['content']
18+
content = self.content_factory.create(content_spec)
1919
required = request_body_deref.get('required', False)
2020

2121
extensions = self.extensions_generator.generate(request_body_deref)
2222

2323
return RequestBody(
24-
media_types,
24+
content,
2525
required=required, extensions=extensions,
2626
)
2727

2828
@property
2929
@lru_cache()
30-
def media_types_generator(self):
31-
return MediaTypeGenerator(self.dereferencer, self.schemas_registry)
30+
def content_factory(self):
31+
return ContentFactory(self.dereferencer, self.schemas_registry)
3232

3333
@property
3434
@lru_cache()

openapi_core/schema/request_bodies/models.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
"""OpenAPI core request bodies models module"""
22
from openapi_core.schema.content.exceptions import MimeTypeNotFound
3-
from openapi_core.schema.content.models import Content
43
from openapi_core.schema.media_types.exceptions import InvalidContentType
54

65

76
class RequestBody(object):
87
"""Represents an OpenAPI RequestBody."""
98

109
def __init__(self, content, required=False, extensions=None):
11-
self.content = Content(content)
10+
self.content = content
1211
self.required = required
1312

1413
self.extensions = extensions and dict(extensions) or {}

tests/integration/data/v3.0/petstore.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,20 @@ paths:
6767
items:
6868
$ref: "#/components/schemas/Tag"
6969
explode: false
70+
- name: coordinates
71+
in: query
72+
content:
73+
application/json:
74+
schema:
75+
type: object
76+
required:
77+
- lat
78+
- long
79+
properties:
80+
lat:
81+
type: number
82+
long:
83+
type: number
7084
responses:
7185
'200':
7286
$ref: "#/components/responses/PetsResponse"

tests/integration/schema/test_spec.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,36 @@ def test_spec(self, spec, spec_dict):
231231
assert parameter.schema.required == schema_spec.get(
232232
'required', [])
233233

234+
content_spec = parameter_spec.get('content')
235+
assert bool(content_spec) == bool(parameter.content)
236+
237+
if not content_spec:
238+
continue
239+
240+
for mimetype, media_type in iteritems(
241+
parameter.content):
242+
assert type(media_type) == MediaType
243+
assert media_type.mimetype == mimetype
244+
245+
media_spec = parameter_spec['content'][mimetype]
246+
schema_spec = media_spec.get('schema')
247+
assert bool(schema_spec) == bool(media_type.schema)
248+
249+
if not schema_spec:
250+
continue
251+
252+
# @todo: test with defererence
253+
if '$ref' in schema_spec:
254+
continue
255+
256+
assert type(media_type.schema) == Schema
257+
assert media_type.schema.type.value ==\
258+
schema_spec['type']
259+
assert media_type.schema.format ==\
260+
schema_spec.get('format')
261+
assert media_type.schema.required == \
262+
schema_spec.get('required', False)
263+
234264
request_body_spec = operation_spec.get('requestBody')
235265

236266
assert bool(request_body_spec) == bool(operation.request_body)

tests/integration/validation/test_petstore.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,23 +40,23 @@ def api_key_encoded(self):
4040
api_key_bytes_enc = b64encode(api_key_bytes)
4141
return text_type(api_key_bytes_enc, 'utf8')
4242

43-
@pytest.fixture
43+
@pytest.fixture(scope='module')
4444
def spec_uri(self):
4545
return "file://tests/integration/data/v3.0/petstore.yaml"
4646

47-
@pytest.fixture
47+
@pytest.fixture(scope='module')
4848
def spec_dict(self, factory):
4949
return factory.spec_from_file("data/v3.0/petstore.yaml")
5050

51-
@pytest.fixture
51+
@pytest.fixture(scope='module')
5252
def spec(self, spec_dict, spec_uri):
5353
return create_spec(spec_dict, spec_uri)
5454

55-
@pytest.fixture
55+
@pytest.fixture(scope='module')
5656
def request_validator(self, spec):
5757
return RequestValidator(spec)
5858

59-
@pytest.fixture
59+
@pytest.fixture(scope='module')
6060
def response_validator(self, spec):
6161
return ResponseValidator(spec)
6262

0 commit comments

Comments
 (0)