Skip to content

Move to jsonschema-path #690

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
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ Firstly create your specification object.

.. code-block:: python

from openapi_core import Spec
from jsonschema_path import SchemaPath

spec = Spec.from_file_path('openapi.json')
spec = SchemaPath.from_file_path('openapi.json')

Now you can use it to validate and unmarshal against requests and/or responses.

Expand Down
4 changes: 2 additions & 2 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ Firstly create your specification object.

.. code-block:: python

from openapi_core import Spec
from jsonschema_path import SchemaPath

spec = Spec.from_file_path('openapi.json')
spec = SchemaPath.from_file_path('openapi.json')

Now you can use it to validate and unmarshal your requests and/or responses.

Expand Down
8 changes: 4 additions & 4 deletions docs/integrations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,29 +54,29 @@ Django can be integrated by middleware. Add ``DjangoOpenAPIMiddleware`` to your
:emphasize-lines: 6,9

# settings.py
from openapi_core import Spec
from jsonschema_path import SchemaPath

MIDDLEWARE = [
# ...
'openapi_core.contrib.django.middlewares.DjangoOpenAPIMiddleware',
]

OPENAPI_SPEC = Spec.from_dict(spec_dict)
OPENAPI_SPEC = SchemaPath.from_dict(spec_dict)

You can skip response validation process: by setting ``OPENAPI_RESPONSE_CLS`` to ``None``

.. code-block:: python
:emphasize-lines: 10

# settings.py
from openapi_core import Spec
from jsonschema_path import SchemaPath

MIDDLEWARE = [
# ...
'openapi_core.contrib.django.middlewares.DjangoOpenAPIMiddleware',
]

OPENAPI_SPEC = Spec.from_dict(spec_dict)
OPENAPI_SPEC = SchemaPath.from_dict(spec_dict)
OPENAPI_RESPONSE_CLS = None

After that you have access to unmarshal result object with all validated request data from Django view through request object.
Expand Down
11 changes: 7 additions & 4 deletions openapi_core/casting/schemas/casters.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
from typing import Callable
from typing import List

from jsonschema_path import SchemaPath

from openapi_core.casting.schemas.datatypes import CasterCallable
from openapi_core.casting.schemas.exceptions import CastError
from openapi_core.spec import Spec

if TYPE_CHECKING:
from openapi_core.casting.schemas.factories import SchemaCastersFactory


class BaseSchemaCaster:
def __init__(self, schema: Spec):
def __init__(self, schema: SchemaPath):
self.schema = schema

def __call__(self, value: Any) -> Any:
Expand All @@ -26,7 +27,7 @@ def cast(self, value: Any) -> Any:


class CallableSchemaCaster(BaseSchemaCaster):
def __init__(self, schema: Spec, caster_callable: CasterCallable):
def __init__(self, schema: SchemaPath, caster_callable: CasterCallable):
super().__init__(schema)
self.caster_callable = caster_callable

Expand All @@ -43,7 +44,9 @@ def cast(self, value: Any) -> Any:


class ComplexCaster(BaseSchemaCaster):
def __init__(self, schema: Spec, casters_factory: "SchemaCastersFactory"):
def __init__(
self, schema: SchemaPath, casters_factory: "SchemaCastersFactory"
):
super().__init__(schema)
self.casters_factory = casters_factory

Expand Down
5 changes: 3 additions & 2 deletions openapi_core/casting/schemas/factories.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from typing import Dict

from jsonschema_path import SchemaPath

from openapi_core.casting.schemas.casters import ArrayCaster
from openapi_core.casting.schemas.casters import BaseSchemaCaster
from openapi_core.casting.schemas.casters import CallableSchemaCaster
from openapi_core.casting.schemas.casters import DummyCaster
from openapi_core.casting.schemas.datatypes import CasterCallable
from openapi_core.spec import Spec
from openapi_core.util import forcebool


Expand All @@ -24,7 +25,7 @@ class SchemaCastersFactory:
"array": ArrayCaster,
}

def create(self, schema: Spec) -> BaseSchemaCaster:
def create(self, schema: SchemaPath) -> BaseSchemaCaster:
schema_type = schema.getkey("type", "any")

if schema_type in self.DUMMY_CASTERS:
Expand Down
6 changes: 3 additions & 3 deletions openapi_core/contrib/falcon/middlewares.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@

from falcon.request import Request
from falcon.response import Response
from jsonschema_path import SchemaPath

from openapi_core.contrib.falcon.handlers import FalconOpenAPIErrorsHandler
from openapi_core.contrib.falcon.handlers import (
FalconOpenAPIValidRequestHandler,
)
from openapi_core.contrib.falcon.requests import FalconOpenAPIRequest
from openapi_core.contrib.falcon.responses import FalconOpenAPIResponse
from openapi_core.spec import Spec
from openapi_core.unmarshalling.processors import UnmarshallingProcessor
from openapi_core.unmarshalling.request.types import RequestUnmarshallerType
from openapi_core.unmarshalling.response.types import ResponseUnmarshallerType
Expand All @@ -28,7 +28,7 @@ class FalconOpenAPIMiddleware(UnmarshallingProcessor[Request, Response]):

