mirror of
https://github.com/correl/openapi-core.git
synced 2024-12-29 11:09:25 +00:00
Parameters on path item object support
This commit is contained in:
parent
40944119d1
commit
27ebae3182
6 changed files with 74 additions and 7 deletions
15
openapi_core/schema/paths/exceptions.py
Normal file
15
openapi_core/schema/paths/exceptions.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import attr
|
||||||
|
|
||||||
|
from openapi_core.schema.exceptions import OpenAPIMappingError
|
||||||
|
|
||||||
|
|
||||||
|
class OpenAPIPathError(OpenAPIMappingError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@attr.s(hash=True)
|
||||||
|
class InvalidPath(OpenAPIPathError):
|
||||||
|
path_pattern = attr.ib()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Unknown path {0}".format(self.path_pattern)
|
|
@ -4,6 +4,7 @@ import logging
|
||||||
|
|
||||||
from openapi_core.compat import partialmethod
|
from openapi_core.compat import partialmethod
|
||||||
from openapi_core.schema.operations.exceptions import InvalidOperation
|
from openapi_core.schema.operations.exceptions import InvalidOperation
|
||||||
|
from openapi_core.schema.paths.exceptions import InvalidPath
|
||||||
from openapi_core.schema.servers.exceptions import InvalidServer
|
from openapi_core.schema.servers.exceptions import InvalidServer
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,8 +20,8 @@ class Spec(object):
|
||||||
self.servers = servers or []
|
self.servers = servers or []
|
||||||
self.components = components
|
self.components = components
|
||||||
|
|
||||||
def __getitem__(self, path_name):
|
def __getitem__(self, path_pattern):
|
||||||
return self.paths[path_name]
|
return self.get_path(path_pattern)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def default_url(self):
|
def default_url(self):
|
||||||
|
@ -36,6 +37,12 @@ class Spec(object):
|
||||||
def get_server_url(self, index=0):
|
def get_server_url(self, index=0):
|
||||||
return self.servers[index].default_url
|
return self.servers[index].default_url
|
||||||
|
|
||||||
|
def get_path(self, path_pattern):
|
||||||
|
try:
|
||||||
|
return self.paths[path_pattern]
|
||||||
|
except KeyError:
|
||||||
|
raise InvalidPath(path_pattern)
|
||||||
|
|
||||||
def get_operation(self, path_pattern, http_method):
|
def get_operation(self, path_pattern, http_method):
|
||||||
try:
|
try:
|
||||||
return self.paths[path_pattern].operations[http_method]
|
return self.paths[path_pattern].operations[http_method]
|
||||||
|
|
|
@ -16,6 +16,16 @@ class RequestParameters(dict):
|
||||||
def __setitem__(self, location, value):
|
def __setitem__(self, location, value):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
if not isinstance(other, self.__class__):
|
||||||
|
raise ValueError("Invalid type")
|
||||||
|
|
||||||
|
for location in self.valid_locations:
|
||||||
|
if location in other:
|
||||||
|
self[location].update(other[location])
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_location(cls, location):
|
def validate_location(cls, location):
|
||||||
if location not in cls.valid_locations:
|
if location not in cls.valid_locations:
|
||||||
|
|
|
@ -26,6 +26,14 @@ class RequestValidator(object):
|
||||||
server.default_url, request.full_url_pattern
|
server.default_url, request.full_url_pattern
|
||||||
)
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
path = self.spec[operation_pattern]
|
||||||
|
# don't process if operation errors
|
||||||
|
except OpenAPIMappingError as exc:
|
||||||
|
return RequestValidationResult([exc, ], None, None)
|
||||||
|
|
||||||
|
path_params, path_params_errors = self._get_parameters(request, path)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
operation = self.spec.get_operation(
|
operation = self.spec.get_operation(
|
||||||
operation_pattern, request.method)
|
operation_pattern, request.method)
|
||||||
|
@ -33,11 +41,11 @@ class RequestValidator(object):
|
||||||
except OpenAPIMappingError as exc:
|
except OpenAPIMappingError as exc:
|
||||||
return RequestValidationResult([exc, ], None, None)
|
return RequestValidationResult([exc, ], None, None)
|
||||||
|
|
||||||
params, params_errors = self._get_parameters(request, operation)
|
op_params, op_params_errors = self._get_parameters(request, operation)
|
||||||
body, body_errors = self._get_body(request, operation)
|
body, body_errors = self._get_body(request, operation)
|
||||||
|
|
||||||
errors = params_errors + body_errors
|
errors = path_params_errors + op_params_errors + body_errors
|
||||||
return RequestValidationResult(errors, body, params)
|
return RequestValidationResult(errors, body, path_params + op_params)
|
||||||
|
|
||||||
def _get_parameters(self, request, operation):
|
def _get_parameters(self, request, operation):
|
||||||
errors = []
|
errors = []
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from openapi_core.schema.operations.exceptions import InvalidOperation
|
from openapi_core.schema.operations.exceptions import InvalidOperation
|
||||||
|
from openapi_core.schema.paths.exceptions import InvalidPath
|
||||||
from openapi_core.shortcuts import create_spec
|
from openapi_core.shortcuts import create_spec
|
||||||
from openapi_core.validation.request.validators import RequestValidator
|
from openapi_core.validation.request.validators import RequestValidator
|
||||||
from openapi_core.wrappers.mock import MockRequest
|
from openapi_core.wrappers.mock import MockRequest
|
||||||
|
@ -39,7 +40,7 @@ class TestMinimal(object):
|
||||||
spec_dict = factory.spec_from_file(spec_path)
|
spec_dict = factory.spec_from_file(spec_path)
|
||||||
spec = create_spec(spec_dict)
|
spec = create_spec(spec_dict)
|
||||||
validator = RequestValidator(spec)
|
validator = RequestValidator(spec)
|
||||||
request = MockRequest(server, "get", "/nonexistent")
|
request = MockRequest(server, "post", "/status")
|
||||||
|
|
||||||
result = validator.validate(request)
|
result = validator.validate(request)
|
||||||
|
|
||||||
|
@ -47,3 +48,18 @@ class TestMinimal(object):
|
||||||
assert isinstance(result.errors[0], InvalidOperation)
|
assert isinstance(result.errors[0], InvalidOperation)
|
||||||
assert result.body is None
|
assert result.body is None
|
||||||
assert result.parameters == {}
|
assert result.parameters == {}
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("server", servers)
|
||||||
|
@pytest.mark.parametrize("spec_path", spec_paths)
|
||||||
|
def test_invalid_path(self, factory, server, spec_path):
|
||||||
|
spec_dict = factory.spec_from_file(spec_path)
|
||||||
|
spec = create_spec(spec_dict)
|
||||||
|
validator = RequestValidator(spec)
|
||||||
|
request = MockRequest(server, "get", "/nonexistent")
|
||||||
|
|
||||||
|
result = validator.validate(request)
|
||||||
|
|
||||||
|
assert len(result.errors) == 1
|
||||||
|
assert isinstance(result.errors[0], InvalidPath)
|
||||||
|
assert result.body is None
|
||||||
|
assert result.parameters == {}
|
||||||
|
|
|
@ -10,6 +10,7 @@ from openapi_core.extensions.models.models import BaseModel
|
||||||
from openapi_core.schema.operations.exceptions import InvalidOperation
|
from openapi_core.schema.operations.exceptions import InvalidOperation
|
||||||
from openapi_core.schema.parameters.exceptions import MissingRequiredParameter
|
from openapi_core.schema.parameters.exceptions import MissingRequiredParameter
|
||||||
from openapi_core.schema.parameters.exceptions import InvalidParameterValue
|
from openapi_core.schema.parameters.exceptions import InvalidParameterValue
|
||||||
|
from openapi_core.schema.paths.exceptions import InvalidPath
|
||||||
from openapi_core.schema.request_bodies.exceptions import MissingRequestBody
|
from openapi_core.schema.request_bodies.exceptions import MissingRequestBody
|
||||||
from openapi_core.schema.responses.exceptions import (
|
from openapi_core.schema.responses.exceptions import (
|
||||||
MissingResponseContent, InvalidResponse,
|
MissingResponseContent, InvalidResponse,
|
||||||
|
@ -55,11 +56,21 @@ class TestRequestValidator(object):
|
||||||
assert result.body is None
|
assert result.body is None
|
||||||
assert result.parameters == {}
|
assert result.parameters == {}
|
||||||
|
|
||||||
def test_invalid_operation(self, validator):
|
def test_invalid_path(self, validator):
|
||||||
request = MockRequest(self.host_url, 'get', '/v1')
|
request = MockRequest(self.host_url, 'get', '/v1')
|
||||||
|
|
||||||
result = validator.validate(request)
|
result = validator.validate(request)
|
||||||
|
|
||||||
|
assert len(result.errors) == 1
|
||||||
|
assert type(result.errors[0]) == InvalidPath
|
||||||
|
assert result.body is None
|
||||||
|
assert result.parameters == {}
|
||||||
|
|
||||||
|
def test_invalid_operation(self, validator):
|
||||||
|
request = MockRequest(self.host_url, 'patch', '/v1/pets')
|
||||||
|
|
||||||
|
result = validator.validate(request)
|
||||||
|
|
||||||
assert len(result.errors) == 1
|
assert len(result.errors) == 1
|
||||||
assert type(result.errors[0]) == InvalidOperation
|
assert type(result.errors[0]) == InvalidOperation
|
||||||
assert result.body is None
|
assert result.body is None
|
||||||
|
|
Loading…
Reference in a new issue