Skip to content

Commit 27ebae3

Browse files
committed
Parameters on path item object support
1 parent 4094411 commit 27ebae3

File tree

6 files changed

+74
-7
lines changed

6 files changed

+74
-7
lines changed
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import attr
2+
3+
from openapi_core.schema.exceptions import OpenAPIMappingError
4+
5+
6+
class OpenAPIPathError(OpenAPIMappingError):
7+
pass
8+
9+
10+
@attr.s(hash=True)
11+
class InvalidPath(OpenAPIPathError):
12+
path_pattern = attr.ib()
13+
14+
def __str__(self):
15+
return "Unknown path {0}".format(self.path_pattern)

openapi_core/schema/specs/models.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from openapi_core.compat import partialmethod
66
from openapi_core.schema.operations.exceptions import InvalidOperation
7+
from openapi_core.schema.paths.exceptions import InvalidPath
78
from openapi_core.schema.servers.exceptions import InvalidServer
89

910

@@ -19,8 +20,8 @@ def __init__(self, info, paths, servers=None, components=None):
1920
self.servers = servers or []
2021
self.components = components
2122

22-
def __getitem__(self, path_name):
23-
return self.paths[path_name]
23+
def __getitem__(self, path_pattern):
24+
return self.get_path(path_pattern)
2425

2526
@property
2627
def default_url(self):
@@ -36,6 +37,12 @@ def get_server(self, full_url_pattern):
3637
def get_server_url(self, index=0):
3738
return self.servers[index].default_url
3839

40+
def get_path(self, path_pattern):
41+
try:
42+
return self.paths[path_pattern]
43+
except KeyError:
44+
raise InvalidPath(path_pattern)
45+
3946
def get_operation(self, path_pattern, http_method):
4047
try:
4148
return self.paths[path_pattern].operations[http_method]

openapi_core/validation/request/models.py

+10
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ def __getitem__(self, location):
1616
def __setitem__(self, location, value):
1717
raise NotImplementedError
1818

19+
def __add__(self, other):
20+
if not isinstance(other, self.__class__):
21+
raise ValueError("Invalid type")
22+
23+
for location in self.valid_locations:
24+
if location in other:
25+
self[location].update(other[location])
26+
27+
return self
28+
1929
@classmethod
2030
def validate_location(cls, location):
2131
if location not in cls.valid_locations:

openapi_core/validation/request/validators.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,26 @@ def validate(self, request):
2626
server.default_url, request.full_url_pattern
2727
)
2828

29+
try:
30+
path = self.spec[operation_pattern]
31+
# don't process if operation errors
32+
except OpenAPIMappingError as exc:
33+
return RequestValidationResult([exc, ], None, None)
34+
35+
path_params, path_params_errors = self._get_parameters(request, path)
36+
2937
try:
3038
operation = self.spec.get_operation(
3139
operation_pattern, request.method)
3240
# don't process if operation errors
3341
except OpenAPIMappingError as exc:
3442
return RequestValidationResult([exc, ], None, None)
3543

36-
params, params_errors = self._get_parameters(request, operation)
44+
op_params, op_params_errors = self._get_parameters(request, operation)
3745
body, body_errors = self._get_body(request, operation)
3846

39-
errors = params_errors + body_errors
40-
return RequestValidationResult(errors, body, params)
47+
errors = path_params_errors + op_params_errors + body_errors
48+
return RequestValidationResult(errors, body, path_params + op_params)
4149

4250
def _get_parameters(self, request, operation):
4351
errors = []

tests/integration/test_minimal.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22

33
from openapi_core.schema.operations.exceptions import InvalidOperation
4+
from openapi_core.schema.paths.exceptions import InvalidPath
45
from openapi_core.shortcuts import create_spec
56
from openapi_core.validation.request.validators import RequestValidator
67
from openapi_core.wrappers.mock import MockRequest
@@ -39,11 +40,26 @@ def test_invalid_operation(self, factory, server, spec_path):
3940
spec_dict = factory.spec_from_file(spec_path)
4041
spec = create_spec(spec_dict)
4142
validator = RequestValidator(spec)
42-
request = MockRequest(server, "get", "/nonexistent")
43+
request = MockRequest(server, "post", "/status")
4344

4445
result = validator.validate(request)
4546

4647
assert len(result.errors) == 1
4748
assert isinstance(result.errors[0], InvalidOperation)
4849
assert result.body is None
4950
assert result.parameters == {}
51+
52+
@pytest.mark.parametrize("server", servers)
53+
@pytest.mark.parametrize("spec_path", spec_paths)
54+
def test_invalid_path(self, factory, server, spec_path):
55+
spec_dict = factory.spec_from_file(spec_path)
56+
spec = create_spec(spec_dict)
57+
validator = RequestValidator(spec)
58+
request = MockRequest(server, "get", "/nonexistent")
59+
60+
result = validator.validate(request)
61+
62+
assert len(result.errors) == 1
63+
assert isinstance(result.errors[0], InvalidPath)
64+
assert result.body is None
65+
assert result.parameters == {}

tests/integration/test_validators.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from openapi_core.schema.operations.exceptions import InvalidOperation
1111
from openapi_core.schema.parameters.exceptions import MissingRequiredParameter
1212
from openapi_core.schema.parameters.exceptions import InvalidParameterValue
13+
from openapi_core.schema.paths.exceptions import InvalidPath
1314
from openapi_core.schema.request_bodies.exceptions import MissingRequestBody
1415
from openapi_core.schema.responses.exceptions import (
1516
MissingResponseContent, InvalidResponse,
@@ -55,11 +56,21 @@ def test_request_server_error(self, validator):
5556
assert result.body is None
5657
assert result.parameters == {}
5758

58-
def test_invalid_operation(self, validator):
59+
def test_invalid_path(self, validator):
5960
request = MockRequest(self.host_url, 'get', '/v1')
6061

6162
result = validator.validate(request)
6263

64+
assert len(result.errors) == 1
65+
assert type(result.errors[0]) == InvalidPath
66+
assert result.body is None
67+
assert result.parameters == {}
68+
69+
def test_invalid_operation(self, validator):
70+
request = MockRequest(self.host_url, 'patch', '/v1/pets')
71+
72+
result = validator.validate(request)
73+
6374
assert len(result.errors) == 1
6475
assert type(result.errors[0]) == InvalidOperation
6576
assert result.body is None

0 commit comments

Comments
 (0)