Skip to content

Specification validation as part of shortcuts #686

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions docs/customizations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@ Customizations
Specification validation
------------------------

By default, the provided specification is validated on ``Spec`` object creation time.
By default, the specified specification is also validated.

If you know you have a valid specification already, disabling the validator can improve the performance.

.. code-block:: python
:emphasize-lines: 5
:emphasize-lines: 4

from openapi_core import Spec

spec = Spec.from_dict(
spec_dict,
validator=None,
validate_request(
request,
spec=spec,
spec_validator_cls=None,
)

Media type deserializers
Expand Down
8 changes: 8 additions & 0 deletions openapi_core/shortcuts.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ def unmarshal_apicall_request(
if not issubclass(cls, RequestUnmarshaller):
raise TypeError("'cls' argument is not type of RequestUnmarshaller")
v = cls(spec, base_url=base_url, **unmarshaller_kwargs)
v.check_spec(spec)
result = v.unmarshal(request)
result.raise_for_errors()
return result
Expand All @@ -134,6 +135,7 @@ def unmarshal_webhook_request(
"'cls' argument is not type of WebhookRequestUnmarshaller"
)
v = cls(spec, base_url=base_url, **unmarshaller_kwargs)
v.check_spec(spec)
result = v.unmarshal(request)
result.raise_for_errors()
return result
Expand Down Expand Up @@ -198,6 +200,7 @@ def unmarshal_apicall_response(
if not issubclass(cls, ResponseUnmarshaller):
raise TypeError("'cls' argument is not type of ResponseUnmarshaller")
v = cls(spec, base_url=base_url, **unmarshaller_kwargs)
v.check_spec(spec)
result = v.unmarshal(request, response)
result.raise_for_errors()
return result
Expand Down Expand Up @@ -227,6 +230,7 @@ def unmarshal_webhook_response(
"'cls' argument is not type of WebhookResponseUnmarshaller"
)
v = cls(spec, base_url=base_url, **unmarshaller_kwargs)
v.check_spec(spec)
result = v.unmarshal(request, response)
result.raise_for_errors()
return result
Expand Down Expand Up @@ -378,6 +382,7 @@ def validate_apicall_request(
if not issubclass(cls, RequestValidator):
raise TypeError("'cls' argument is not type of RequestValidator")
v = cls(spec, base_url=base_url, **validator_kwargs)
v.check_spec(spec)
return v.validate(request)


Expand All @@ -402,6 +407,7 @@ def validate_webhook_request(
"'cls' argument is not type of WebhookRequestValidator"
)
v = cls(spec, base_url=base_url, **validator_kwargs)
v.check_spec(spec)
return v.validate(request)


Expand All @@ -425,6 +431,7 @@ def validate_apicall_response(
if not issubclass(cls, ResponseValidator):
raise TypeError("'cls' argument is not type of ResponseValidator")
v = cls(spec, base_url=base_url, **validator_kwargs)
v.check_spec(spec)
return v.validate(request, response)


Expand Down Expand Up @@ -452,4 +459,5 @@ def validate_webhook_response(
"'cls' argument is not type of WebhookResponseValidator"
)
v = cls(spec, base_url=base_url, **validator_kwargs)
v.check_spec(spec)
return v.validate(request, response)
6 changes: 6 additions & 0 deletions openapi_core/unmarshalling/request/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ class RequestUnmarshaller(Protocol):
def __init__(self, spec: SchemaPath, base_url: Optional[str] = None):
...

def check_spec(self, spec: SchemaPath) -> None:
...

def unmarshal(
self,
request: Request,
Expand All @@ -27,6 +30,9 @@ class WebhookRequestUnmarshaller(Protocol):
def __init__(self, spec: SchemaPath, base_url: Optional[str] = None):
...

def check_spec(self, spec: SchemaPath) -> None:
...

def unmarshal(
self,
request: WebhookRequest,
Expand Down
4 changes: 4 additions & 0 deletions openapi_core/unmarshalling/request/unmarshallers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Optional

from jsonschema_path import SchemaPath
from openapi_spec_validator.validation.types import SpecValidatorType

from openapi_core.casting.schemas import schema_casters_factory
from openapi_core.casting.schemas.factories import SchemaCastersFactory
Expand Down Expand Up @@ -88,6 +89,7 @@ def __init__(
style_deserializers_factory: StyleDeserializersFactory = style_deserializers_factory,
media_type_deserializers_factory: MediaTypeDeserializersFactory = media_type_deserializers_factory,
schema_validators_factory: Optional[SchemaValidatorsFactory] = None,
spec_validator_cls: Optional[SpecValidatorType] = None,
format_validators: Optional[FormatValidatorsDict] = None,
extra_format_validators: Optional[FormatValidatorsDict] = None,
extra_media_type_deserializers: Optional[
Expand All @@ -108,6 +110,7 @@ def __init__(
style_deserializers_factory=style_deserializers_factory,
media_type_deserializers_factory=media_type_deserializers_factory,
schema_validators_factory=schema_validators_factory,
spec_validator_cls=spec_validator_cls,
format_validators=format_validators,
extra_format_validators=extra_format_validators,
extra_media_type_deserializers=extra_media_type_deserializers,
Expand All @@ -123,6 +126,7 @@ def __init__(
style_deserializers_factory=style_deserializers_factory,
media_type_deserializers_factory=media_type_deserializers_factory,
schema_validators_factory=schema_validators_factory,
spec_validator_cls=spec_validator_cls,
format_validators=format_validators,
extra_format_validators=extra_format_validators,
extra_media_type_deserializers=extra_media_type_deserializers,
Expand Down
6 changes: 6 additions & 0 deletions openapi_core/unmarshalling/response/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ class ResponseUnmarshaller(Protocol):
def __init__(self, spec: SchemaPath, base_url: Optional[str] = None):
...

def check_spec(self, spec: SchemaPath) -> None:
...

def unmarshal(
self,
request: Request,
Expand All @@ -33,6 +36,9 @@ class WebhookResponseUnmarshaller(Protocol):
def __init__(self, spec: SchemaPath, base_url: Optional[str] = None):
...

def check_spec(self, spec: SchemaPath) -> None:
...

def unmarshal(
self,
request: WebhookRequest,
Expand Down
3 changes: 3 additions & 0 deletions openapi_core/unmarshalling/unmarshallers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import Tuple

from jsonschema_path import SchemaPath
from openapi_spec_validator.validation.types import SpecValidatorType

from openapi_core.casting.schemas import schema_casters_factory
from openapi_core.casting.schemas.factories import SchemaCastersFactory
Expand Down Expand Up @@ -42,6 +43,7 @@ def __init__(
style_deserializers_factory: StyleDeserializersFactory = style_deserializers_factory,
media_type_deserializers_factory: MediaTypeDeserializersFactory = media_type_deserializers_factory,
schema_validators_factory: Optional[SchemaValidatorsFactory] = None,
spec_validator_cls: Optional[SpecValidatorType] = None,
format_validators: Optional[FormatValidatorsDict] = None,
extra_format_validators: Optional[FormatValidatorsDict] = None,
extra_media_type_deserializers: Optional[
Expand All @@ -64,6 +66,7 @@ def __init__(
style_deserializers_factory=style_deserializers_factory,
media_type_deserializers_factory=media_type_deserializers_factory,
schema_validators_factory=schema_validators_factory,
spec_validator_cls=spec_validator_cls,
format_validators=format_validators,
extra_format_validators=extra_format_validators,
extra_media_type_deserializers=extra_media_type_deserializers,
Expand Down
6 changes: 6 additions & 0 deletions openapi_core/validation/request/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ class RequestValidator(Protocol):
def __init__(self, spec: SchemaPath, base_url: Optional[str] = None):
...

def check_spec(self, spec: SchemaPath) -> None:
...

def iter_errors(
self,
request: Request,
Expand All @@ -33,6 +36,9 @@ class WebhookRequestValidator(Protocol):
def __init__(self, spec: SchemaPath, base_url: Optional[str] = None):
...

def check_spec(self, spec: SchemaPath) -> None:
...

def iter_errors(
self,
request: WebhookRequest,
Expand Down
17 changes: 17 additions & 0 deletions openapi_core/validation/request/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
from typing import Optional

from jsonschema_path import SchemaPath
from openapi_spec_validator import OpenAPIV30SpecValidator
from openapi_spec_validator import OpenAPIV31SpecValidator
from openapi_spec_validator.validation.types import SpecValidatorType

from openapi_core.casting.schemas import schema_casters_factory
from openapi_core.casting.schemas.factories import SchemaCastersFactory
Expand Down Expand Up @@ -70,6 +73,7 @@ def __init__(
style_deserializers_factory: StyleDeserializersFactory = style_deserializers_factory,
media_type_deserializers_factory: MediaTypeDeserializersFactory = media_type_deserializers_factory,
schema_validators_factory: Optional[SchemaValidatorsFactory] = None,
spec_validator_cls: Optional[SpecValidatorType] = None,
format_validators: Optional[FormatValidatorsDict] = None,
extra_format_validators: Optional[FormatValidatorsDict] = None,
extra_media_type_deserializers: Optional[
Expand All @@ -84,6 +88,7 @@ def __init__(
style_deserializers_factory=style_deserializers_factory,
media_type_deserializers_factory=media_type_deserializers_factory,
schema_validators_factory=schema_validators_factory,
spec_validator_cls=spec_validator_cls,
format_validators=format_validators,
extra_format_validators=extra_format_validators,
extra_media_type_deserializers=extra_media_type_deserializers,
Expand Down Expand Up @@ -387,53 +392,65 @@ def iter_errors(self, request: WebhookRequest) -> Iterator[Exception]:


class V30RequestBodyValidator(APICallRequestBodyValidator):
spec_validator_cls = OpenAPIV30SpecValidator
schema_validators_factory = oas30_write_schema_validators_factory


class V30RequestParametersValidator(APICallRequestParametersValidator):
spec_validator_cls = OpenAPIV30SpecValidator
schema_validators_factory = oas30_write_schema_validators_factory


class V30RequestSecurityValidator(APICallRequestSecurityValidator):
spec_validator_cls = OpenAPIV30SpecValidator
schema_validators_factory = oas30_write_schema_validators_factory


class V30RequestValidator(APICallRequestValidator):
spec_validator_cls = OpenAPIV30SpecValidator
schema_validators_factory = oas30_write_schema_validators_factory


class V31RequestBodyValidator(APICallRequestBodyValidator):
spec_validator_cls = OpenAPIV31SpecValidator
schema_validators_factory = oas31_schema_validators_factory


class V31RequestParametersValidator(APICallRequestParametersValidator):
spec_validator_cls = OpenAPIV31SpecValidator
schema_validators_factory = oas31_schema_validators_factory


class V31RequestSecurityValidator(APICallRequestSecurityValidator):
spec_validator_cls = OpenAPIV31SpecValidator
schema_validators_factory = oas31_schema_validators_factory


class V31RequestValidator(APICallRequestValidator):
spec_validator_cls = OpenAPIV31SpecValidator
schema_validators_factory = oas31_schema_validators_factory
path_finder_cls = WebhookPathFinder


class V31WebhookRequestBodyValidator(WebhookRequestBodyValidator):
spec_validator_cls = OpenAPIV31SpecValidator
schema_validators_factory = oas31_schema_validators_factory
path_finder_cls = WebhookPathFinder


class V31WebhookRequestParametersValidator(WebhookRequestParametersValidator):
spec_validator_cls = OpenAPIV31SpecValidator
schema_validators_factory = oas31_schema_validators_factory
path_finder_cls = WebhookPathFinder


class V31WebhookRequestSecurityValidator(WebhookRequestSecurityValidator):
spec_validator_cls = OpenAPIV31SpecValidator
schema_validators_factory = oas31_schema_validators_factory
path_finder_cls = WebhookPathFinder


class V31WebhookRequestValidator(WebhookRequestValidator):
spec_validator_cls = OpenAPIV31SpecValidator
schema_validators_factory = oas31_schema_validators_factory
path_finder_cls = WebhookPathFinder
6 changes: 6 additions & 0 deletions openapi_core/validation/response/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ class ResponseValidator(Protocol):
def __init__(self, spec: SchemaPath, base_url: Optional[str] = None):
...

def check_spec(self, spec: SchemaPath) -> None:
...

def iter_errors(
self,
request: Request,
Expand All @@ -36,6 +39,9 @@ class WebhookResponseValidator(Protocol):
def __init__(self, spec: SchemaPath, base_url: Optional[str] = None):
...

def check_spec(self, spec: SchemaPath) -> None:
...

def iter_errors(
self,
request: WebhookRequest,
Expand Down
11 changes: 11 additions & 0 deletions openapi_core/validation/response/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from typing import Mapping

from jsonschema_path import SchemaPath
from openapi_spec_validator import OpenAPIV30SpecValidator
from openapi_spec_validator import OpenAPIV31SpecValidator

from openapi_core.exceptions import OpenAPIError
from openapi_core.protocols import Request
Expand Down Expand Up @@ -330,36 +332,45 @@ def iter_errors(


class V30ResponseDataValidator(APICallResponseDataValidator):
spec_validator_cls = OpenAPIV30SpecValidator
schema_validators_factory = oas30_read_schema_validators_factory


class V30ResponseHeadersValidator(APICallResponseHeadersValidator):
spec_validator_cls = OpenAPIV30SpecValidator
schema_validators_factory = oas30_read_schema_validators_factory


class V30ResponseValidator(APICallResponseValidator):
spec_validator_cls = OpenAPIV30SpecValidator
schema_validators_factory = oas30_read_schema_validators_factory


class V31ResponseDataValidator(APICallResponseDataValidator):
spec_validator_cls = OpenAPIV31SpecValidator
schema_validators_factory = oas31_schema_validators_factory


class V31ResponseHeadersValidator(APICallResponseHeadersValidator):
spec_validator_cls = OpenAPIV31SpecValidator
schema_validators_factory = oas31_schema_validators_factory


class V31ResponseValidator(APICallResponseValidator):
spec_validator_cls = OpenAPIV31SpecValidator
schema_validators_factory = oas31_schema_validators_factory


class V31WebhookResponseDataValidator(WebhookResponseDataValidator):
spec_validator_cls = OpenAPIV31SpecValidator
schema_validators_factory = oas31_schema_validators_factory


class V31WebhookResponseHeadersValidator(WebhookResponseHeadersValidator):
spec_validator_cls = OpenAPIV31SpecValidator
schema_validators_factory = oas31_schema_validators_factory


class V31WebhookResponseValidator(WebhookResponseValidator):
spec_validator_cls = OpenAPIV31SpecValidator
schema_validators_factory = oas31_schema_validators_factory
Loading