def __init__(
self,
spec: Spec,
spec: SchemaPath,
request_unmarshaller_cls: Optional[RequestUnmarshallerType] = None,
response_unmarshaller_cls: Optional[ResponseUnmarshallerType] = None,
request_cls: Type[FalconOpenAPIRequest] = FalconOpenAPIRequest,
Expand All @@ -51,7 +51,7 @@ def __init__(
@classmethod
def from_spec(
cls,
spec: Spec,
spec: SchemaPath,
request_unmarshaller_cls: Optional[RequestUnmarshallerType] = None,
response_unmarshaller_cls: Optional[ResponseUnmarshallerType] = None,
request_cls: Type[FalconOpenAPIRequest] = FalconOpenAPIRequest,
Expand Down
6 changes: 3 additions & 3 deletions openapi_core/contrib/flask/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
from flask.globals import request
from flask.wrappers import Request
from flask.wrappers import Response
from jsonschema_path import SchemaPath

from openapi_core.contrib.flask.handlers import FlaskOpenAPIErrorsHandler
from openapi_core.contrib.flask.handlers import FlaskOpenAPIValidRequestHandler
from openapi_core.contrib.flask.providers import FlaskRequestProvider
from openapi_core.contrib.flask.requests import FlaskOpenAPIRequest
from openapi_core.contrib.flask.responses import FlaskOpenAPIResponse
from openapi_core.spec import Spec
from openapi_core.unmarshalling.processors import UnmarshallingProcessor
from openapi_core.unmarshalling.request.types import RequestUnmarshallerType
from openapi_core.unmarshalling.response.types import ResponseUnmarshallerType
Expand All @@ -28,7 +28,7 @@ class FlaskOpenAPIViewDecorator(UnmarshallingProcessor[Request, Response]):

def __init__(
self,
spec: Spec,
spec: SchemaPath,
request_unmarshaller_cls: Optional[RequestUnmarshallerType] = None,
response_unmarshaller_cls: Optional[ResponseUnmarshallerType] = None,
request_cls: Type[FlaskOpenAPIRequest] = FlaskOpenAPIRequest,
Expand Down Expand Up @@ -85,7 +85,7 @@ def _validate_response(self) -> bool:
@classmethod
def from_spec(
cls,
spec: Spec,
spec: SchemaPath,
request_unmarshaller_cls: Optional[RequestUnmarshallerType] = None,
response_unmarshaller_cls: Optional[ResponseUnmarshallerType] = None,
request_cls: Type[FlaskOpenAPIRequest] = FlaskOpenAPIRequest,
Expand Down
4 changes: 2 additions & 2 deletions openapi_core/contrib/flask/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@
from typing import Any

from flask.views import MethodView
from jsonschema_path import SchemaPath

from openapi_core.contrib.flask.decorators import FlaskOpenAPIViewDecorator
from openapi_core.contrib.flask.handlers import FlaskOpenAPIErrorsHandler
from openapi_core.spec import Spec


class FlaskOpenAPIView(MethodView):
"""Brings OpenAPI specification validation and unmarshalling for views."""

openapi_errors_handler = FlaskOpenAPIErrorsHandler

def __init__(self, spec: Spec, **unmarshaller_kwargs: Any):
def __init__(self, spec: SchemaPath, **unmarshaller_kwargs: Any):
super().__init__()

self.decorator = FlaskOpenAPIViewDecorator(
Expand Down
5 changes: 3 additions & 2 deletions openapi_core/deserializing/styles/deserializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@
from typing import List
from typing import Optional

from jsonschema_path import SchemaPath

from openapi_core.deserializing.exceptions import DeserializeError
from openapi_core.deserializing.styles.datatypes import DeserializerCallable
from openapi_core.deserializing.styles.exceptions import (
EmptyQueryParameterValue,
)
from openapi_core.schema.parameters import get_aslist
from openapi_core.schema.parameters import get_explode
from openapi_core.spec import Spec


class CallableStyleDeserializer:
def __init__(
self,
param_or_header: Spec,
param_or_header: SchemaPath,
style: str,
deserializer_callable: Optional[DeserializerCallable] = None,
):
Expand Down
5 changes: 3 additions & 2 deletions openapi_core/deserializing/styles/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
from functools import partial
from typing import Dict

from jsonschema_path import SchemaPath

from openapi_core.deserializing.styles.datatypes import DeserializerCallable
from openapi_core.deserializing.styles.deserializers import (
CallableStyleDeserializer,
)
from openapi_core.deserializing.styles.util import split
from openapi_core.schema.parameters import get_style
from openapi_core.spec import Spec


class StyleDeserializersFactory:
Expand All @@ -20,7 +21,7 @@ class StyleDeserializersFactory:
"deepObject": partial(re.split, pattern=r"\[|\]"),
}

def create(self, param_or_header: Spec) -> CallableStyleDeserializer:
def create(self, param_or_header: SchemaPath) -> CallableStyleDeserializer:
style = get_style(param_or_header)

deserialize_callable = self.STYLE_DESERIALIZERS.get(style)
Expand Down
9 changes: 5 additions & 4 deletions openapi_core/extensions/models/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,24 @@
from typing import Optional
from typing import Type

from jsonschema_path import SchemaPath

from openapi_core.extensions.models.types import Field
from openapi_core.spec import Spec


class DictFactory:
base_class = dict

def create(
self, schema: Spec, fields: Iterable[Field]
self, schema: SchemaPath, fields: Iterable[Field]
) -> Type[Dict[Any, Any]]:
return self.base_class


class ModelFactory(DictFactory):
def create(
self,
schema: Spec,
schema: SchemaPath,
fields: Iterable[Field],
) -> Type[Any]:
name = schema.getkey("x-model")
Expand All @@ -37,7 +38,7 @@ def create(
class ModelPathFactory(ModelFactory):
def create(
self,
schema: Spec,
schema: SchemaPath,
fields: Iterable[Field],
) -> Any:
model_class_path = schema.getkey("x-model-path")
Expand Down
5 changes: 3 additions & 2 deletions openapi_core/finders.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
from typing import Optional
from typing import Type

from jsonschema_path import SchemaPath

from openapi_core.exceptions import SpecError
from openapi_core.spec import Spec
from openapi_core.unmarshalling.request.types import RequestUnmarshallerType
from openapi_core.unmarshalling.request.types import (
WebhookRequestUnmarshallerType,
Expand Down Expand Up @@ -42,7 +43,7 @@ class SpecFinder:
def __init__(self, specs: Mapping[SpecVersion, SpecClasses]) -> None:
self.specs = specs

def get_classes(self, spec: Spec) -> SpecClasses:
def get_classes(self, spec: SchemaPath) -> SpecClasses:
for v, classes in self.specs.items():
if v.name in spec and spec[v.name].startswith(v.version):
return classes
Expand Down
9 changes: 5 additions & 4 deletions openapi_core/schema/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
from typing import Mapping
from typing import Optional

from jsonschema_path import SchemaPath

from openapi_core.schema.protocols import SuportsGetAll
from openapi_core.schema.protocols import SuportsGetList
from openapi_core.spec import Spec


def get_aslist(param_or_header: Spec) -> bool:
def get_aslist(param_or_header: SchemaPath) -> bool:
"""Checks if parameter/header is described as list for simpler scenarios"""
# if schema is not defined it's a complex scenario
if "schema" not in param_or_header:
Expand All @@ -21,7 +22,7 @@ def get_aslist(param_or_header: Spec) -> bool:
return schema_type in ["array", "object"]


def get_style(param_or_header: Spec) -> str:
def get_style(param_or_header: SchemaPath) -> str:
"""Checks parameter/header style for simpler scenarios"""
if "style" in param_or_header:
assert isinstance(param_or_header["style"], str)
Expand All @@ -34,7 +35,7 @@ def get_style(param_or_header: Spec) -> str:
return "simple" if location in ["path", "header"] else "form"


def get_explode(param_or_header: Spec) -> bool:
def get_explode(param_or_header: SchemaPath) -> bool:
"""Checks parameter/header explode for simpler scenarios"""
if "explode" in param_or_header:
assert isinstance(param_or_header["explode"], bool)
Expand Down
4 changes: 2 additions & 2 deletions openapi_core/schema/schemas.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from typing import Any
from typing import Dict

from openapi_core.spec import Spec
from jsonschema_path import SchemaPath


def get_properties(schema: Spec) -> Dict[str, Any]:
def get_properties(schema: SchemaPath) -> Dict[str, Any]:
properties = schema.get("properties", {})
properties_dict = dict(list(properties.items()))
return properties_dict
6 changes: 3 additions & 3 deletions openapi_core/schema/servers.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
from typing import Any
from typing import Dict

from openapi_core.spec import Spec
from jsonschema_path import SchemaPath


def is_absolute(url: str) -> bool:
return url.startswith("//") or "://" in url


def get_server_default_variables(server: Spec) -> Dict[str, Any]:
def get_server_default_variables(server: SchemaPath) -> Dict[str, Any]:
if "variables" not in server:
return {}

Expand All @@ -19,7 +19,7 @@ def get_server_default_variables(server: Spec) -> Dict[str, Any]:
return defaults


def get_server_url(server: Spec, **variables: Any) -> str:
def get_server_url(server: SchemaPath, **variables: Any) -> str:
if not variables:
variables = get_server_default_variables(server)
assert isinstance(server["url"], str)
Expand Down
5 changes: 3 additions & 2 deletions openapi_core/schema/specs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from jsonschema_path import SchemaPath

from openapi_core.schema.servers import get_server_url
from openapi_core.spec import Spec


def get_spec_url(spec: Spec, index: int = 0) -> str:
def get_spec_url(spec: SchemaPath, index: int = 0) -> str:
servers = spec / "servers"
return get_server_url(servers / 0)
Loading