Skip to content

Commit 37f09d7

Browse files
committed
Factories and exceptions cleanup
1 parent e85d2d9 commit 37f09d7

File tree

12 files changed

+214
-246
lines changed

12 files changed

+214
-246
lines changed

openapi_core/__init__.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
"""OpenAPI core module"""
22
from openapi_core.shortcuts import create_spec
3-
from openapi_core.wrappers import RequestParametersFactory, RequestBodyFactory
43

54
__author__ = 'Artur Maciąg'
65
__email__ = 'maciag.artur@gmail.com'
76
__version__ = '0.2.2'
87
__url__ = 'https://github.com/p1c2u/openapi-core'
98
__license__ = 'BSD 3-Clause License'
109

11-
__all__ = ['create_spec', 'request_parameters_factory', 'request_body_factory']
12-
13-
request_parameters_factory = RequestParametersFactory()
14-
request_body_factory = RequestBodyFactory()
10+
__all__ = ['create_spec', ]

openapi_core/exceptions.py

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,41 +9,65 @@ class OpenAPIMappingError(OpenAPIError):
99
pass
1010

1111

12-
class MissingParameterError(OpenAPIMappingError):
12+
class OpenAPIServerError(OpenAPIMappingError):
1313
pass
1414

1515

16-
class MissingBodyError(OpenAPIMappingError):
16+
class OpenAPIOperationError(OpenAPIMappingError):
1717
pass
1818

1919

20-
class MissingPropertyError(OpenAPIMappingError):
20+
class InvalidValueType(OpenAPIMappingError):
2121
pass
2222

2323

24-
class InvalidContentTypeError(OpenAPIMappingError):
24+
class OpenAPIParameterError(OpenAPIMappingError):
2525
pass
2626

2727

28-
class InvalidOperationError(OpenAPIMappingError):
28+
class OpenAPIBodyError(OpenAPIMappingError):
2929
pass
3030

3131

32-
class InvalidServerError(OpenAPIMappingError):
32+
class InvalidServer(OpenAPIServerError):
3333
pass
3434

3535

36-
class InvalidValueType(OpenAPIMappingError):
36+
class InvalidOperation(OpenAPIOperationError):
3737
pass
3838

3939

40-
class InvalidValue(OpenAPIMappingError):
40+
class EmptyValue(OpenAPIParameterError):
41+
pass
42+
43+
44+
class MissingParameter(OpenAPIParameterError):
45+
pass
46+
47+
48+
class InvalidParameterValue(OpenAPIParameterError):
49+
pass
50+
51+
52+
class MissingBody(OpenAPIBodyError):
53+
pass
54+
55+
56+
class InvalidMediaTypeValue(OpenAPIBodyError):
4157
pass
4258

4359

44-
class EmptyValue(OpenAPIMappingError):
60+
class UndefinedSchemaProperty(OpenAPIBodyError):
4561
pass
4662

4763

48-
class UndefinedSchemaProperty(OpenAPIMappingError):
64+
class MissingProperty(OpenAPIBodyError):
65+
pass
66+
67+
68+
class InvalidContentType(OpenAPIBodyError):
69+
pass
70+
71+
72+
class InvalidValue(OpenAPIMappingError):
4973
pass

openapi_core/media_types.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
"""OpenAPI core mediaTypes module"""
22
from six import iteritems
33

4+
from openapi_core.exceptions import InvalidValueType, InvalidMediaTypeValue
5+
46

57
class MediaType(object):
68
"""Represents an OpenAPI MediaType."""
@@ -13,7 +15,10 @@ def unmarshal(self, value):
1315
if not self.schema:
1416
return value
1517

16-
return self.schema.unmarshal(value)
18+
try:
19+
return self.schema.unmarshal(value)
20+
except InvalidValueType as exc:
21+
raise InvalidMediaTypeValue(str(exc))
1722

1823

1924
class MediaTypeGenerator(object):

openapi_core/parameters.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
import logging
33
import warnings
44

