Skip to content

Commit 5e9af67

Browse files
authored
Merge pull request #392 from p1c2u/refactor/validators-exceptions-catch
Validators exceptions catch refactor
2 parents 51fa9cd + 9837b86 commit 5e9af67

File tree

4 files changed

+143
-75
lines changed

4 files changed

+143
-75
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from dataclasses import dataclass
2+
from typing import List
3+
4+
from openapi_core.validation.request.datatypes import Parameters
5+
6+
7+
@dataclass
8+
class ParametersError(Exception):
9+
parameters: Parameters
10+
context: List[Exception]

openapi_core/validation/request/validators.py

Lines changed: 65 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from openapi_core.validation.exceptions import InvalidSecurity
2222
from openapi_core.validation.request.datatypes import Parameters
2323
from openapi_core.validation.request.datatypes import RequestValidationResult
24+
from openapi_core.validation.request.exceptions import ParametersError
2425
from openapi_core.validation.validators import BaseValidator
2526

2627

@@ -74,7 +75,10 @@ def _get_parameters(self, request, path, operation):
7475
location = getattr(parameters, param_location)
7576
location[param_name] = value
7677

77-
return parameters, errors
78+
if errors:
79+
raise ParametersError(context=errors, parameters=parameters)
80+
81+
return parameters
7882

7983
def _get_parameter(self, param, request):
8084
name = param["name"]
@@ -114,7 +118,7 @@ def _get_security(self, request, operation):
114118
except SecurityError:
115119
continue
116120

117-
raise InvalidSecurity()
121+
raise InvalidSecurity
118122

119123
def _get_security_value(self, scheme_name, request):
120124
security_schemes = self.spec / "components#securitySchemes"
@@ -126,44 +130,24 @@ def _get_security_value(self, scheme_name, request):
126130

127131
def _get_body(self, request, operation):
128132
if "requestBody" not in operation:
129-
return None, []
133+
return None
130134

131135
request_body = operation / "requestBody"
132136

133-
try:
134-
raw_body = self._get_body_value(request_body, request)
135-
except MissingRequiredRequestBody as exc:
136-
return None, [exc]
137-
except MissingRequestBody:
138-
return None, []
139-
140-
try:
141-
media_type, mimetype = self._get_media_type(
142-
request_body / "content", request.mimetype
143-
)
144-
except MediaTypeFinderError as exc:
145-
return None, [exc]
146-
147-
try:
148-
deserialised = self._deserialise_data(mimetype, raw_body)
149-
except DeserializeError as exc:
150-
return None, [exc]
151-
152-
try:
153-
casted = self._cast(media_type, deserialised)
154-
except CastError as exc:
155-
return None, [exc]
137+
raw_body = self._get_body_value(request_body, request)
138+
media_type, mimetype = self._get_media_type(
139+
request_body / "content", request.mimetype
140+
)
141+
deserialised = self._deserialise_data(mimetype, raw_body)
142+
casted = self._cast(media_type, deserialised)
156143

157144
if "schema" not in media_type:
158-
return casted, []
145+
return casted
159146

160147
schema = media_type / "schema"
161-
try:
162-
body = self._unmarshal(schema, casted)
163-
except (ValidateError, UnmarshalError) as exc:
164-
return None, [exc]
148+
body = self._unmarshal(schema, casted)
165149

166-
return body, []
150+
return body
167151

168152
def _get_body_value(self, request_body, request):
169153
if not request.body:
@@ -186,7 +170,13 @@ def validate(self, request):
186170
request.parameters.path or path_result.variables
187171
)
188172

189-
params, params_errors = self._get_parameters(request, path, operation)
173+
try:
174+
params = self._get_parameters(request, path, operation)
175+
except ParametersError as exc:
176+
params = exc.parameters
177+
params_errors = exc.context
178+
else:
179+
params_errors = []
190180

191181
return RequestValidationResult(
192182
errors=params_errors,
@@ -203,10 +193,26 @@ def validate(self, request):
203193
except PathError as exc:
204194
return RequestValidationResult(errors=[exc])
205195

206-
body, body_errors = self._get_body(request, operation)
196+
try:
197+
body = self._get_body(request, operation)
198+
except (
199+
MissingRequiredRequestBody,
200+
MediaTypeFinderError,
201+
DeserializeError,
202+
CastError,
203+
ValidateError,
204+
UnmarshalError,
205+
) as exc:
206+
body = None
207+
errors = [exc]
208+
except MissingRequestBody:
209+
body = None
210+
errors = []
211+
else:
212+
errors = []
207213

208214
return RequestValidationResult(
209-
errors=body_errors,
215+
errors=errors,
210216
body=body,
211217
)
212218

@@ -250,9 +256,31 @@ def validate(self, request):
250256
request.parameters.path or path_result.variables
251257
)
252258

253-
params, params_errors = self._get_parameters(request, path, operation)
259+
try:
260+
params = self._get_parameters(request, path, operation)
261+
except ParametersError as exc:
262+
params = exc.parameters
263+
params_errors = exc.context
264+
else:
265+
params_errors = []
254266

255-
body, body_errors = self._get_body(request, operation)
267+
try:
268+
body = self._get_body(request, operation)
269+
except (
270+
MissingRequiredRequestBody,
271+
MediaTypeFinderError,
272+
DeserializeError,
273+
CastError,
274+
ValidateError,
275+
UnmarshalError,
276+
) as exc:
277+
body = None
278+
body_errors = [exc]
279+
except MissingRequestBody:
280+
body = None
281+
body_errors = []
282+
else:
283+
body_errors = []
256284

