Skip to content

Commit b61a21b

Browse files
committed
Move unmarshal out of schema models
1 parent 991c586 commit b61a21b

File tree

15 files changed

+285
-269
lines changed

15 files changed

+285
-269
lines changed

README.rst

-61
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,6 @@ and unmarshal request data from validation result
7878
# get body
7979
validated_body = result.body
8080
81-
or use shortcuts for simple validation
82-
83-
.. code-block:: python
84-
85-
from openapi_core import validate_parameters, validate_body
86-
87-
validated_params = validate_parameters(spec, request)
88-
validated_body = validate_body(spec, request)
89-
9081
Request object should be instance of OpenAPIRequest class (See `Integrations`_).
9182

9283
Response
@@ -117,14 +108,6 @@ and unmarshal response data from validation result
117108
# get data
118109
validated_data = result.data
119110
120-
or use shortcuts for simple validation
121-
122-
.. code-block:: python
123-
124-
from openapi_core import validate_data
125-
126-
validated_data = validate_data(spec, request, response)
127-
128111
Response object should be instance of OpenAPIResponse class (See `Integrations`_).
129112

130113

@@ -145,17 +128,6 @@ For Django 2.2 you can use DjangoOpenAPIRequest a Django request factory:
145128
validator = RequestValidator(spec)
146129
result = validator.validate(openapi_request)
147130
148-
or simply specify request factory for shortcuts
149-
150-
.. code-block:: python
151-
152-
from openapi_core import validate_parameters, validate_body
153-
154-
validated_params = validate_parameters(
155-
spec, request, request_factory=DjangoOpenAPIRequest)
156-
validated_body = validate_body(
157-
spec, request, request_factory=DjangoOpenAPIRequest)
158-
159131
You can use DjangoOpenAPIResponse as a Django response factory:
160132

161133
.. code-block:: python
@@ -167,17 +139,6 @@ You can use DjangoOpenAPIResponse as a Django response factory:
167139
validator = ResponseValidator(spec)
168140
result = validator.validate(openapi_request, openapi_response)
169141
170-
or simply specify response factory for shortcuts
171-
172-
.. code-block:: python
173-
174-
from openapi_core import validate_parameters, validate_body
175-
176-
validated_data = validate_data(
177-
spec, request, response,
178-
request_factory=DjangoOpenAPIRequest,
179-
response_factory=DjangoOpenAPIResponse)
180-
181142
Flask
182143
*****
183144

@@ -247,17 +208,6 @@ You can use FlaskOpenAPIRequest a Flask/Werkzeug request factory:
247208
validator = RequestValidator(spec)
248209
result = validator.validate(openapi_request)
249210
250-
or simply specify request factory for shortcuts
251-
252-
.. code-block:: python
253-
254-
from openapi_core import validate_parameters, validate_body
255-
256-
validated_params = validate_parameters(
257-
spec, request, request_factory=FlaskOpenAPIRequest)
258-
validated_body = validate_body(
259-
spec, request, request_factory=FlaskOpenAPIRequest)
260-
261211
You can use FlaskOpenAPIResponse as a Flask/Werkzeug response factory:
262212

263213
.. code-block:: python
@@ -269,17 +219,6 @@ You can use FlaskOpenAPIResponse as a Flask/Werkzeug response factory:
269219
validator = ResponseValidator(spec)
270220
result = validator.validate(openapi_request, openapi_response)
271221
272-
or simply specify response factory for shortcuts
273-
274-
.. code-block:: python
275-
276-
from openapi_core import validate_parameters, validate_body
277-
278-
validated_data = validate_data(
279-
spec, request, response,
280-
request_factory=FlaskOpenAPIRequest,
281-
response_factory=FlaskOpenAPIResponse)
282-
283222
Pyramid
284223
*******
285224

openapi_core/schema/media_types/models.py

-13
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
from openapi_core.schema.media_types.exceptions import InvalidMediaTypeValue
55
from openapi_core.schema.media_types.util import json_loads
66
from openapi_core.casting.schemas.exceptions import CastError
7-
from openapi_core.unmarshalling.schemas.exceptions import (
8-
UnmarshalError, ValidateError,
9-
)
107

118

