Skip to content

Commit cffc47c

Browse files
committed
OpenAPI request and response datatypes
1 parent 8a614de commit cffc47c

File tree

8 files changed

+151
-97
lines changed

8 files changed

+151
-97
lines changed

openapi_core/testing/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"""OpenAPI core testing module"""
2+
from openapi_core.testing.mock import MockRequestFactory, MockResponseFactory
3+
4+
# backward compatibility
5+
MockRequest = MockRequestFactory.create
6+
MockResponse = MockResponseFactory.create
7+
8+
__all__ = [
9+
'MockRequestFactory', 'MockResponseFactory', 'MockRequest', 'MockResponse',
10+
]

openapi_core/testing/mock.py

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,45 @@
1-
"""OpenAPI core wrappers module"""
1+
"""OpenAPI core testing mock module"""
22
from werkzeug.datastructures import ImmutableMultiDict
33

4-
from openapi_core.wrappers.base import BaseOpenAPIRequest, BaseOpenAPIResponse
4+
from openapi_core.validation.request.datatypes import (
5+
RequestParameters, OpenAPIRequest,
6+
)
7+
from openapi_core.validation.response.datatypes import OpenAPIResponse
58

69

7-
class MockRequest(BaseOpenAPIRequest):
10+
class MockRequestFactory(object):
811

9-
def __init__(
10-
self, host_url, method, path, path_pattern=None, args=None,
12+
@classmethod
13+
def create(
14+
cls, host_url, method, path, path_pattern=None, args=None,
1115
view_args=None, headers=None, cookies=None, data=None,
1216
mimetype='application/json'):
13-
self.host_url = host_url
14-
self.path = path
15-
self.path_pattern = path_pattern or path
16-
self.method = method.lower()
17-
18-
self.parameters = {
19-
'path': view_args or {},
20-
'query': ImmutableMultiDict(args or []),
21-
'header': headers or {},
22-
'cookie': cookies or {},
23-
}
24-
25-
self.body = data or ''
26-
27-
self.mimetype = mimetype
28-
29-
30-
class MockResponse(BaseOpenAPIResponse):
31-
32-
def __init__(self, data, status_code=200, mimetype='application/json'):
33-
self.data = data
34-
35-
self.status_code = status_code
36-
self.mimetype = mimetype
17+
parameters = RequestParameters(
18+
path=view_args or {},
19+
query=ImmutableMultiDict(args or []),
20+
header=headers or {},
21+
cookie=cookies or {},
22+
)
23+
path_pattern = path_pattern or path
24+
method = method.lower()
25+
body = data or ''
26+
return OpenAPIRequest(
27+
host_url=host_url,
28+
path=path,
29+
path_pattern=path_pattern,
30+
method=method,
31+
parameters=parameters,
32+
body=body,
33+
mimetype=mimetype,
34+
)
35+
36+
37+
class MockResponseFactory(object):
38+
39+
@classmethod
40+
def create(cls, data, status_code=200, mimetype='application/json'):
41+
return OpenAPIResponse(
42+
data=data,
43+
status_code=status_code,
44+
mimetype=mimetype,
45+
)

openapi_core/validation/request/datatypes.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,43 @@
11
"""OpenAPI core validation request datatypes module"""
22
import attr
3+
from werkzeug.datastructures import ImmutableMultiDict
34

45
from openapi_core.validation.datatypes import BaseValidationResult
56

67

8+
from six.moves.urllib.parse import urljoin
9+
10+
711
@attr.s
812
class RequestParameters(object):
913
path = attr.ib(factory=dict)
10-
query = attr.ib(factory=dict)
14+
query = attr.ib(factory=ImmutableMultiDict)
1115
header = attr.ib(factory=dict)
1216
cookie = attr.ib(factory=dict)
1317

1418
def __getitem__(self, location):
1519
return getattr(self, location)
1620

1721

22+
@attr.s
23+
class OpenAPIRequest(object):
24+
25+
host_url = attr.ib()
26+
path = attr.ib()
27+
path_pattern = attr.ib()
28+
method = attr.ib()
29+
30+
body = attr.ib()
31+
32+
mimetype = attr.ib()
33+
34+
parameters = attr.ib(factory=RequestParameters)
35+
36+
@property
37+
def full_url_pattern(self):
38+
return urljoin(self.host_url, self.path_pattern)
39+
40+
1841
@attr.s
1942
class RequestValidationResult(BaseValidationResult):
2043
body = attr.ib(default=None)

openapi_core/validation/request/validators.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def validate(self, request):
5050
def _get_parameters(self, request, params):
5151
errors = []
5252
seen = set()
53-
parameters = RequestParameters()
53+
locations = {}
5454
for param_name, param in params:
5555
if (param_name, param.location.value) in seen:
5656
# skip parameter already seen
@@ -79,9 +79,10 @@ def _get_parameters(self, request, params):
7979
except OpenAPIMappingError as exc:
8080
errors.append(exc)
8181
else:
82-
parameters[param.location.value][param_name] = unmarshalled
82+
locations.setdefault(param.location.value, {})
83+
locations[param.location.value][param_name] = unmarshalled
8384

84-
return parameters, errors
85+
return RequestParameters(**locations), errors
8586

8687
def _get_body(self, request, operation):
8788
errors = []

openapi_core/validation/response/datatypes.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@
44
from openapi_core.validation.datatypes import BaseValidationResult
55

66

7+
@attr.s
8+
class OpenAPIResponse(object):
9+
10+
data = attr.ib()
11+
status_code = attr.ib()
12+
13+
mimetype = attr.ib()
14+
15+
716
@attr.s
817
class ResponseValidationResult(BaseValidationResult):
918
data = attr.ib(default=None)

tests/integration/validation/test_minimal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from openapi_core.schema.operations.exceptions import InvalidOperation
44
from openapi_core.schema.paths.exceptions import InvalidPath
55
from openapi_core.shortcuts import create_spec
6-
from openapi_core.testing.mock import MockRequest
6+
from openapi_core.testing import MockRequest
77
from openapi_core.validation.request.validators import RequestValidator
88

99

0 commit comments

Comments
 (0)