diff --git a/README.rst b/README.rst index 226e551f..c1f3b881 100644 --- a/README.rst +++ b/README.rst @@ -19,7 +19,8 @@ About ##### Openapi-core is a Python library that adds client-side and server-side support -for the `OpenAPI Specification v3 `__. +for the `OpenAPI v3.0 `__ +and `OpenAPI v3.1 `__ specification. Key features ************ @@ -57,7 +58,7 @@ Alternatively you can download the code and install from the repository: Usage ##### -Firstly create your specification object: +Firstly create your specification object. By default, OpenAPI spec version is detected: .. code-block:: python @@ -132,6 +133,19 @@ and unmarshal response data from validation result Response object should implement OpenAPI Response protocol (See `Integrations `__). +In order to explicitly validate a: + +* OpenAPI 3.0 spec, import ``openapi_v30_request_validator`` or ``openapi_v30_response_validator`` +* OpenAPI 3.1 spec, import ``openapi_v31_request_validator`` or ``openapi_v31_response_validator`` + +.. code:: python + + from openapi_core.validation.response import openapi_v31_response_validator + + result = openapi_v31_response_validator.validate(spec, request, response) + +You can also explicitly import ``openapi_v3_request_validator`` or ``openapi_v3_response_validator`` which is a shortcut to the latest v3 release. + Related projects ################ * `bottle-openapi-3 `__ diff --git a/docs/index.rst b/docs/index.rst index 33b5f48c..8090a33b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -7,7 +7,8 @@ Welcome to openapi-core's documentation! ======================================== Openapi-core is a Python library that adds client-side and server-side support -for the `OpenAPI Specification v3 `__. +for the `OpenAPI v3.0 `__ +and `OpenAPI v3.1 `__ specification. Key features ------------ diff --git a/docs/usage.rst b/docs/usage.rst index aa30e485..94ddbda3 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -1,7 +1,7 @@ Usage ===== -Firstly create your specification: object +Firstly create your specification object. By default, OpenAPI spec version is detected: .. code-block:: python @@ -46,7 +46,7 @@ and unmarshal request data from validation result # get security data validated_security = result.security -Request object should be instance of OpenAPIRequest class (See :doc:`integrations`). +Request object should implement OpenAPI Request protocol (See :doc:`integrations`). Response -------- @@ -75,7 +75,7 @@ and unmarshal response data from validation result # get data validated_data = result.data -Response object should be instance of OpenAPIResponse class (See :doc:`integrations`). +Response object should implement OpenAPI Response protocol (See :doc:`integrations`). Security -------- diff --git a/openapi_core/__init__.py b/openapi_core/__init__.py index fa1ace79..9da86a38 100644 --- a/openapi_core/__init__.py +++ b/openapi_core/__init__.py @@ -1,16 +1,14 @@ """OpenAPI core module""" from openapi_core.spec import Spec -from openapi_core.validation.request.validators import RequestBodyValidator -from openapi_core.validation.request.validators import ( - RequestParametersValidator, +from openapi_core.validation.request import openapi_request_body_validator +from openapi_core.validation.request import ( + openapi_request_parameters_validator, ) -from openapi_core.validation.request.validators import RequestSecurityValidator -from openapi_core.validation.request.validators import RequestValidator -from openapi_core.validation.response.validators import ResponseDataValidator -from openapi_core.validation.response.validators import ( - ResponseHeadersValidator, -) -from openapi_core.validation.response.validators import ResponseValidator +from openapi_core.validation.request import openapi_request_security_validator +from openapi_core.validation.request import openapi_request_validator +from openapi_core.validation.response import openapi_response_data_validator +from openapi_core.validation.response import openapi_response_headers_validator +from openapi_core.validation.response import openapi_response_validator from openapi_core.validation.shortcuts import validate_request from openapi_core.validation.shortcuts import validate_response @@ -24,11 +22,11 @@ "Spec", "validate_request", "validate_response", - "RequestValidator", - "ResponseValidator", - "RequestBodyValidator", - "RequestParametersValidator", - "RequestSecurityValidator", - "ResponseDataValidator", - "ResponseHeadersValidator", + "openapi_request_body_validator", + "openapi_request_parameters_validator", + "openapi_request_security_validator", + "openapi_request_validator", + "openapi_response_data_validator", + "openapi_response_headers_validator", + "openapi_response_validator", ] diff --git a/openapi_core/contrib/flask/decorators.py b/openapi_core/contrib/flask/decorators.py index b30f41d8..9e2eb182 100644 --- a/openapi_core/contrib/flask/decorators.py +++ b/openapi_core/contrib/flask/decorators.py @@ -16,10 +16,10 @@ from openapi_core.validation.processors import OpenAPIProcessor from openapi_core.validation.request import openapi_request_validator from openapi_core.validation.request.datatypes import RequestValidationResult -from openapi_core.validation.request.validators import RequestValidator +from openapi_core.validation.request.protocols import RequestValidator from openapi_core.validation.response import openapi_response_validator from openapi_core.validation.response.datatypes import ResponseValidationResult -from openapi_core.validation.response.validators import ResponseValidator +from openapi_core.validation.response.protocols import ResponseValidator class FlaskOpenAPIViewDecorator(OpenAPIProcessor): diff --git a/openapi_core/unmarshalling/schemas/__init__.py b/openapi_core/unmarshalling/schemas/__init__.py index 0591dee2..0a3e2cf1 100644 --- a/openapi_core/unmarshalling/schemas/__init__.py +++ b/openapi_core/unmarshalling/schemas/__init__.py @@ -1,4 +1,5 @@ from openapi_schema_validator import OAS30Validator +from openapi_schema_validator import OAS31Validator from openapi_core.unmarshalling.schemas.enums import UnmarshalContext from openapi_core.unmarshalling.schemas.factories import ( @@ -8,6 +9,9 @@ __all__ = [ "oas30_request_schema_unmarshallers_factory", "oas30_response_schema_unmarshallers_factory", + "oas31_request_schema_unmarshallers_factory", + "oas31_response_schema_unmarshallers_factory", + "oas31_schema_unmarshallers_factory", ] oas30_request_schema_unmarshallers_factory = SchemaUnmarshallersFactory( @@ -19,3 +23,13 @@ OAS30Validator, context=UnmarshalContext.RESPONSE, ) + +oas31_schema_unmarshallers_factory = SchemaUnmarshallersFactory( + OAS31Validator, +) + +# alias to v31 version (request/response are the same bcs no context needed) +oas31_request_schema_unmarshallers_factory = oas31_schema_unmarshallers_factory +oas31_response_schema_unmarshallers_factory = ( + oas31_schema_unmarshallers_factory +) diff --git a/openapi_core/validation/exceptions.py b/openapi_core/validation/exceptions.py index 71b2bb87..5250ecb1 100644 --- a/openapi_core/validation/exceptions.py +++ b/openapi_core/validation/exceptions.py @@ -4,6 +4,10 @@ from openapi_core.exceptions import OpenAPIError +class ValidatorDetectError(OpenAPIError): + pass + + class ValidationError(OpenAPIError): pass diff --git a/openapi_core/validation/processors.py b/openapi_core/validation/processors.py index 13d393bc..c2d9356d 100644 --- a/openapi_core/validation/processors.py +++ b/openapi_core/validation/processors.py @@ -2,10 +2,10 @@ from openapi_core.spec import Spec from openapi_core.validation.request.datatypes import RequestValidationResult from openapi_core.validation.request.protocols import Request -from openapi_core.validation.request.validators import RequestValidator +from openapi_core.validation.request.protocols import RequestValidator from openapi_core.validation.response.datatypes import ResponseValidationResult from openapi_core.validation.response.protocols import Response -from openapi_core.validation.response.validators import ResponseValidator +from openapi_core.validation.response.protocols import ResponseValidator class OpenAPIProcessor: diff --git a/openapi_core/validation/request/__init__.py b/openapi_core/validation/request/__init__.py index 7d088554..d4c57fc4 100644 --- a/openapi_core/validation/request/__init__.py +++ b/openapi_core/validation/request/__init__.py @@ -2,6 +2,10 @@ from openapi_core.unmarshalling.schemas import ( oas30_request_schema_unmarshallers_factory, ) +from openapi_core.unmarshalling.schemas import ( + oas31_schema_unmarshallers_factory, +) +from openapi_core.validation.request.proxies import DetectRequestValidatorProxy from openapi_core.validation.request.validators import RequestBodyValidator from openapi_core.validation.request.validators import ( RequestParametersValidator, @@ -14,6 +18,14 @@ "openapi_v30_request_parameters_validator", "openapi_v30_request_security_validator", "openapi_v30_request_validator", + "openapi_v31_request_body_validator", + "openapi_v31_request_parameters_validator", + "openapi_v31_request_security_validator", + "openapi_v31_request_validator", + "openapi_v3_request_body_validator", + "openapi_v3_request_parameters_validator", + "openapi_v3_request_security_validator", + "openapi_v3_request_validator", "openapi_request_body_validator", "openapi_request_parameters_validator", "openapi_request_security_validator", @@ -33,8 +45,49 @@ schema_unmarshallers_factory=oas30_request_schema_unmarshallers_factory, ) +openapi_v31_request_body_validator = RequestBodyValidator( + schema_unmarshallers_factory=oas31_schema_unmarshallers_factory, +) +openapi_v31_request_parameters_validator = RequestParametersValidator( + schema_unmarshallers_factory=oas31_schema_unmarshallers_factory, +) +openapi_v31_request_security_validator = RequestSecurityValidator( + schema_unmarshallers_factory=oas31_schema_unmarshallers_factory, +) +openapi_v31_request_validator = RequestValidator( + schema_unmarshallers_factory=oas31_schema_unmarshallers_factory, +) + # alias to the latest v3 version -openapi_request_body_validator = openapi_v30_request_body_validator -openapi_request_parameters_validator = openapi_v30_request_parameters_validator -openapi_request_security_validator = openapi_v30_request_security_validator -openapi_request_validator = openapi_v30_request_validator +openapi_v3_request_body_validator = openapi_v31_request_body_validator +openapi_v3_request_parameters_validator = ( + openapi_v31_request_parameters_validator +) +openapi_v3_request_security_validator = openapi_v31_request_security_validator +openapi_v3_request_validator = openapi_v31_request_validator + +# detect version spec +openapi_request_body_validator = DetectRequestValidatorProxy( + { + ("openapi", "3.0"): openapi_v30_request_body_validator, + ("openapi", "3.1"): openapi_v31_request_body_validator, + }, +) +openapi_request_parameters_validator = DetectRequestValidatorProxy( + { + ("openapi", "3.0"): openapi_v30_request_parameters_validator, + ("openapi", "3.1"): openapi_v31_request_parameters_validator, + }, +) +openapi_request_security_validator = DetectRequestValidatorProxy( + { + ("openapi", "3.0"): openapi_v30_request_security_validator, + ("openapi", "3.1"): openapi_v31_request_security_validator, + }, +) +openapi_request_validator = DetectRequestValidatorProxy( + { + ("openapi", "3.0"): openapi_v30_request_validator, + ("openapi", "3.1"): openapi_v31_request_validator, + }, +) diff --git a/openapi_core/validation/request/protocols.py b/openapi_core/validation/request/protocols.py index 1a880eb9..8a3ab254 100644 --- a/openapi_core/validation/request/protocols.py +++ b/openapi_core/validation/request/protocols.py @@ -13,7 +13,9 @@ from typing_extensions import Protocol from typing_extensions import runtime_checkable +from openapi_core.spec import Spec from openapi_core.validation.request.datatypes import RequestParameters +from openapi_core.validation.request.datatypes import RequestValidationResult @runtime_checkable @@ -85,3 +87,14 @@ class SupportsPathPattern(Protocol): @property def path_pattern(self) -> str: ... + + +@runtime_checkable +class RequestValidator(Protocol): + def validate( + self, + spec: Spec, + request: Request, + base_url: Optional[str] = None, + ) -> RequestValidationResult: + ... diff --git a/openapi_core/validation/request/proxies.py b/openapi_core/validation/request/proxies.py new file mode 100644 index 00000000..725853ac --- /dev/null +++ b/openapi_core/validation/request/proxies.py @@ -0,0 +1,57 @@ +"""OpenAPI spec validator validation proxies module.""" +from typing import Any +from typing import Hashable +from typing import Iterator +from typing import Mapping +from typing import Optional +from typing import Tuple + +from openapi_core.exceptions import OpenAPIError +from openapi_core.spec import Spec +from openapi_core.validation.exceptions import ValidatorDetectError +from openapi_core.validation.request.datatypes import RequestValidationResult +from openapi_core.validation.request.protocols import Request +from openapi_core.validation.request.validators import BaseRequestValidator + + +class DetectRequestValidatorProxy: + def __init__( + self, choices: Mapping[Tuple[str, str], BaseRequestValidator] + ): + self.choices = choices + + def detect(self, spec: Spec) -> BaseRequestValidator: + for (key, value), validator in self.choices.items(): + if key in spec and spec[key].startswith(value): + return validator + raise ValidatorDetectError("Spec schema version not detected") + + def validate( + self, + spec: Spec, + request: Request, + base_url: Optional[str] = None, + ) -> RequestValidationResult: + validator = self.detect(spec) + return validator.validate(spec, request, base_url=base_url) + + def is_valid( + self, + spec: Spec, + request: Request, + base_url: Optional[str] = None, + ) -> bool: + validator = self.detect(spec) + error = next( + validator.iter_errors(spec, request, base_url=base_url), None + ) + return error is None + + def iter_errors( + self, + spec: Spec, + request: Request, + base_url: Optional[str] = None, + ) -> Iterator[Exception]: + validator = self.detect(spec) + yield from validator.iter_errors(spec, request, base_url=base_url) diff --git a/openapi_core/validation/request/validators.py b/openapi_core/validation/request/validators.py index c0298fb2..ec703d5a 100644 --- a/openapi_core/validation/request/validators.py +++ b/openapi_core/validation/request/validators.py @@ -2,6 +2,7 @@ import warnings from typing import Any from typing import Dict +from typing import Iterator from typing import Optional from openapi_core.casting.schemas import schema_casters_factory @@ -20,6 +21,7 @@ from openapi_core.deserializing.parameters.factories import ( ParameterDeserializersFactory, ) +from openapi_core.exceptions import OpenAPIError from openapi_core.security import security_provider_factory from openapi_core.security.exceptions import SecurityError from openapi_core.security.factories import SecurityProviderFactory @@ -64,6 +66,15 @@ def __init__( ) self.security_provider_factory = security_provider_factory + def iter_errors( + self, + spec: Spec, + request: Request, + base_url: Optional[str] = None, + ) -> Iterator[Exception]: + result = self.validate(spec, request, base_url=base_url) + yield from result.errors + def validate( self, spec: Spec, diff --git a/openapi_core/validation/response/__init__.py b/openapi_core/validation/response/__init__.py index bce2ee18..3bbc3001 100644 --- a/openapi_core/validation/response/__init__.py +++ b/openapi_core/validation/response/__init__.py @@ -2,6 +2,12 @@ from openapi_core.unmarshalling.schemas import ( oas30_response_schema_unmarshallers_factory, ) +from openapi_core.unmarshalling.schemas import ( + oas31_schema_unmarshallers_factory, +) +from openapi_core.validation.response.proxies import ( + DetectResponseValidatorProxy, +) from openapi_core.validation.response.validators import ResponseDataValidator from openapi_core.validation.response.validators import ( ResponseHeadersValidator, @@ -12,6 +18,12 @@ "openapi_v30_response_data_validator", "openapi_v30_response_headers_validator", "openapi_v30_response_validator", + "openapi_v31_response_data_validator", + "openapi_v31_response_headers_validator", + "openapi_v31_response_validator", + "openapi_v3_response_data_validator", + "openapi_v3_response_headers_validator", + "openapi_v3_response_validator", "openapi_response_data_validator", "openapi_response_headers_validator", "openapi_response_validator", @@ -27,7 +39,37 @@ schema_unmarshallers_factory=oas30_response_schema_unmarshallers_factory, ) +openapi_v31_response_data_validator = ResponseDataValidator( + schema_unmarshallers_factory=oas31_schema_unmarshallers_factory, +) +openapi_v31_response_headers_validator = ResponseHeadersValidator( + schema_unmarshallers_factory=oas31_schema_unmarshallers_factory, +) +openapi_v31_response_validator = ResponseValidator( + schema_unmarshallers_factory=oas31_schema_unmarshallers_factory, +) + # alias to the latest v3 version -openapi_response_data_validator = openapi_v30_response_data_validator -openapi_response_headers_validator = openapi_v30_response_headers_validator -openapi_response_validator = openapi_v30_response_validator +openapi_v3_response_data_validator = openapi_v31_response_data_validator +openapi_v3_response_headers_validator = openapi_v31_response_headers_validator +openapi_v3_response_validator = openapi_v31_response_validator + +# detect version spec +openapi_response_data_validator = DetectResponseValidatorProxy( + { + ("openapi", "3.0"): openapi_v30_response_data_validator, + ("openapi", "3.1"): openapi_v31_response_data_validator, + }, +) +openapi_response_headers_validator = DetectResponseValidatorProxy( + { + ("openapi", "3.0"): openapi_v30_response_headers_validator, + ("openapi", "3.1"): openapi_v31_response_headers_validator, + }, +) +openapi_response_validator = DetectResponseValidatorProxy( + { + ("openapi", "3.0"): openapi_v30_response_validator, + ("openapi", "3.1"): openapi_v31_response_validator, + }, +) diff --git a/openapi_core/validation/response/protocols.py b/openapi_core/validation/response/protocols.py index 2e67ecdb..7a66ea8f 100644 --- a/openapi_core/validation/response/protocols.py +++ b/openapi_core/validation/response/protocols.py @@ -1,5 +1,6 @@ """OpenAPI core validation response protocols module""" from typing import TYPE_CHECKING +from typing import Optional if TYPE_CHECKING: from typing_extensions import Protocol @@ -14,6 +15,10 @@ from werkzeug.datastructures import Headers +from openapi_core.spec import Spec +from openapi_core.validation.request.protocols import Request +from openapi_core.validation.response.datatypes import ResponseValidationResult + @runtime_checkable class Response(Protocol): @@ -45,3 +50,15 @@ def mimetype(self) -> str: @property def headers(self) -> Headers: ... + + +@runtime_checkable +class ResponseValidator(Protocol): + def validate( + self, + spec: Spec, + request: Request, + response: Response, + base_url: Optional[str] = None, + ) -> ResponseValidationResult: + ... diff --git a/openapi_core/validation/response/proxies.py b/openapi_core/validation/response/proxies.py new file mode 100644 index 00000000..750d0337 --- /dev/null +++ b/openapi_core/validation/response/proxies.py @@ -0,0 +1,64 @@ +"""OpenAPI spec validator validation proxies module.""" +from typing import Any +from typing import Hashable +from typing import Iterator +from typing import Mapping +from typing import Optional +from typing import Tuple + +from openapi_core.exceptions import OpenAPIError +from openapi_core.spec import Spec +from openapi_core.validation.exceptions import ValidatorDetectError +from openapi_core.validation.request.protocols import Request +from openapi_core.validation.response.datatypes import ResponseValidationResult +from openapi_core.validation.response.protocols import Response +from openapi_core.validation.response.validators import BaseResponseValidator + + +class DetectResponseValidatorProxy: + def __init__( + self, choices: Mapping[Tuple[str, str], BaseResponseValidator] + ): + self.choices = choices + + def detect(self, spec: Spec) -> BaseResponseValidator: + for (key, value), validator in self.choices.items(): + if key in spec and spec[key].startswith(value): + return validator + raise ValidatorDetectError("Spec schema version not detected") + + def validate( + self, + spec: Spec, + request: Request, + response: Response, + base_url: Optional[str] = None, + ) -> ResponseValidationResult: + validator = self.detect(spec) + return validator.validate(spec, request, response, base_url=base_url) + + def is_valid( + self, + spec: Spec, + request: Request, + response: Response, + base_url: Optional[str] = None, + ) -> bool: + validator = self.detect(spec) + error = next( + validator.iter_errors(spec, request, response, base_url=base_url), + None, + ) + return error is None + + def iter_errors( + self, + spec: Spec, + request: Request, + response: Response, + base_url: Optional[str] = None, + ) -> Iterator[Exception]: + validator = self.detect(spec) + yield from validator.iter_errors( + spec, request, response, base_url=base_url + ) diff --git a/openapi_core/validation/response/validators.py b/openapi_core/validation/response/validators.py index 0e735c82..9c884a06 100644 --- a/openapi_core/validation/response/validators.py +++ b/openapi_core/validation/response/validators.py @@ -2,6 +2,7 @@ import warnings from typing import Any from typing import Dict +from typing import Iterator from typing import List from typing import Optional @@ -30,6 +31,16 @@ class BaseResponseValidator(BaseValidator): + def iter_errors( + self, + spec: Spec, + request: Request, + response: Response, + base_url: Optional[str] = None, + ) -> Iterator[Exception]: + result = self.validate(spec, request, response, base_url=base_url) + yield from result.errors + def validate( self, spec: Spec, diff --git a/openapi_core/validation/shortcuts.py b/openapi_core/validation/shortcuts.py index 7eaed534..35840604 100644 --- a/openapi_core/validation/shortcuts.py +++ b/openapi_core/validation/shortcuts.py @@ -5,11 +5,11 @@ from openapi_core.validation.request import openapi_request_validator from openapi_core.validation.request.datatypes import RequestValidationResult from openapi_core.validation.request.protocols import Request -from openapi_core.validation.request.validators import RequestValidator +from openapi_core.validation.request.protocols import RequestValidator from openapi_core.validation.response import openapi_response_validator from openapi_core.validation.response.datatypes import ResponseValidationResult from openapi_core.validation.response.protocols import Response -from openapi_core.validation.response.validators import ResponseValidator +from openapi_core.validation.response.protocols import ResponseValidator def validate_request( diff --git a/tests/integration/data/v3.1/empty.yaml b/tests/integration/data/v3.1/empty.yaml new file mode 100644 index 00000000..7bd07431 --- /dev/null +++ b/tests/integration/data/v3.1/empty.yaml @@ -0,0 +1 @@ +openapi: "3.1.0" diff --git a/tests/integration/data/v3.1/links.yaml b/tests/integration/data/v3.1/links.yaml new file mode 100644 index 00000000..a35733fa --- /dev/null +++ b/tests/integration/data/v3.1/links.yaml @@ -0,0 +1,48 @@ +openapi: "3.1.0" +info: + title: Minimal valid OpenAPI specification + version: "0.1" +paths: + /linked/noParam: + get: + operationId: noParOp + responses: + default: + description: the linked result + /linked/withParam: + get: + operationId: paramOp + parameters: + - name: opParam + in: query + description: test + schema: + type: string + responses: + default: + description: the linked result + /status: + get: + responses: + default: + description: Return something + links: + noParamLink: + operationId: noParOp + /status/{resourceId}: + get: + parameters: + - name: resourceId + in: path + required: true + schema: + type: string + responses: + default: + description: Return something else + links: + paramLink: + operationId: paramOp + parameters: + opParam: $request.path.resourceId + requestBody: test \ No newline at end of file diff --git a/tests/integration/data/v3.1/minimal.yaml b/tests/integration/data/v3.1/minimal.yaml new file mode 100644 index 00000000..94fb971e --- /dev/null +++ b/tests/integration/data/v3.1/minimal.yaml @@ -0,0 +1,10 @@ +openapi: "3.1.0" +info: + title: Minimal valid OpenAPI specification + version: "0.1" +paths: + /status: + get: + responses: + default: + description: Return the API status. \ No newline at end of file diff --git a/tests/integration/data/v3.1/minimal_with_servers.yaml b/tests/integration/data/v3.1/minimal_with_servers.yaml new file mode 100644 index 00000000..d437c20f --- /dev/null +++ b/tests/integration/data/v3.1/minimal_with_servers.yaml @@ -0,0 +1,12 @@ +openapi: "3.1.0" +info: + title: Minimal valid OpenAPI specification with explicit 'servers' array + version: "0.1" +servers: + - url: / +paths: + /status: + get: + responses: + default: + description: Return the API status. \ No newline at end of file diff --git a/tests/integration/data/v3.1/path_param.yaml b/tests/integration/data/v3.1/path_param.yaml new file mode 100644 index 00000000..72c9b676 --- /dev/null +++ b/tests/integration/data/v3.1/path_param.yaml @@ -0,0 +1,17 @@ +openapi: "3.1.0" +info: + title: Minimal OpenAPI specification with path parameters + version: "0.1" +paths: + /resource/{resId}: + parameters: + - name: resId + in: path + required: true + description: the ID of the resource to retrieve + schema: + type: string + get: + responses: + default: + description: Return the resource. \ No newline at end of file diff --git a/tests/integration/data/v3.1/security_override.yaml b/tests/integration/data/v3.1/security_override.yaml new file mode 100644 index 00000000..9d6bec96 --- /dev/null +++ b/tests/integration/data/v3.1/security_override.yaml @@ -0,0 +1,41 @@ +openapi: "3.1.0" +info: + title: Minimal OpenAPI specification with security override + version: "0.1" +security: + - api_key: [] +paths: + /resource/{resId}: + parameters: + - name: resId + in: path + required: true + description: the ID of the resource to retrieve + schema: + type: string + get: + responses: + default: + description: Default security. + post: + security: + - petstore_auth: + - write:pets + - read:pets + responses: + default: + description: Override security. + put: + security: [] + responses: + default: + description: Remove security. +components: + securitySchemes: + api_key: + type: apiKey + name: api_key + in: query + petstore_auth: + type: http + scheme: basic \ No newline at end of file diff --git a/tests/integration/data/v3.1/webhook-example.yaml b/tests/integration/data/v3.1/webhook-example.yaml new file mode 100644 index 00000000..44fc73aa --- /dev/null +++ b/tests/integration/data/v3.1/webhook-example.yaml @@ -0,0 +1,34 @@ +openapi: 3.1.0 +info: + title: Webhook Example + version: 1.0.0 +# Since OAS 3.1.0 the paths element isn't necessary. Now a valid OpenAPI Document can describe only paths, webhooks, or even only reusable components +webhooks: + # Each webhook needs a name + newPet: + # This is a Path Item Object, the only difference is that the request is initiated by the API provider + post: + requestBody: + description: Information about a new pet in the system + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + responses: + "200": + description: Return a 200 status to indicate that the data was received successfully + +components: + schemas: + Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string diff --git a/tests/integration/schema/test_link_spec.py b/tests/integration/schema/test_link_spec.py index e2ee046d..7e519f9b 100644 --- a/tests/integration/schema/test_link_spec.py +++ b/tests/integration/schema/test_link_spec.py @@ -1,6 +1,16 @@ +import pytest + + class TestLinkSpec: - def test_no_param(self, factory): - spec = factory.spec_from_file("data/v3.0/links.yaml") + @pytest.mark.parametrize( + "spec_file", + [ + "data/v3.0/links.yaml", + "data/v3.1/links.yaml", + ], + ) + def test_no_param(self, spec_file, factory): + spec = factory.spec_from_file(spec_file) resp = spec / "paths#/status#get#responses#default" links = resp / "links" @@ -12,8 +22,15 @@ def test_no_param(self, factory): assert "requestBody" not in link assert "parameters" not in link - def test_param(self, factory): - spec = factory.spec_from_file("data/v3.0/links.yaml") + @pytest.mark.parametrize( + "spec_file", + [ + "data/v3.0/links.yaml", + "data/v3.1/links.yaml", + ], + ) + def test_param(self, spec_file, factory): + spec = factory.spec_from_file(spec_file) resp = spec / "paths#/status/{resourceId}#get#responses#default" links = resp / "links" diff --git a/tests/integration/schema/test_path_params.py b/tests/integration/schema/test_path_params.py index 1c9e8606..34ed7d05 100644 --- a/tests/integration/schema/test_path_params.py +++ b/tests/integration/schema/test_path_params.py @@ -2,12 +2,15 @@ class TestMinimal: - - spec_paths = ["data/v3.0/path_param.yaml"] - - @pytest.mark.parametrize("spec_path", spec_paths) - def test_param_present(self, factory, spec_path): - spec = factory.spec_from_file(spec_path) + @pytest.mark.parametrize( + "spec_file", + [ + "data/v3.0/path_param.yaml", + "data/v3.1/path_param.yaml", + ], + ) + def test_param_present(self, spec_file, factory): + spec = factory.spec_from_file(spec_file) path = spec / "paths#/resource/{resId}" diff --git a/tests/integration/schema/test_spec.py b/tests/integration/schema/test_spec.py index 4fecad7e..fbca2d81 100644 --- a/tests/integration/schema/test_spec.py +++ b/tests/integration/schema/test_spec.py @@ -1,6 +1,8 @@ from base64 import b64encode import pytest +from openapi_spec_validator import openapi_v30_spec_validator +from openapi_spec_validator import openapi_v31_spec_validator from openapi_core.schema.servers import get_server_url from openapi_core.schema.specs import get_spec_url @@ -30,7 +32,9 @@ def spec_dict(self, factory): @pytest.fixture def spec(self, spec_dict, spec_uri): - return Spec.create(spec_dict, url=spec_uri) + return Spec.create( + spec_dict, url=spec_uri, validator=openapi_v30_spec_validator + ) @pytest.fixture def request_validator(self, spec): @@ -297,3 +301,59 @@ def test_spec(self, spec, spec_dict): schema_spec = spec_dict["components"]["schemas"][schema_name] assert schema.getkey("readOnly") == schema_spec.get("readOnly") assert schema.getkey("writeOnly") == schema_spec.get("writeOnly") + + +class TestWebhook: + api_key = "12345" + + @property + def api_key_encoded(self): + api_key_bytes = self.api_key.encode("utf8") + api_key_bytes_enc = b64encode(api_key_bytes) + return str(api_key_bytes_enc, "utf8") + + @pytest.fixture + def spec_uri(self): + return "file://tests/integration/data/v3.1/webhook-example.yaml" + + @pytest.fixture + def spec_dict(self, factory): + content, _ = factory.content_from_file( + "data/v3.1/webhook-example.yaml" + ) + return content + + @pytest.fixture + def spec(self, spec_dict, spec_uri): + return Spec.create( + spec_dict, + url=spec_uri, + validator=openapi_v31_spec_validator, + ) + + @pytest.fixture + def request_validator(self, spec): + return RequestValidator(spec) + + @pytest.fixture + def response_validator(self, spec): + return ResponseValidator(spec) + + def test_spec(self, spec, spec_dict): + + info = spec / "info" + info_spec = spec_dict["info"] + assert info["title"] == info_spec["title"] + assert info["version"] == info_spec["version"] + + webhooks = spec / "webhooks" + webhooks_spec = spec_dict["webhooks"] + assert webhooks["newPet"] == webhooks_spec["newPet"] + + components = spec.get("components") + if not components: + return + + schemas = components.get("schemas", {}) + for schema_name, schema in schemas.items(): + assert spec_dict["components"]["schemas"][schema_name] is not None diff --git a/tests/integration/validation/test_minimal.py b/tests/integration/validation/test_minimal.py index 74803180..bc52c41b 100644 --- a/tests/integration/validation/test_minimal.py +++ b/tests/integration/validation/test_minimal.py @@ -20,6 +20,8 @@ class TestMinimal: spec_paths = [ "data/v3.0/minimal_with_servers.yaml", "data/v3.0/minimal.yaml", + "data/v3.1/minimal_with_servers.yaml", + "data/v3.1/minimal.yaml", ] @pytest.mark.parametrize("server", servers) diff --git a/tests/integration/validation/test_petstore.py b/tests/integration/validation/test_petstore.py index 589f0bbf..fd9e9f5c 100644 --- a/tests/integration/validation/test_petstore.py +++ b/tests/integration/validation/test_petstore.py @@ -20,15 +20,21 @@ from openapi_core.unmarshalling.schemas.exceptions import InvalidSchemaValue from openapi_core.validation.exceptions import MissingRequiredHeader from openapi_core.validation.exceptions import MissingRequiredParameter -from openapi_core.validation.request import openapi_request_body_validator +from openapi_core.validation.request import openapi_v30_request_body_validator from openapi_core.validation.request import ( - openapi_request_parameters_validator, + openapi_v30_request_parameters_validator, +) +from openapi_core.validation.request import ( + openapi_v30_request_security_validator, ) -from openapi_core.validation.request import openapi_request_security_validator from openapi_core.validation.request.datatypes import Parameters -from openapi_core.validation.response import openapi_response_data_validator -from openapi_core.validation.response import openapi_response_headers_validator -from openapi_core.validation.response import openapi_response_validator +from openapi_core.validation.response import ( + openapi_v30_response_data_validator, +) +from openapi_core.validation.response import ( + openapi_v30_response_headers_validator, +) +from openapi_core.validation.response import openapi_v30_response_validator from openapi_core.validation.shortcuts import validate_request from openapi_core.validation.shortcuts import validate_response @@ -73,7 +79,9 @@ def test_get_pets(self, spec): with pytest.warns(DeprecationWarning): result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, + request, + validator=openapi_v30_request_parameters_validator, ) assert result.parameters == Parameters( @@ -85,7 +93,7 @@ def test_get_pets(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -126,7 +134,9 @@ def test_get_pets_response(self, spec): with pytest.warns(DeprecationWarning): result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, + request, + validator=openapi_v30_request_parameters_validator, ) assert result.parameters == Parameters( @@ -138,7 +148,7 @@ def test_get_pets_response(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -182,7 +192,9 @@ def test_get_pets_response_no_schema(self, spec): with pytest.warns(DeprecationWarning): result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, + request, + validator=openapi_v30_request_parameters_validator, ) assert result.parameters == Parameters( @@ -194,7 +206,7 @@ def test_get_pets_response_no_schema(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -225,7 +237,9 @@ def test_get_pets_invalid_response(self, spec): with pytest.warns(DeprecationWarning): result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, + request, + validator=openapi_v30_request_parameters_validator, ) assert result.parameters == Parameters( @@ -237,7 +251,7 @@ def test_get_pets_invalid_response(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -260,10 +274,10 @@ def test_get_pets_invalid_response(self, spec): spec, request, response, - validator=openapi_response_data_validator, + validator=openapi_v30_response_data_validator, ) - response_result = openapi_response_validator.validate( + response_result = openapi_v30_response_validator.validate( spec, request, response ) @@ -295,7 +309,9 @@ def test_get_pets_ids_param(self, spec): with pytest.warns(DeprecationWarning): result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, + request, + validator=openapi_v30_request_parameters_validator, ) assert result.parameters == Parameters( @@ -308,7 +324,7 @@ def test_get_pets_ids_param(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -343,7 +359,9 @@ def test_get_pets_tags_param(self, spec): with pytest.warns(DeprecationWarning): result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, + request, + validator=openapi_v30_request_parameters_validator, ) assert result.parameters == Parameters( @@ -356,7 +374,7 @@ def test_get_pets_tags_param(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -394,11 +412,11 @@ def test_get_pets_parameter_deserialization_error(self, spec): validate_request( spec, request, - validator=openapi_request_parameters_validator, + validator=openapi_v30_request_parameters_validator, ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -423,11 +441,11 @@ def test_get_pets_wrong_parameter_type(self, spec): validate_request( spec, request, - validator=openapi_request_parameters_validator, + validator=openapi_v30_request_parameters_validator, ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -447,11 +465,11 @@ def test_get_pets_raises_missing_required_param(self, spec): validate_request( spec, request, - validator=openapi_request_parameters_validator, + validator=openapi_v30_request_parameters_validator, ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -476,10 +494,10 @@ def test_get_pets_empty_value(self, spec): validate_request( spec, request, - validator=openapi_request_parameters_validator, + validator=openapi_v30_request_parameters_validator, ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -502,7 +520,9 @@ def test_get_pets_allow_empty_value(self, spec): with pytest.warns(DeprecationWarning): result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, + request, + validator=openapi_v30_request_parameters_validator, ) assert result.parameters == Parameters( @@ -514,7 +534,7 @@ def test_get_pets_allow_empty_value(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -536,7 +556,9 @@ def test_get_pets_none_value(self, spec): with pytest.warns(DeprecationWarning): result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, + request, + validator=openapi_v30_request_parameters_validator, ) assert result.parameters == Parameters( @@ -548,7 +570,7 @@ def test_get_pets_none_value(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -571,7 +593,9 @@ def test_get_pets_param_order(self, spec): with pytest.warns(DeprecationWarning): result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, + request, + validator=openapi_v30_request_parameters_validator, ) assert result.parameters == Parameters( @@ -584,7 +608,7 @@ def test_get_pets_param_order(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -611,7 +635,9 @@ def test_get_pets_param_coordinates(self, spec): with pytest.warns(DeprecationWarning): result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, + request, + validator=openapi_v30_request_parameters_validator, ) assert result.parameters == Parameters( @@ -624,7 +650,7 @@ def test_get_pets_param_coordinates(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -674,7 +700,7 @@ def test_post_birds(self, spec, spec_dict): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters( @@ -690,7 +716,7 @@ def test_post_birds(self, spec, spec_dict): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) schemas = spec_dict["components"]["schemas"] @@ -706,7 +732,7 @@ def test_post_birds(self, spec, spec_dict): assert result.body.healthy == pet_healthy result = validate_request( - spec, request, validator=openapi_request_security_validator + spec, request, validator=openapi_v30_request_security_validator ) assert result.security == {} @@ -751,7 +777,7 @@ def test_post_cats(self, spec, spec_dict): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters( @@ -764,7 +790,7 @@ def test_post_cats(self, spec, spec_dict): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) schemas = spec_dict["components"]["schemas"] @@ -819,7 +845,7 @@ def test_post_cats_boolean_string(self, spec, spec_dict): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters( @@ -832,7 +858,7 @@ def test_post_cats_boolean_string(self, spec, spec_dict): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) schemas = spec_dict["components"]["schemas"] @@ -875,7 +901,7 @@ def test_post_no_one_of_schema(self, spec, spec_dict): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters( @@ -889,7 +915,7 @@ def test_post_no_one_of_schema(self, spec, spec_dict): with pytest.raises(InvalidSchemaValue): validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) def test_post_cats_only_required_body(self, spec, spec_dict): @@ -922,7 +948,7 @@ def test_post_cats_only_required_body(self, spec, spec_dict): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters( @@ -935,7 +961,7 @@ def test_post_cats_only_required_body(self, spec, spec_dict): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) schemas = spec_dict["components"]["schemas"] @@ -972,7 +998,7 @@ def test_post_pets_raises_invalid_mimetype(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters( @@ -986,7 +1012,7 @@ def test_post_pets_raises_invalid_mimetype(self, spec): with pytest.raises(MediaTypeNotFound): validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) def test_post_pets_missing_cookie(self, spec, spec_dict): @@ -1016,11 +1042,13 @@ def test_post_pets_missing_cookie(self, spec, spec_dict): with pytest.raises(MissingRequiredParameter): validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, + request, + validator=openapi_v30_request_parameters_validator, ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) schemas = spec_dict["components"]["schemas"] @@ -1057,11 +1085,13 @@ def test_post_pets_missing_header(self, spec, spec_dict): with pytest.raises(MissingRequiredParameter): validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, + request, + validator=openapi_v30_request_parameters_validator, ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) schemas = spec_dict["components"]["schemas"] @@ -1099,12 +1129,14 @@ def test_post_pets_raises_invalid_server_error(self, spec): with pytest.raises(ServerNotFound): validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, + request, + validator=openapi_v30_request_parameters_validator, ) with pytest.raises(ServerNotFound): validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) data_id = 1 @@ -1126,7 +1158,7 @@ def test_post_pets_raises_invalid_server_error(self, spec): spec, request, response, - validator=openapi_response_data_validator, + validator=openapi_v30_response_data_validator, ) def test_get_pet(self, spec): @@ -1149,7 +1181,7 @@ def test_get_pet(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters( @@ -1159,13 +1191,13 @@ def test_get_pet(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None result = validate_request( - spec, request, validator=openapi_request_security_validator + spec, request, validator=openapi_v30_request_security_validator ) assert result.security == { @@ -1209,7 +1241,7 @@ def test_get_pet_not_found(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters( @@ -1219,7 +1251,7 @@ def test_get_pet_not_found(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -1258,7 +1290,7 @@ def test_get_pet_wildcard(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters( @@ -1268,7 +1300,7 @@ def test_get_pet_wildcard(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -1294,13 +1326,13 @@ def test_get_tags(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters() result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -1334,14 +1366,14 @@ def test_post_tags_extra_body_properties(self, spec, spec_dict): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters() with pytest.raises(InvalidSchemaValue): validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) def test_post_tags_empty_body(self, spec, spec_dict): @@ -1359,14 +1391,14 @@ def test_post_tags_empty_body(self, spec, spec_dict): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters() with pytest.raises(InvalidSchemaValue): validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) def test_post_tags_wrong_property_type(self, spec): @@ -1384,14 +1416,14 @@ def test_post_tags_wrong_property_type(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters() with pytest.raises(InvalidSchemaValue): validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) def test_post_tags_additional_properties(self, spec): @@ -1412,13 +1444,13 @@ def test_post_tags_additional_properties(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters() result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert isinstance(result.body, BaseModel) @@ -1466,13 +1498,13 @@ def test_post_tags_created_now(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters() result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert isinstance(result.body, BaseModel) @@ -1521,13 +1553,13 @@ def test_post_tags_created_datetime(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters() result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert isinstance(result.body, BaseModel) @@ -1550,7 +1582,10 @@ def test_post_tags_created_datetime(self, spec): response = MockResponse(response_data, status_code=404) result = validate_response( - spec, request, response, validator=openapi_response_data_validator + spec, + request, + response, + validator=openapi_v30_response_data_validator, ) assert isinstance(result.data, BaseModel) @@ -1588,14 +1623,14 @@ def test_post_tags_created_invalid_type(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters() with pytest.raises(InvalidSchemaValue): validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) code = 400 @@ -1639,13 +1674,13 @@ def test_delete_tags_with_requestbody(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters() result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert isinstance(result.body, BaseModel) @@ -1667,7 +1702,7 @@ def test_delete_tags_with_requestbody(self, spec): spec, request, response, - validator=openapi_response_headers_validator, + validator=openapi_v30_response_headers_validator, ) assert result.headers == { @@ -1685,13 +1720,13 @@ def test_delete_tags_no_requestbody(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters() result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -1707,13 +1742,13 @@ def test_delete_tags_raises_missing_required_response_header(self, spec): ) result = validate_request( - spec, request, validator=openapi_request_parameters_validator + spec, request, validator=openapi_v30_request_parameters_validator ) assert result.parameters == Parameters() result = validate_request( - spec, request, validator=openapi_request_body_validator + spec, request, validator=openapi_v30_request_body_validator ) assert result.body is None @@ -1722,7 +1757,7 @@ def test_delete_tags_raises_missing_required_response_header(self, spec): response = MockResponse(data, status_code=200) with pytest.warns(DeprecationWarning): - response_result = openapi_response_validator.validate( + response_result = openapi_v30_response_validator.validate( spec, request, response ) diff --git a/tests/integration/validation/test_read_only_write_only.py b/tests/integration/validation/test_read_only_write_only.py index 1c16cef6..e4bc1fda 100644 --- a/tests/integration/validation/test_read_only_write_only.py +++ b/tests/integration/validation/test_read_only_write_only.py @@ -5,8 +5,8 @@ from openapi_core.testing import MockRequest from openapi_core.testing import MockResponse from openapi_core.unmarshalling.schemas.exceptions import InvalidSchemaValue -from openapi_core.validation.request import openapi_request_validator -from openapi_core.validation.response import openapi_response_validator +from openapi_core.validation.request import openapi_v30_request_validator +from openapi_core.validation.response import openapi_v30_response_validator @pytest.fixture(scope="class") @@ -27,7 +27,7 @@ def test_write_a_read_only_property(self, spec): host_url="", method="POST", path="/users", data=data ) - result = openapi_request_validator.validate(spec, request) + result = openapi_v30_request_validator.validate(spec, request) assert type(result.errors[0]) == InvalidSchemaValue assert result.body is None @@ -44,7 +44,9 @@ def test_read_only_property_response(self, spec): response = MockResponse(data) - result = openapi_response_validator.validate(spec, request, response) + result = openapi_v30_response_validator.validate( + spec, request, response + ) assert not result.errors assert result.data == { @@ -66,7 +68,7 @@ def test_write_only_property(self, spec): host_url="", method="POST", path="/users", data=data ) - result = openapi_request_validator.validate(spec, request) + result = openapi_v30_request_validator.validate(spec, request) assert not result.errors assert result.body == { @@ -86,7 +88,9 @@ def test_read_a_write_only_property(self, spec): request = MockRequest(host_url="", method="POST", path="/users") response = MockResponse(data) - result = openapi_response_validator.validate(spec, request, response) + result = openapi_v30_response_validator.validate( + spec, request, response + ) assert type(result.errors[0]) == InvalidSchemaValue assert result.data is None