129
MEDIA_TYPE_DESERIALIZERS = {
@@ -47,13 +44,3 @@ def cast(self, value):
4744
return self.schema.cast(deserialized)
4845
except CastError as exc:
4946
raise InvalidMediaTypeValue(exc)
50-
51-
def unmarshal(self, value, custom_formatters=None, resolver=None):
52-
if not self.schema:
53-
return value
54-
55-
try:
56-
return self.schema.unmarshal(
57-
value, resolver=resolver, custom_formatters=custom_formatters)
58-
except (ValidateError, UnmarshalError) as exc:
59-
raise InvalidMediaTypeValue(exc)

openapi_core/schema/parameters/models.py

-16
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@
1111
)
1212
from openapi_core.schema.schemas.enums import SchemaType
1313
from openapi_core.casting.schemas.exceptions import CastError
14-
from openapi_core.unmarshalling.schemas.exceptions import (
15-
UnmarshalError, ValidateError,
16-
)
1714

1815
log = logging.getLogger(__name__)
1916

@@ -114,16 +111,3 @@ def cast(self, value):
114111
return self.schema.cast(deserialized)
115112
except CastError as exc:
116113
raise InvalidParameterValue(self.name, exc)
117-
118-
def unmarshal(self, value, custom_formatters=None, resolver=None):
119-
if not self.schema:
120-
return value
121-
122-
try:
123-
return self.schema.unmarshal(
124-
value,
125-
resolver=resolver,
126-
custom_formatters=custom_formatters,
127-
)
128-
except (ValidateError, UnmarshalError) as exc:
129-
raise InvalidParameterValue(self.name, exc)

openapi_core/unmarshalling/schemas/factories.py

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import warnings
33

