Skip to content

Commit 90100c5

Browse files
committed
Finder exception
1 parent 817ff5c commit 90100c5

File tree

12 files changed

+86
-45
lines changed

12 files changed

+86
-45
lines changed

openapi_core/contrib/flask/handlers.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
from flask.json import dumps
44

55
from openapi_core.schema.media_types.exceptions import InvalidContentType
6-
from openapi_core.schema.servers.exceptions import InvalidServer
6+
from openapi_core.templating.paths.exceptions import (
7+
OperationNotFound, PathNotFound,
8+
)
79

810

911
class FlaskOpenAPIErrorsHandler(object):
1012

1113
OPENAPI_ERROR_STATUS = {
12-
InvalidServer: 500,
14+
OperationNotFound: 500,
15+
PathNotFound: 500,
1316
InvalidContentType: 415,
1417
}
1518

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import attr
2+
3+
from openapi_core.exceptions import OpenAPIError
4+
5+
6+
class PathError(OpenAPIError):
7+
"""Path error"""
8+
9+
10+
@attr.s(hash=True)
11+
class PathNotFound(PathError):
12+
"""Find path error"""
13+
path_pattern = attr.ib()
14+
15+
def __str__(self):
16+
return "Path not found for {0}".format(self.path_pattern)
17+
18+
19+
@attr.s(hash=True)
20+
class OperationNotFound(PathError):
21+
"""Find path operation error"""
22+
path_pattern = attr.ib()
23+
operation = attr.ib()
24+
25+
def __str__(self):
26+
return "Operation {0} not found for {0}".format(
27+
self.operation, self.path_pattern)

openapi_core/templating/paths/finders.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
"""OpenAPI core templating paths finders module"""
2+
from openapi_core.schema.operations.exceptions import InvalidOperation
3+
from openapi_core.schema.paths.exceptions import InvalidPath
4+
from openapi_core.schema.servers.exceptions import InvalidServer
5+
from openapi_core.templating.paths.exceptions import (
6+
PathNotFound, OperationNotFound,
7+
)
28
from openapi_core.templating.paths.util import get_operation_pattern
39

410

@@ -8,16 +14,22 @@ def __init__(self, spec):
814
self.spec = spec
915

1016
def find(self, request):
11-
operation_pattern = self._get_operation_pattern(request)
12-
13-
path = self.spec[operation_pattern]
14-
path_variables = {}
15-
operation = self.spec.get_operation(operation_pattern, request.method)
16-
servers = path.servers or operation.servers or self.spec.servers
17-
server = servers[0]
18-
server_variables = {}
19-
20-
return path, operation, server, path_variables, server_variables
17+
try:
18+
operation_pattern = self._get_operation_pattern(request)
19+
20+
path = self.spec[operation_pattern]
21+
path_variables = {}
22+
operation = self.spec.get_operation(
23+
operation_pattern, request.method)
24+
servers = path.servers or operation.servers or self.spec.servers
25+
server = servers[0]
26+
server_variables = {}
27+
except (InvalidServer, InvalidPath):
28+
raise PathNotFound(request.full_url_pattern)
29+
except InvalidOperation:
30+
raise OperationNotFound(request.full_url_pattern, request.method)
31+
else:
32+
return path, operation, server, path_variables, server_variables
2133

2234
def _get_operation_pattern(self, request):
2335
server = self.spec.get_server(request.full_url_pattern)

