Shortcuts cleanup

This commit is contained in:
Artur Maciag 2020-01-17 14:20:20 +00:00
parent 6f9200eada
commit da3b6ee669
12 changed files with 396 additions and 330 deletions

View file

@ -0,0 +1,12 @@
"""OpenAPI core schema shortcuts module"""
from jsonschema.validators import RefResolver
from openapi_spec_validator import default_handlers
from openapi_core.schema.specs.factories import SpecFactory
def create_spec(spec_dict, spec_url='', handlers=default_handlers):
spec_resolver = RefResolver(
spec_url, spec_dict, handlers=handlers)
spec_factory = SpecFactory(spec_resolver)
return spec_factory.create(spec_dict, spec_url=spec_url)

View file

@ -1,71 +1,14 @@
"""OpenAPI core shortcuts module"""
from jsonschema.validators import RefResolver
from openapi_spec_validator import default_handlers
from openapi_core.schema.media_types.exceptions import OpenAPIMediaTypeError
from openapi_core.schema.parameters.exceptions import OpenAPIParameterError
from openapi_core.schema.request_bodies.exceptions import (
OpenAPIRequestBodyError,
# backward compatibility
from openapi_core.schema.shortcuts import create_spec
from openapi_core.validation.request.shortcuts import (
spec_validate_body as validate_body,
spec_validate_parameters as validate_parameters,
)
from openapi_core.validation.response.shortcuts import (
spec_validate_data as validate_data
)
from openapi_core.schema.schemas.exceptions import OpenAPISchemaError
from openapi_core.schema.specs.factories import SpecFactory
from openapi_core.validation.request.validators import RequestValidator
from openapi_core.validation.response.validators import ResponseValidator
def create_spec(spec_dict, spec_url=''):
spec_resolver = RefResolver(
spec_url, spec_dict, handlers=default_handlers)
spec_factory = SpecFactory(spec_resolver)
return spec_factory.create(spec_dict, spec_url=spec_url)
def validate_parameters(spec, request, request_factory=None):
if request_factory is not None:
request = request_factory(request)
validator = RequestValidator(spec)
result = validator.validate(request)
try:
result.raise_for_errors()
except (
OpenAPIRequestBodyError, OpenAPIMediaTypeError,
OpenAPISchemaError,
):
return result.parameters
else:
return result.parameters
def validate_body(spec, request, request_factory=None):
if request_factory is not None:
request = request_factory(request)
validator = RequestValidator(spec)
result = validator.validate(request)
try:
result.raise_for_errors()
except OpenAPIParameterError:
return result.body
else:
return result.body
def validate_data(
spec, request, response,
request_factory=None,
response_factory=None):
if request_factory is not None:
request = request_factory(request)
if response_factory is not None:
response = response_factory(response)
validator = ResponseValidator(spec)
result = validator.validate(request, response)
result.raise_for_errors()
return result.data
__all__ = [
'create_spec', 'validate_body', 'validate_parameters', 'validate_data',
]

View file

@ -0,0 +1,18 @@
class ResultMock(object):
def __init__(
self, body=None, parameters=None, data=None, error_to_raise=None):
self.body = body
self.parameters = parameters
self.data = data
self.error_to_raise = error_to_raise
def raise_for_errors(self):
if self.error_to_raise is not None:
raise self.error_to_raise
if self.parameters is not None:
return self.parameters
if self.data is not None:
return self.data

View file

@ -0,0 +1,11 @@
class FactoryClassMock(object):
_instances = {}
def __new__(cls, obj):
if obj not in cls._instances:
cls._instances[obj] = object.__new__(cls)
return cls._instances[obj]
def __init__(self, obj):
self.obj = obj

View file

@ -1,45 +1,6 @@
"""OpenAPI core testing mock module"""
from werkzeug.datastructures import ImmutableMultiDict
# backward compatibility
from openapi_core.testing.requests import MockRequestFactory
from openapi_core.testing.responses import MockResponseFactory
from openapi_core.validation.request.datatypes import (
RequestParameters, OpenAPIRequest,
)
from openapi_core.validation.response.datatypes import OpenAPIResponse
class MockRequestFactory(object):
@classmethod
def create(
cls, host_url, method, path, path_pattern=None, args=None,
view_args=None, headers=None, cookies=None, data=None,
mimetype='application/json'):
parameters = RequestParameters(
path=view_args or {},
query=ImmutableMultiDict(args or []),
header=headers or {},
cookie=cookies or {},
)
path_pattern = path_pattern or path
method = method.lower()
body = data or ''
return OpenAPIRequest(
host_url=host_url,
path=path,
path_pattern=path_pattern,
method=method,
parameters=parameters,
body=body,
mimetype=mimetype,
)
class MockResponseFactory(object):
@classmethod
def create(cls, data, status_code=200, mimetype='application/json'):
return OpenAPIResponse(
data=data,
status_code=status_code,
mimetype=mimetype,
)
__all__ = ['MockRequestFactory', 'MockResponseFactory']

View file

@ -0,0 +1,33 @@
"""OpenAPI core testing requests module"""
from werkzeug.datastructures import ImmutableMultiDict
from openapi_core.validation.request.datatypes import (
RequestParameters, OpenAPIRequest,
)
class MockRequestFactory(object):
@classmethod
def create(
cls, host_url, method, path, path_pattern=None, args=None,
view_args=None, headers=None, cookies=None, data=None,
mimetype='application/json'):
parameters = RequestParameters(
path=view_args or {},
query=ImmutableMultiDict(args or []),
header=headers or {},
cookie=cookies or {},
)
path_pattern = path_pattern or path
method = method.lower()
body = data or ''
return OpenAPIRequest(
host_url=host_url,
path=path,
path_pattern=path_pattern,
method=method,
parameters=parameters,
body=body,
mimetype=mimetype,
)

View file

@ -0,0 +1,13 @@
"""OpenAPI core testing responses module"""
from openapi_core.validation.response.datatypes import OpenAPIResponse
class MockResponseFactory(object):
@classmethod
def create(cls, data, status_code=200, mimetype='application/json'):
return OpenAPIResponse(
data=data,
status_code=status_code,
mimetype=mimetype,
)

View file

@ -0,0 +1,52 @@
"""OpenAPI core validation request shortcuts module"""
from functools import partial
from openapi_core.schema.media_types.exceptions import OpenAPIMediaTypeError
from openapi_core.schema.parameters.exceptions import OpenAPIParameterError
from openapi_core.schema.request_bodies.exceptions import (
OpenAPIRequestBodyError,
)
from openapi_core.schema.schemas.exceptions import OpenAPISchemaError
from openapi_core.validation.request.validators import RequestValidator
ERRORS_BODY = (
OpenAPIRequestBodyError, OpenAPIMediaTypeError, OpenAPISchemaError,
)
ERRORS_PARAMETERS = (
OpenAPIParameterError,
)
def validate_request(validator, request, failsafe=None):
if failsafe is None:
failsafe = ()
result = validator.validate(request)
try:
result.raise_for_errors()
except failsafe:
pass
return result
validate_parameters = partial(validate_request, failsafe=ERRORS_BODY)
validate_body = partial(validate_request, failsafe=ERRORS_PARAMETERS)
def spec_validate_parameters(spec, request, request_factory=None):
if request_factory is not None:
request = request_factory(request)
validator = RequestValidator(spec)
result = validate_parameters(validator, request)
return result.parameters
def spec_validate_body(spec, request, request_factory=None):
if request_factory is not None:
request = request_factory(request)
validator = RequestValidator(spec)
result = validate_body(validator, request)
return result.body

View file

@ -0,0 +1,23 @@
"""OpenAPI core validation response shortcuts module"""
from openapi_core.validation.response.validators import ResponseValidator
def validate_response(validator, request, response):
result = validator.validate(request, response)
result.raise_for_errors()
return result
def spec_validate_data(
spec, request, response,
request_factory=None,
response_factory=None):
if request_factory is not None:
request = request_factory(request)
if response_factory is not None:
response = response_factory(response)
validator = ResponseValidator(spec)
result = validate_response(validator, request, response)
return result.data

View file

@ -1,219 +0,0 @@
import mock
import pytest
from openapi_core.shortcuts import (
validate_parameters, validate_body, validate_data,
)
class ResultMock(object):
def __init__(
self, body=None, parameters=None, data=None, error_to_raise=None):
self.body = body
self.parameters = parameters
self.data = data
self.error_to_raise = error_to_raise
def raise_for_errors(self):
if self.error_to_raise is not None:
raise self.error_to_raise
if self.parameters is not None:
return self.parameters
if self.data is not None:
return self.data
class FactoryClassMock(object):
_instances = {}
def __new__(cls, obj):
if obj not in cls._instances:
cls._instances[obj] = object.__new__(cls)
return cls._instances[obj]
def __init__(self, obj):
self.obj = obj
class TestValidateParameters(object):
@mock.patch('openapi_core.shortcuts.RequestValidator.validate')
def test_no_request_factory(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
parameters = mock.sentinel.parameters
mock_validate.return_value = ResultMock(parameters=parameters)
result = validate_parameters(spec, request)
assert result == parameters
mock_validate.aasert_called_once_with(request)
@mock.patch('openapi_core.shortcuts.RequestValidator.validate')
def test_no_request_factory_error(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
mock_validate.return_value = ResultMock(error_to_raise=ValueError)
with pytest.raises(ValueError):
validate_parameters(spec, request)
mock_validate.aasert_called_once_with(request)
@mock.patch('openapi_core.shortcuts.RequestValidator.validate')
def test_request_factory(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
parameters = mock.sentinel.parameters
mock_validate.return_value = ResultMock(parameters=parameters)
request_factory = FactoryClassMock
result = validate_parameters(spec, request, request_factory)
assert result == parameters
mock_validate.assert_called_once_with(
FactoryClassMock(request),
)
@mock.patch('openapi_core.shortcuts.RequestValidator.validate')
def test_request_factory_error(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
mock_validate.return_value = ResultMock(error_to_raise=ValueError)
request_factory = FactoryClassMock
with pytest.raises(ValueError):
validate_parameters(spec, request, request_factory)
mock_validate.assert_called_once_with(
FactoryClassMock(request),
)
class TestValidateBody(object):
@mock.patch('openapi_core.shortcuts.RequestValidator.validate')
def test_no_request_factory(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
body = mock.sentinel.body
mock_validate.return_value = ResultMock(body=body)
result = validate_body(spec, request)
assert result == body
mock_validate.aasert_called_once_with(request)
@mock.patch('openapi_core.shortcuts.RequestValidator.validate')
def test_no_request_factory_error(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
mock_validate.return_value = ResultMock(error_to_raise=ValueError)
with pytest.raises(ValueError):
validate_body(spec, request)
mock_validate.aasert_called_once_with(request)
@mock.patch('openapi_core.shortcuts.RequestValidator.validate')
def test_request_factory(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
body = mock.sentinel.body
mock_validate.return_value = ResultMock(body=body)
request_factory = FactoryClassMock
result = validate_body(spec, request, request_factory)
assert result == body
mock_validate.assert_called_once_with(
FactoryClassMock(request),
)
@mock.patch('openapi_core.shortcuts.RequestValidator.validate')
def test_request_factory_error(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
mock_validate.return_value = ResultMock(error_to_raise=ValueError)
request_factory = FactoryClassMock
with pytest.raises(ValueError):
validate_body(spec, request, request_factory)
mock_validate.assert_called_once_with(
FactoryClassMock(request),
)
class TestvalidateData(object):
@mock.patch('openapi_core.shortcuts.ResponseValidator.validate')
def test_no_factories(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
response = mock.sentinel.response
data = mock.sentinel.data
mock_validate.return_value = ResultMock(data=data)
result = validate_data(spec, request, response)
assert result == data
mock_validate.aasert_called_once_with(request, response)
@mock.patch('openapi_core.shortcuts.ResponseValidator.validate')
def test_no_factories_error(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
response = mock.sentinel.response
mock_validate.return_value = ResultMock(error_to_raise=ValueError)
with pytest.raises(ValueError):
validate_data(spec, request, response)
mock_validate.aasert_called_once_with(request, response)
@mock.patch('openapi_core.shortcuts.ResponseValidator.validate')
def test_factories(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
response = mock.sentinel.response
data = mock.sentinel.data
mock_validate.return_value = ResultMock(data=data)
request_factory = FactoryClassMock
response_factory = FactoryClassMock
result = validate_data(
spec, request, response,
request_factory, response_factory,
)
assert result == data
mock_validate.assert_called_once_with(
FactoryClassMock(request),
FactoryClassMock(response),
)
@mock.patch('openapi_core.shortcuts.ResponseValidator.validate')
def test_factories_error(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
response = mock.sentinel.response
mock_validate.return_value = ResultMock(error_to_raise=ValueError)
request_factory = FactoryClassMock
response_factory = FactoryClassMock
with pytest.raises(ValueError):
validate_data(
spec, request, response,
request_factory, response_factory,
)
mock_validate.assert_called_once_with(
FactoryClassMock(request),
FactoryClassMock(response),
)

View file

@ -0,0 +1,135 @@
import mock
import pytest
from openapi_core.testing.datatypes import ResultMock
from openapi_core.testing.factories import FactoryClassMock
from openapi_core.validation.request.shortcuts import (
spec_validate_parameters, spec_validate_body,
)
class TestSpecValidateParameters(object):
@mock.patch(
'openapi_core.validation.request.shortcuts.RequestValidator.validate'
)
def test_no_request_factory(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
parameters = mock.sentinel.parameters
mock_validate.return_value = ResultMock(parameters=parameters)
result = spec_validate_parameters(spec, request)
assert result == parameters
mock_validate.aasert_called_once_with(request)
@mock.patch(
'openapi_core.validation.request.shortcuts.RequestValidator.validate'
)
def test_no_request_factory_error(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
mock_validate.return_value = ResultMock(error_to_raise=ValueError)
with pytest.raises(ValueError):
spec_validate_parameters(spec, request)
mock_validate.aasert_called_once_with(request)
@mock.patch(
'openapi_core.validation.request.shortcuts.RequestValidator.validate'
)
def test_request_factory(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
parameters = mock.sentinel.parameters
mock_validate.return_value = ResultMock(parameters=parameters)
request_factory = FactoryClassMock
result = spec_validate_parameters(spec, request, request_factory)
assert result == parameters
mock_validate.assert_called_once_with(
FactoryClassMock(request),
)
@mock.patch(
'openapi_core.validation.request.shortcuts.RequestValidator.validate'
)
def test_request_factory_error(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
mock_validate.return_value = ResultMock(error_to_raise=ValueError)
request_factory = FactoryClassMock
with pytest.raises(ValueError):
spec_validate_parameters(spec, request, request_factory)
mock_validate.assert_called_once_with(
FactoryClassMock(request),
)
class TestSpecValidateBody(object):
@mock.patch(
'openapi_core.validation.request.shortcuts.RequestValidator.validate'
)
def test_no_request_factory(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
body = mock.sentinel.body
mock_validate.return_value = ResultMock(body=body)
result = spec_validate_body(spec, request)
assert result == body
mock_validate.aasert_called_once_with(request)
@mock.patch(
'openapi_core.validation.request.shortcuts.RequestValidator.validate'
)
def test_no_request_factory_error(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
mock_validate.return_value = ResultMock(error_to_raise=ValueError)
with pytest.raises(ValueError):
spec_validate_body(spec, request)
mock_validate.aasert_called_once_with(request)
@mock.patch(
'openapi_core.validation.request.shortcuts.RequestValidator.validate'
)
def test_request_factory(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
body = mock.sentinel.body
mock_validate.return_value = ResultMock(body=body)
request_factory = FactoryClassMock
result = spec_validate_body(spec, request, request_factory)
assert result == body
mock_validate.assert_called_once_with(
FactoryClassMock(request),
)
@mock.patch(
'openapi_core.validation.request.shortcuts.RequestValidator.validate'
)
def test_request_factory_error(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
mock_validate.return_value = ResultMock(error_to_raise=ValueError)
request_factory = FactoryClassMock
with pytest.raises(ValueError):
spec_validate_body(spec, request, request_factory)
mock_validate.assert_called_once_with(
FactoryClassMock(request),
)

View file

@ -0,0 +1,84 @@
import mock
import pytest
from openapi_core.testing.datatypes import ResultMock
from openapi_core.testing.factories import FactoryClassMock
from openapi_core.validation.response.shortcuts import spec_validate_data
class TestSpecValidateData(object):
@mock.patch(
'openapi_core.validation.response.shortcuts.ResponseValidator.validate'
)
def test_no_factories(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
response = mock.sentinel.response
data = mock.sentinel.data
mock_validate.return_value = ResultMock(data=data)
result = spec_validate_data(spec, request, response)
assert result == data
mock_validate.aasert_called_once_with(request, response)
@mock.patch(
'openapi_core.validation.response.shortcuts.ResponseValidator.validate'
)
def test_no_factories_error(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
response = mock.sentinel.response
mock_validate.return_value = ResultMock(error_to_raise=ValueError)
with pytest.raises(ValueError):
spec_validate_data(spec, request, response)
mock_validate.aasert_called_once_with(request, response)
@mock.patch(
'openapi_core.validation.response.shortcuts.ResponseValidator.validate'
)
def test_factories(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
response = mock.sentinel.response
data = mock.sentinel.data
mock_validate.return_value = ResultMock(data=data)
request_factory = FactoryClassMock
response_factory = FactoryClassMock
result = spec_validate_data(
spec, request, response,
request_factory, response_factory,
)
assert result == data
mock_validate.assert_called_once_with(
FactoryClassMock(request),
FactoryClassMock(response),
)
@mock.patch(
'openapi_core.validation.response.shortcuts.ResponseValidator.validate'
)
def test_factories_error(self, mock_validate):
spec = mock.sentinel.spec
request = mock.sentinel.request
response = mock.sentinel.response
mock_validate.return_value = ResultMock(error_to_raise=ValueError)
request_factory = FactoryClassMock
response_factory = FactoryClassMock
with pytest.raises(ValueError):
spec_validate_data(
spec, request, response,
request_factory, response_factory,
)
mock_validate.assert_called_once_with(
FactoryClassMock(request),
FactoryClassMock(response),
)