44
from openapi_core.schema.schemas.enums import SchemaType, SchemaFormat
5+
from openapi_core.schema.schemas.models import Schema
56
from openapi_core.schema_validator import OAS30Validator
67
from openapi_core.schema_validator import oas30_format_checker
78
from openapi_core.unmarshalling.schemas.exceptions import (
@@ -36,6 +37,8 @@ def __init__(self, resolver=None, custom_formatters=None):
3637

3738
def create(self, schema, type_override=None):
3839
"""Create unmarshaller from the schema."""
40+
if not isinstance(schema, Schema):
41+
raise TypeError("schema not type of Schema")
3942
if schema.deprecated:
4043
warnings.warn("The schema is deprecated", DeprecationWarning)
4144

openapi_core/validation/request/shortcuts.py

+25-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""OpenAPI core validation request shortcuts module"""
22
from functools import partial
3+
import warnings
34

45
from openapi_core.schema.media_types.exceptions import OpenAPIMediaTypeError
56
from openapi_core.schema.parameters.exceptions import OpenAPIParameterError
@@ -28,8 +29,30 @@ def validate_request(validator, request, failsafe=None):
2829
return result
2930

3031

31-
validate_parameters = partial(validate_request, failsafe=ERRORS_BODY)
32-
validate_body = partial(validate_request, failsafe=ERRORS_PARAMETERS)
32+
# validate_parameters = partial(validate_request, failsafe=ERRORS_BODY)
33+
# validate_body = partial(validate_request, failsafe=ERRORS_PARAMETERS)
34+
35+
36+
def validate_parameters(validator, request):
37+
warnings.warn(
38+
"validate_parameters shortcut is deprecated, "
39+
"use validator.validate instead",
40+
DeprecationWarning,
41+
)
42+
result = validator._validate_parameters(request)
43+
result.raise_for_errors()
44+
return result
45+
46+
47+
def validate_body(validator, request):
48+
warnings.warn(
49+
"validate_body shortcut is deprecated, "
50+
"use validator.validate instead",
51+
DeprecationWarning,
52+
)
53+
result = validator._validate_body(request)
54+
result.raise_for_errors()
55+
return result
3356

3457

3558
def spec_validate_parameters(spec, request, request_factory=None):

openapi_core/validation/request/validators.py

+58-25
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
from openapi_core.schema.paths.exceptions import InvalidPath
1313
from openapi_core.schema.request_bodies.exceptions import MissingRequestBody
1414
from openapi_core.schema.servers.exceptions import InvalidServer
15+
from openapi_core.unmarshalling.schemas.exceptions import (
16+
UnmarshalError, ValidateError,
17+
)
1518
from openapi_core.validation.request.datatypes import (
1619
RequestParameters, RequestValidationResult,
1720
)
@@ -26,25 +29,29 @@ def __init__(self, spec, custom_formatters=None):
2629

2730
def validate(self, request):
2831
try:
29-
server = self.spec.get_server(request.full_url_pattern)
30-
# don't process if server errors
31-
except InvalidServer as exc:
32+
path = self._get_path(request)
33+
operation = self._get_operation(request)
34+
# don't process if operation errors
35+
except (InvalidServer, InvalidPath, InvalidOperation) as exc:
3236
return RequestValidationResult([exc, ], None, None)
3337

34-
operation_pattern = get_operation_pattern(
35-
server.default_url, request.full_url_pattern
38+
params, params_errors = self._get_parameters(
39+
request, chain(
40+
iteritems(operation.parameters),
41+
iteritems(path.parameters)
42+
)
3643
)
3744

38-
try:
39-
path = self.spec[operation_pattern]
40-
except InvalidPath as exc:
41-
return RequestValidationResult([exc, ], None, None)
45+
body, body_errors = self._get_body(request, operation)
4246

47+
errors = params_errors + body_errors
48+
return RequestValidationResult(errors, body, params)
49+
50+
def _validate_parameters(self, request):
4351
try:
44-
operation = self.spec.get_operation(
45-
operation_pattern, request.method)
46-
# don't process if operation errors
47-
except InvalidOperation as exc:
52+
path = self._get_path(request)
53+
operation = self._get_operation(request)
54+
except (InvalidServer, InvalidPath, InvalidOperation) as exc:
4855
return RequestValidationResult([exc, ], None, None)
4956

5057
params, params_errors = self._get_parameters(
@@ -53,11 +60,33 @@ def validate(self, request):
5360
iteritems(path.parameters)
5461
)
5562
)
63+
return RequestValidationResult(params_errors, None, params)
64+
65+
def _validate_body(self, request):
66+
try:
67+
operation = self._get_operation(request)
68+
except (InvalidServer, InvalidOperation) as exc:
69+
return RequestValidationResult([exc, ], None, None)
5670

5771
body, body_errors = self._get_body(request, operation)
72+
return RequestValidationResult(body_errors, body, None)
5873

59-
errors = params_errors + body_errors
60-
return RequestValidationResult(errors, body, params)
74+
def _get_operation_pattern(self, request):
75+
server = self.spec.get_server(request.full_url_pattern)
76+
77+
return get_operation_pattern(
78+
server.default_url, request.full_url_pattern
79+
)
80+
81+
def _get_path(self, request):
82+
operation_pattern = self._get_operation_pattern(request)
83+
84+
return self.spec[operation_pattern]
85+
86+
def _get_operation(self, request):
87+
operation_pattern = self._get_operation_pattern(request)
88+
89+
return self.spec.get_operation(operation_pattern, request.method)
6190

6291
def _get_parameters(self, request, params):
6392
errors = []
@@ -86,11 +115,8 @@ def _get_parameters(self, request, params):
86115
continue
87116

88117
try:
89-
unmarshalled = param.unmarshal(
90-
casted, self.custom_formatters,
91-
resolver=self.spec._resolver,
92-
)
93-
except OpenAPIParameterError as exc:
118+
unmarshalled = self._unmarshal(param, casted)
119+
except (ValidateError, UnmarshalError) as exc:
94120
errors.append(exc)
95121
else:
96122
locations.setdefault(param.location.value, {})
@@ -121,11 +147,18 @@ def _get_body(self, request, operation):
121147
errors.append(exc)
122148
else:
123149
try:
124-
body = media_type.unmarshal(
125-
casted, self.custom_formatters,
126-
resolver=self.spec._resolver,
127-
)
128-
except InvalidMediaTypeValue as exc:
150+
body = self._unmarshal(media_type, casted)
151+
except (ValidateError, UnmarshalError) as exc:
129152
errors.append(exc)
130153

131154
return body, errors
155+
156+
def _unmarshal(self, param_or_media_type, value):
157+
if not param_or_media_type.schema:
158+
return value
159+
160+
return param_or_media_type.schema.unmarshal(
161+
value,
162+
resolver=self.spec._resolver,
163+
custom_formatters=self.custom_formatters,
164+
)

openapi_core/validation/response/shortcuts.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
"""OpenAPI core validation response shortcuts module"""
2+
import warnings
3+
24
from openapi_core.validation.response.validators import ResponseValidator
35

46

@@ -8,6 +10,17 @@ def validate_response(validator, request, response):
810
return result
911

1012

13+
def validate_data(validator, request, response):
14+
warnings.warn(
15+
"validate_data shortcut is deprecated, "
16+
"use validator.validate instead",
17+
DeprecationWarning,
18+
)
19+
result = validator._validate_data(request, response)
20+
result.raise_for_errors()
21+
return result
22+
23+
1124
def spec_validate_data(
1225
spec, request, response,
1326
request_factory=None,
@@ -18,6 +31,6 @@ def spec_validate_data(
1831
response = response_factory(response)
1932

2033
validator = ResponseValidator(spec)
21-
result = validate_response(validator, request, response)
34+
result = validate_data(validator, request, response)
2235

2336
return result.data

0 commit comments

Comments
 (0)