openapi_core/validation/request/validators.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@
55
from openapi_core.casting.schemas.exceptions import CastError
66
from openapi_core.deserializing.exceptions import DeserializeError
77
from openapi_core.schema.media_types.exceptions import InvalidContentType
8-
from openapi_core.schema.operations.exceptions import InvalidOperation
98
from openapi_core.schema.parameters.exceptions import (
109
MissingRequiredParameter, MissingParameter,
1110
)
12-
from openapi_core.schema.paths.exceptions import InvalidPath
1311
from openapi_core.schema.request_bodies.exceptions import MissingRequestBody
14-
from openapi_core.schema.servers.exceptions import InvalidServer
1512
from openapi_core.security.exceptions import SecurityError
13+
from openapi_core.templating.paths.exceptions import PathError
1614
from openapi_core.unmarshalling.schemas.enums import UnmarshalContext
1715
from openapi_core.unmarshalling.schemas.exceptions import (
1816
UnmarshalError, ValidateError,
@@ -30,7 +28,7 @@ def validate(self, request):
3028
try:
3129
path, operation, _, _, _ = self._find_path(request)
3230
# don't process if operation errors
33-
except (InvalidServer, InvalidPath, InvalidOperation) as exc:
31+
except PathError as exc:
3432
return RequestValidationResult([exc, ], None, None, None)
3533

3634
try:
@@ -53,7 +51,7 @@ def validate(self, request):
5351
def _validate_parameters(self, request):
5452
try:
5553
path, operation, _, _, _ = self._find_path(request)
56-
except (InvalidServer, InvalidPath, InvalidOperation) as exc:
54+
except PathError as exc:
5755
return RequestValidationResult([exc, ], None, None)
5856

5957
params, params_errors = self._get_parameters(
@@ -67,7 +65,7 @@ def _validate_parameters(self, request):
6765
def _validate_body(self, request):
6866
try:
6967
_, operation, _, _, _ = self._find_path(request)
70-
except (InvalidServer, InvalidOperation) as exc:
68+
except PathError as exc:
7169
return RequestValidationResult([exc, ], None, None)
7270

7371
body, body_errors = self._get_body(request, operation)

openapi_core/validation/response/validators.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
"""OpenAPI core validation response validators module"""
22
from openapi_core.casting.schemas.exceptions import CastError
33
from openapi_core.deserializing.exceptions import DeserializeError
4-
from openapi_core.schema.operations.exceptions import InvalidOperation
54
from openapi_core.schema.media_types.exceptions import InvalidContentType
6-
from openapi_core.schema.paths.exceptions import InvalidPath
75
from openapi_core.schema.responses.exceptions import (
86
InvalidResponse, MissingResponseContent,
97
)
10-
from openapi_core.schema.servers.exceptions import InvalidServer
8+
from openapi_core.templating.paths.exceptions import PathError
119
from openapi_core.unmarshalling.schemas.enums import UnmarshalContext
1210
from openapi_core.unmarshalling.schemas.exceptions import (
1311
UnmarshalError, ValidateError,
@@ -22,7 +20,7 @@ def validate(self, request, response):
2220
try:
2321
_, operation, _, _, _ = self._find_path(request)
2422
# don't process if operation errors
25-
except (InvalidServer, InvalidPath, InvalidOperation) as exc:
23+
except PathError as exc:
2624
return ResponseValidationResult([exc, ], None, None)
2725

2826
try:
@@ -47,7 +45,7 @@ def _validate_data(self, request, response):
4745
try:
4846
_, operation, _, _, _ = self._find_path(request)
4947
# don't process if operation errors
50-
except (InvalidServer, InvalidPath, InvalidOperation) as exc:
48+
except PathError as exc:
5149
return ResponseValidationResult([exc, ], None, None)
5250

5351
try:

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ lazy-object-proxy
44
strict_rfc3339
55
isodate
66
attrs
7+
parse==1.14.0

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ install_requires =
3030
isodate
3131
attrs
3232
werkzeug
33+
parse
3334
backports.functools-lru-cache; python_version<"3.0"
3435
backports.functools-partialmethod; python_version<"3.0"
3536
tests_require =

tests/integration/contrib/flask/test_flask_decorator.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,12 @@ def test_server_error(self, client):
8080
'errors': [
8181
{
8282
'class': (
83-
"<class 'openapi_core.schema.servers.exceptions."
84-
"InvalidServer'>"
83+
"<class 'openapi_core.templating.paths.exceptions."
84+
"PathNotFound'>"
8585
),
8686
'status': 500,
8787
'title': (
88-
'Invalid request server '
88+
'Path not found for '
8989
'https://localhost/browse/{id}/'
9090
),
9191
}

tests/integration/contrib/flask/test_flask_views.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ def test_server_error(self, client):
6868
'errors': [
6969
{
7070
'class': (
71-
"<class 'openapi_core.schema.servers.exceptions."
72-
"InvalidServer'>"
71+
"<class 'openapi_core.templating.paths.exceptions."
72+
"PathNotFound'>"
7373
),
7474
'status': 500,
7575
'title': (
76-
'Invalid request server '
76+
'Path not found for '
7777
'https://localhost/browse/{id}/'
7878
),
7979
}

tests/integration/validation/test_minimal.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import pytest
22

3-
from openapi_core.schema.operations.exceptions import InvalidOperation
4-
from openapi_core.schema.paths.exceptions import InvalidPath
53
from openapi_core.shortcuts import create_spec
4+
from openapi_core.templating.paths.exceptions import (
5+
PathNotFound, OperationNotFound,
6+
)
67
from openapi_core.testing import MockRequest
78
from openapi_core.validation.request.validators import RequestValidator
89

@@ -45,7 +46,7 @@ def test_invalid_operation(self, factory, server, spec_path):
4546
result = validator.validate(request)
4647

4748
assert len(result.errors) == 1
48-
assert isinstance(result.errors[0], InvalidOperation)
49+
assert isinstance(result.errors[0], OperationNotFound)
4950
assert result.body is None
5051
assert result.parameters is None
5152

@@ -60,6 +61,6 @@ def test_invalid_path(self, factory, server, spec_path):
6061
result = validator.validate(request)
6162

6263
assert len(result.errors) == 1
63-
assert isinstance(result.errors[0], InvalidPath)
64+
assert isinstance(result.errors[0], PathNotFound)
6465
assert result.body is None
6566
assert result.parameters is None

0 commit comments

Comments
 (0)