257285
errors = params_errors + body_errors
258286
return RequestValidationResult(
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from dataclasses import dataclass
2+
from typing import Any
3+
from typing import Dict
4+
from typing import List
5+
6+
7+
@dataclass
8+
class HeadersError(Exception):
9+
headers: Dict[str, Any]
10+
context: List[Exception]

openapi_core/validation/response/validators.py

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
SchemaUnmarshallersFactory,
1717
)
1818
from openapi_core.validation.response.datatypes import ResponseValidationResult
19+
from openapi_core.validation.response.exceptions import HeadersError
1920
from openapi_core.validation.validators import BaseValidator
2021

2122

@@ -46,40 +47,22 @@ def _get_operation_response(self, operation, response):
4647

4748
def _get_data(self, response, operation_response):
4849
if "content" not in operation_response:
49-
return None, []
50+
return None
5051

51-
try:
52-
media_type, mimetype = self._get_media_type(
53-
operation_response / "content", response.mimetype
54-
)
55-
except MediaTypeFinderError as exc:
56-
return None, [exc]
57-
58-
try:
59-
raw_data = self._get_data_value(response)
60-
except MissingResponseContent as exc:
61-
return None, [exc]
62-
63-
try:
64-
deserialised = self._deserialise_data(mimetype, raw_data)
65-
except DeserializeError as exc:
66-
return None, [exc]
67-
68-
try:
69-
casted = self._cast(media_type, deserialised)
70-
except CastError as exc:
71-
return None, [exc]
52+
media_type, mimetype = self._get_media_type(
53+
operation_response / "content", response.mimetype
54+
)
55+
raw_data = self._get_data_value(response)
56+
deserialised = self._deserialise_data(mimetype, raw_data)
57+
casted = self._cast(media_type, deserialised)
7258

7359
if "schema" not in media_type:
74-
return casted, []
60+
return casted
7561

7662
schema = media_type / "schema"
77-
try:
78-
data = self._unmarshal(schema, casted)
79-
except (ValidateError, UnmarshalError) as exc:
80-
return None, [exc]
63+
data = self._unmarshal(schema, casted)
8164

82-
return data, []
65+
return data
8366

8467
def _get_data_value(self, response):
8568
if not response.data:
@@ -89,7 +72,7 @@ def _get_data_value(self, response):
8972

9073
def _get_headers(self, response, operation_response):
9174
if "headers" not in operation_response:
92-
return {}, []
75+
return {}
9376

9477
headers = operation_response / "headers"
9578

@@ -115,7 +98,10 @@ def _get_headers(self, response, operation_response):
11598
else:
11699
validated[name] = value
117100

118-
return validated, errors
101+
if errors:
102+
raise HeadersError(context=errors, headers=validated)
103+
104+
return validated
119105

120106
def _get_header(self, name, header, response):
121107
deprecated = header.getkey("deprecated", False)
@@ -146,7 +132,20 @@ def validate(self, request, response):
146132
except (PathError, ResponseFinderError) as exc:
147133
return ResponseValidationResult(errors=[exc])
148134

149-
data, data_errors = self._get_data(response, operation_response)
135+
try:
136+
data = self._get_data(response, operation_response)
137+
except (
138+
MediaTypeFinderError,
139+
MissingResponseContent,
140+
DeserializeError,
141+
CastError,
142+
ValidateError,
143+
UnmarshalError,
144+
) as exc:
145+
data = None
146+
data_errors = [exc]
147+
else:
148+
data_errors = []
150149

151150
return ResponseValidationResult(
152151
errors=data_errors,
@@ -164,9 +163,13 @@ def validate(self, request, response):
164163
except (PathError, ResponseFinderError) as exc:
165164
return ResponseValidationResult(errors=[exc])
166165

167-
headers, headers_errors = self._get_headers(
168-
response, operation_response
169-
)
166+
try:
167+
headers = self._get_headers(response, operation_response)
168+
except HeadersError as exc:
169+
headers = exc.headers
170+
headers_errors = exc.context
171+
else:
172+
headers_errors = []
170173

171174
return ResponseValidationResult(
172175
errors=headers_errors,
@@ -184,11 +187,28 @@ def validate(self, request, response):
184187
except (PathError, ResponseFinderError) as exc:
185188
return ResponseValidationResult(errors=[exc])
186189

187-
data, data_errors = self._get_data(response, operation_response)
190+
try:
191+
data = self._get_data(response, operation_response)
192+
except (
193+
MediaTypeFinderError,
194+
MissingResponseContent,
195+
DeserializeError,
196+
CastError,
197+
ValidateError,
198+
UnmarshalError,
199+
) as exc:
200+
data = None
201+
data_errors = [exc]
202+
else:
203+
data_errors = []
188204

189-
headers, headers_errors = self._get_headers(
190-
response, operation_response
191-
)
205+
try:
206+
headers = self._get_headers(response, operation_response)
207+
except HeadersError as exc:
208+
headers = exc.headers
209+
headers_errors = exc.context
210+
else:
211+
headers_errors = []
192212

193213
errors = data_errors + headers_errors
194214
return ResponseValidationResult(

0 commit comments

Comments
 (0)