Parameters on path item object support

This commit is contained in:
Artur Maciag 2019-06-18 16:13:44 +01:00
parent 40944119d1
commit 27ebae3182
6 changed files with 74 additions and 7 deletions

View 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)

View file

@ -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]

View file

@ -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:

View file

@ -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 = []

View file

@ -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 == {}

View file

@ -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