5-
from openapi_core.exceptions import EmptyValue
5+
from openapi_core.exceptions import (
6+
EmptyValue, InvalidValueType, InvalidParameterValue,
7+
)
68

79
log = logging.getLogger(__name__)
810

@@ -35,12 +37,15 @@ def unmarshal(self, value):
3537
if (self.location == "query" and value == "" and
3638
not self.allow_empty_value):
3739
raise EmptyValue(
38-
"Value of {0} parameter cannot be empty.".format(self.name))
40+
"Value of {0} parameter cannot be empty".format(self.name))
3941

4042
if not self.schema:
4143
return value
4244

43-
return self.schema.unmarshal(value)
45+
try:
46+
return self.schema.unmarshal(value)
47+
except InvalidValueType as exc:
48+
raise InvalidParameterValue(str(exc))
4449

4550

4651
class ParametersGenerator(object):

openapi_core/request_bodies.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""OpenAPI core requestBodies module"""
22
from functools import lru_cache
33

4-
from openapi_core.exceptions import InvalidContentTypeError
4+
from openapi_core.exceptions import InvalidContentType
55
from openapi_core.media_types import MediaTypeGenerator
66

77

@@ -16,7 +16,7 @@ def __getitem__(self, mimetype):
1616
try:
1717
return self.content[mimetype]
1818
except KeyError:
19-
raise InvalidContentTypeError(
19+
raise InvalidContentType(
2020
"Invalid mime type `{0}`".format(mimetype))
2121

2222

openapi_core/schemas.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
from six import iteritems
1111

1212
from openapi_core.exceptions import (
13-
InvalidValueType, UndefinedSchemaProperty, MissingPropertyError,
14-
InvalidValue,
13+
InvalidValueType, UndefinedSchemaProperty, MissingProperty, InvalidValue,
1514
)
1615
from openapi_core.models import ModelFactory
1716

@@ -59,7 +58,8 @@ def cast(self, value):
5958
if value is None:
6059
if not self.nullable:
6160
raise InvalidValueType(
62-
"Failed to cast value of %s to %s", value, self.type,
61+
"Failed to cast value of {0} to {1}".format(
62+
value, self.type)
6363
)
6464
return self.default
6565

@@ -73,7 +73,7 @@ def cast(self, value):
7373
return cast_callable(value)
7474
except ValueError:
7575
raise InvalidValueType(
76-
"Failed to cast value of %s to %s", value, self.type,
76+
"Failed to cast value of {0} to {1}".format(value, self.type)
7777
)
7878

7979
def unmarshal(self, value):
@@ -88,7 +88,8 @@ def unmarshal(self, value):
8888

8989
if self.enum and casted not in self.enum:
9090
raise InvalidValue(
91-
"Value of %s not in enum choices: %s", value, str(self.enum),
91+
"Value of {0} not in enum choices: {1}".format(
92+
value, self.enum)
9293
)
9394

9495
return casted
@@ -115,7 +116,7 @@ def _unmarshal_object(self, value):
115116
prop_value = value[prop_name]
116117
except KeyError:
117118
if prop_name in self.required:
118-
raise MissingPropertyError(
119+
raise MissingProperty(
119120
"Missing schema property {0}".format(prop_name))
120121
if not prop.nullable and not prop.default:
121122
continue

openapi_core/specs.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from openapi_spec_validator import openapi_v3_spec_validator
77

88
from openapi_core.components import ComponentsFactory
9-
from openapi_core.exceptions import InvalidOperationError, InvalidServerError
9+
from openapi_core.exceptions import InvalidOperation, InvalidServer
1010
from openapi_core.infos import InfoFactory
1111
from openapi_core.paths import PathsGenerator
1212
from openapi_core.schemas import SchemaRegistry
@@ -37,7 +37,7 @@ def get_server(self, full_url_pattern):
3737
if spec_server.default_url in full_url_pattern:
3838
return spec_server
3939

40-
raise InvalidServerError(
40+
raise InvalidServer(
4141
"Invalid request server {0}".format(full_url_pattern))
4242

4343
def get_server_url(self, index=0):
@@ -47,7 +47,7 @@ def get_operation(self, path_pattern, http_method):
4747
try:
4848
return self.paths[path_pattern].operations[http_method]
4949
except KeyError:
50-
raise InvalidOperationError(
50+
raise InvalidOperation(
5151
"Unknown operation path {0} with method {1}".format(
5252
path_pattern, http_method))
5353

openapi_core/validators.py

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from six import iteritems
33

44
from openapi_core.exceptions import (
5-
OpenAPIMappingError, MissingParameterError, MissingBodyError,
5+
OpenAPIMappingError, MissingParameter, MissingBody,
66
)
77

88

@@ -45,13 +45,6 @@ def __init__(self, errors, body=None, parameters=None):
4545

4646
class RequestValidator(object):
4747

48-
SPEC_LOCATION_TO_REQUEST_LOCATION = {
49-
'path': 'view_args',
50-
'query': 'args',
51-
'headers': 'headers',
52-
'cookies': 'cookies',
53-
}
54-
5548
def __init__(self, spec):
5649
self.spec = spec
5750

@@ -69,10 +62,10 @@ def validate(self, request):
6962

7063
operation_pattern = request.full_url_pattern.replace(
7164
server.default_url, '')
72-
method = request.method.lower()
7365

7466
try:
75-
operation = self.spec.get_operation(operation_pattern, method)
67+
operation = self.spec.get_operation(
68+
operation_pattern, request.method)
7669
# don't process if operation errors
7770
except OpenAPIMappingError as exc:
7871
errors.append(exc)
@@ -81,17 +74,20 @@ def validate(self, request):
8174
for param_name, param in iteritems(operation.parameters):
8275
try:
8376
raw_value = self._get_raw_value(request, param)
84-
except MissingParameterError as exc:
77+
except MissingParameter as exc:
8578
if param.required:
8679
errors.append(exc)
8780

8881
if not param.schema or param.schema.default is None:
8982
continue
9083
raw_value = param.schema.default
9184

92-
value = param.unmarshal(raw_value)
93-
94-
parameters[param.location][param_name] = value
85+
try:
86+
value = param.unmarshal(raw_value)
87+
except OpenAPIMappingError as exc:
88+
errors.append(exc)
89+
else:
90+
parameters[param.location][param_name] = value
9591

9692
if operation.request_body is not None:
9793
try:
@@ -101,29 +97,26 @@ def validate(self, request):
10197
else:
10298
try:
10399
raw_body = self._get_raw_body(request)
104-
except MissingBodyError as exc:
100+
except MissingBody as exc:
105101
if operation.request_body.required:
106102
errors.append(exc)
107103
else:
108-
body = media_type.unmarshal(raw_body)
104+
try:
105+
body = media_type.unmarshal(raw_body)
106+
except OpenAPIMappingError as exc:
107+
errors.append(exc)
109108

110109
return RequestValidationResult(errors, body, parameters)
111110

112-
def _get_request_location(self, spec_location):
113-
return self.SPEC_LOCATION_TO_REQUEST_LOCATION[spec_location]
114-
115111
def _get_raw_value(self, request, param):
116-
request_location = self._get_request_location(param.location)
117-
request_attr = getattr(request, request_location)
118-
119112
try:
120-
return request_attr[param.name]
113+
return request.parameters[param.location][param.name]
121114
except KeyError:
122-
raise MissingParameterError(
115+
raise MissingParameter(
123116
"Missing required `{0}` parameter".format(param.name))
124117

125118
def _get_raw_body(self, request):
126-
if not request.data:
127-
raise MissingBodyError("Missing required request body")
119+
if not request.body:
120+
raise MissingBody("Missing required request body")
128121

129-
return request.data
122+
return request.body

0 commit comments

Comments
 (0)