From 400d4552f0cd2af3bf16e4ad49bd18a34d55fd54 Mon Sep 17 00:00:00 2001 From: p1c2u Date: Sat, 7 Jun 2025 18:45:55 +0100 Subject: [PATCH] Jsonschema-path upgrade --- openapi_spec_validator/readers.py | 8 +- openapi_spec_validator/schemas/utils.py | 8 +- openapi_spec_validator/validation/keywords.py | 58 ++++++++------ .../validation/protocols.py | 11 ++- openapi_spec_validator/validation/proxies.py | 8 +- .../validation/validators.py | 2 +- poetry.lock | 80 +++++++++++++++---- pyproject.toml | 2 +- 8 files changed, 116 insertions(+), 61 deletions(-) diff --git a/openapi_spec_validator/readers.py b/openapi_spec_validator/readers.py index e56944a..4af9270 100644 --- a/openapi_spec_validator/readers.py +++ b/openapi_spec_validator/readers.py @@ -1,20 +1,18 @@ import sys -from collections.abc import Hashable from os import path from pathlib import Path -from typing import Any -from typing import Mapping from typing import Tuple from jsonschema_path.handlers import all_urls_handler from jsonschema_path.handlers import file_handler +from jsonschema_path.typing import Schema -def read_from_stdin(filename: str) -> Tuple[Mapping[Hashable, Any], str]: +def read_from_stdin(filename: str) -> Tuple[Schema, str]: return file_handler(sys.stdin), "" # type: ignore -def read_from_filename(filename: str) -> Tuple[Mapping[Hashable, Any], str]: +def read_from_filename(filename: str) -> Tuple[Schema, str]: if not path.isfile(filename): raise OSError(f"No such file: {filename}") diff --git a/openapi_spec_validator/schemas/utils.py b/openapi_spec_validator/schemas/utils.py index ca437e6..7b2fd92 100644 --- a/openapi_spec_validator/schemas/utils.py +++ b/openapi_spec_validator/schemas/utils.py @@ -1,16 +1,14 @@ """OpenAIP spec validator schemas utils module.""" -from collections.abc import Hashable from importlib.resources import as_file from importlib.resources import files from os import path -from typing import Any -from typing import Mapping from typing import Tuple from jsonschema_path.readers import FilePathReader +from jsonschema_path.typing import Schema -def get_schema(version: str) -> Tuple[Mapping[Hashable, Any], str]: +def get_schema(version: str) -> Tuple[Schema, str]: schema_path = f"resources/schemas/v{version}/schema.json" ref = files("openapi_spec_validator") / schema_path with as_file(ref) as resource_path: @@ -18,6 +16,6 @@ def get_schema(version: str) -> Tuple[Mapping[Hashable, Any], str]: return FilePathReader(schema_path_full).read() -def get_schema_content(version: str) -> Mapping[Hashable, Any]: +def get_schema_content(version: str) -> Schema: content, _ = get_schema(version) return content diff --git a/openapi_spec_validator/validation/keywords.py b/openapi_spec_validator/validation/keywords.py index 869c9fd..877a3fe 100644 --- a/openapi_spec_validator/validation/keywords.py +++ b/openapi_spec_validator/validation/keywords.py @@ -1,6 +1,7 @@ import string from typing import TYPE_CHECKING from typing import Any +from typing import Sequence from typing import Iterator from typing import List from typing import Optional @@ -78,7 +79,8 @@ def _collect_properties(self, schema: SchemaPath) -> set[str]: props: set[str] = set() if "properties" in schema: - props.update((schema / "properties").keys()) + schema_props = (schema / "properties").keys() + props.update(cast(Sequence[str], schema_props)) for kw in ("allOf", "anyOf", "oneOf"): if kw in schema: @@ -96,11 +98,12 @@ def _collect_properties(self, schema: SchemaPath) -> set[str]: def __call__( self, schema: SchemaPath, require_properties: bool = True ) -> Iterator[ValidationError]: - if not hasattr(schema.content(), "__getitem__"): + schema_value = schema.read_value() + if not hasattr(schema_value, "__getitem__"): return assert self.schema_ids_registry is not None - schema_id = id(schema.content()) + schema_id = id(schema_value) if schema_id in self.schema_ids_registry: return self.schema_ids_registry.append(schema_id) @@ -151,8 +154,8 @@ def __call__( require_properties=False, ) - required = schema.getkey("required", []) - properties = schema.get("properties", {}).keys() + required = "required" in schema and (schema / "required").read_value() or [] + properties = "properties" in schema and (schema / "properties").keys() or [] if "allOf" in schema: extra_properties = list( set(required) - set(properties) - set(nested_properties) @@ -166,10 +169,12 @@ def __call__( ) if "default" in schema: - default = schema["default"] - nullable = schema.get("nullable", False) - if default is not None or nullable is not True: - yield from self.default_validator(schema, default) + default_value = (schema / "default").read_value() + nullable_value = False + if "nullable" in schema: + nullable_value = (schema / "nullable").read_value() + if default_value is not None or nullable_value is not True: + yield from self.default_validator(schema, default_value) class SchemasValidator(KeywordValidator): @@ -203,9 +208,9 @@ def __call__(self, parameter: SchemaPath) -> Iterator[ValidationError]: if "default" in parameter: # only possible in swagger 2.0 - default = parameter.getkey("default") - if default is not None: - yield from self.default_validator(parameter, default) + if "default" in parameter: + default_value = (parameter / "default").read_value() + yield from self.default_validator(parameter, default_value) class ParametersValidator(KeywordValidator): @@ -246,6 +251,7 @@ def media_type_validator(self) -> MediaTypeValidator: def __call__(self, content: SchemaPath) -> Iterator[ValidationError]: for mimetype, media_type in content.items(): + assert isinstance(mimetype, str) yield from self.media_type_validator(mimetype, media_type) @@ -291,6 +297,7 @@ def response_validator(self) -> ResponseValidator: def __call__(self, responses: SchemaPath) -> Iterator[ValidationError]: for response_code, response in responses.items(): + assert isinstance(response_code, str) yield from self.response_validator(response_code, response) @@ -317,15 +324,17 @@ def __call__( ) -> Iterator[ValidationError]: assert self.operation_ids_registry is not None - operation_id = operation.getkey("operationId") - if ( - operation_id is not None - and operation_id in self.operation_ids_registry - ): - yield DuplicateOperationIDError( - f"Operation ID '{operation_id}' for '{name}' in '{url}' is not unique" - ) - self.operation_ids_registry.append(operation_id) + if "operationId" in operation: + operation_id_value = (operation / "operationId").read_value() + if ( + operation_id_value is not None + and operation_id_value in self.operation_ids_registry + ): + yield DuplicateOperationIDError( + f"Operation ID '{operation_id_value}' for " + f"'{name}' in '{url}' is not unique" + ) + self.operation_ids_registry.append(operation_id_value) if "responses" in operation: responses = operation / "responses" @@ -392,6 +401,7 @@ def __call__( yield from self.parameters_validator(parameters) for field_name, operation in path_item.items(): + assert isinstance(field_name, str) if field_name not in self.OPERATIONS: continue @@ -407,6 +417,7 @@ def path_validator(self) -> PathValidator: def __call__(self, paths: SchemaPath) -> Iterator[ValidationError]: for url, path_item in paths.items(): + assert isinstance(url, str) yield from self.path_validator(url, path_item) @@ -416,8 +427,9 @@ def schemas_validator(self) -> SchemasValidator: return cast(SchemasValidator, self.registry["schemas"]) def __call__(self, components: SchemaPath) -> Iterator[ValidationError]: - schemas = components.get("schemas", {}) - yield from self.schemas_validator(schemas) + if "schemas" in components: + schemas = components / "schemas" + yield from self.schemas_validator(schemas) class RootValidator(KeywordValidator): diff --git a/openapi_spec_validator/validation/protocols.py b/openapi_spec_validator/validation/protocols.py index f6aa41a..3e7403c 100644 --- a/openapi_spec_validator/validation/protocols.py +++ b/openapi_spec_validator/validation/protocols.py @@ -1,22 +1,21 @@ -from typing import Any -from typing import Hashable from typing import Iterator -from typing import Mapping from typing import Optional from typing import Protocol from typing import runtime_checkable +from jsonschema_path.typing import Schema + from openapi_spec_validator.validation.exceptions import OpenAPIValidationError @runtime_checkable class SupportsValidation(Protocol): - def is_valid(self, instance: Mapping[Hashable, Any]) -> bool: + def is_valid(self, instance: Schema) -> bool: ... def iter_errors( self, - instance: Mapping[Hashable, Any], + instance: Schema, base_uri: str = "", spec_url: Optional[str] = None, ) -> Iterator[OpenAPIValidationError]: @@ -24,7 +23,7 @@ def iter_errors( def validate( self, - instance: Mapping[Hashable, Any], + instance: Schema, base_uri: str = "", spec_url: Optional[str] = None, ) -> None: diff --git a/openapi_spec_validator/validation/proxies.py b/openapi_spec_validator/validation/proxies.py index 8651dfa..964266d 100644 --- a/openapi_spec_validator/validation/proxies.py +++ b/openapi_spec_validator/validation/proxies.py @@ -62,7 +62,7 @@ class DetectValidatorProxy: def __init__(self, choices: Mapping[Tuple[str, str], SpecValidatorProxy]): self.choices = choices - def detect(self, instance: Mapping[Hashable, Any]) -> SpecValidatorProxy: + def detect(self, instance: Schema) -> SpecValidatorProxy: for (key, value), validator in self.choices.items(): if key in instance and instance[key].startswith(value): return validator @@ -70,7 +70,7 @@ def detect(self, instance: Mapping[Hashable, Any]) -> SpecValidatorProxy: def validate( self, - instance: Mapping[Hashable, Any], + instance: Schema, base_uri: str = "", spec_url: Optional[str] = None, ) -> None: @@ -80,14 +80,14 @@ def validate( ): raise err - def is_valid(self, instance: Mapping[Hashable, Any]) -> bool: + def is_valid(self, instance: Schema) -> bool: validator = self.detect(instance) error = next(validator.iter_errors(instance), None) return error is None def iter_errors( self, - instance: Mapping[Hashable, Any], + instance: Schema, base_uri: str = "", spec_url: Optional[str] = None, ) -> Iterator[OpenAPIValidationError]: diff --git a/openapi_spec_validator/validation/validators.py b/openapi_spec_validator/validation/validators.py index f4d889d..397f022 100644 --- a/openapi_spec_validator/validation/validators.py +++ b/openapi_spec_validator/validation/validators.py @@ -53,7 +53,7 @@ def __init__( if isinstance(schema, SchemaPath): self.schema_path = schema - self.schema = schema.contents() + self.schema = schema.read_value() else: self.schema = schema self.schema_path = SchemaPath.from_dict( diff --git a/poetry.lock b/poetry.lock index a9fcd89..3fa1795 100644 --- a/poetry.lock +++ b/poetry.lock @@ -148,7 +148,7 @@ version = "2025.4.26" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" -groups = ["main", "docs"] +groups = ["docs"] files = [ {file = "certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3"}, {file = "certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6"}, @@ -184,7 +184,7 @@ version = "3.4.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" -groups = ["main", "docs"] +groups = ["docs"] files = [ {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"}, {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"}, @@ -569,7 +569,7 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" -groups = ["main", "docs"] +groups = ["docs"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -685,21 +685,24 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- [[package]] name = "jsonschema-path" -version = "0.3.4" +version = "0.4.0b1" description = "JSONSchema Spec with object-oriented paths" optional = false -python-versions = "<4.0.0,>=3.8.0" +python-versions = "<4.0.0,>=3.9.0" groups = ["main"] files = [ - {file = "jsonschema_path-0.3.4-py3-none-any.whl", hash = "sha256:f502191fdc2b22050f9a81c9237be9d27145b9001c55842bece5e94e382e52f8"}, - {file = "jsonschema_path-0.3.4.tar.gz", hash = "sha256:8365356039f16cc65fddffafda5f58766e34bebab7d6d105616ab52bc4297001"}, + {file = "jsonschema_path-0.4.0b1-py3-none-any.whl", hash = "sha256:f0cd42238c1445cecac3b2796fa24dcc62b8426623d1cb4d8d755f3715abf3ba"}, + {file = "jsonschema_path-0.4.0b1.tar.gz", hash = "sha256:4678dcb27e5fbc58b39baf7ca8c36a6a7de3bcafacaaafc1b8a1d54038ce8d8a"}, ] [package.dependencies] -pathable = ">=0.4.1,<0.5.0" +pathable = ">=0.5.0b2,<0.6.0" +pyrsistent = ">=0.20.0,<0.21.0" PyYAML = ">=5.1" referencing = "<0.37.0" -requests = ">=2.31.0,<3.0.0" + +[package.extras] +requests = ["requests (>=2.31.0,<3.0.0)"] [[package]] name = "jsonschema-specifications" @@ -933,16 +936,19 @@ files = [ [[package]] name = "pathable" -version = "0.4.4" +version = "0.5.0b2" description = "Object-oriented paths" optional = false -python-versions = "<4.0.0,>=3.7.0" +python-versions = "<4.0,>=3.9" groups = ["main"] files = [ - {file = "pathable-0.4.4-py3-none-any.whl", hash = "sha256:5ae9e94793b6ef5a4cbe0a7ce9dbbefc1eec38df253763fd0aeeacf2762dbbc2"}, - {file = "pathable-0.4.4.tar.gz", hash = "sha256:6905a3cd17804edfac7875b5f6c9142a218c7caef78693c2dbbbfbac186d88b2"}, + {file = "pathable-0.5.0b2-py3-none-any.whl", hash = "sha256:4c78bc5dae0c64a6191b955b7975bab58f0e298e197f591d4f0172886824a52b"}, + {file = "pathable-0.5.0b2.tar.gz", hash = "sha256:0005483148dc1991ab32e4cb4cde7e2b8f376f081a1639631e424db0792860e9"}, ] +[package.dependencies] +pyrsistent = ">=0.20.0,<0.21.0" + [[package]] name = "pathspec" version = "0.12.1" @@ -1224,6 +1230,48 @@ tomli = {version = ">=2.2.1", markers = "python_version < \"3.11\""} docs = ["furo (>=2024.8.6)", "sphinx-autodoc-typehints (>=3.2)"] testing = ["covdefaults (>=2.3)", "pytest (>=8.3.5)", "pytest-cov (>=6.1.1)", "pytest-mock (>=3.14)", "setuptools (>=80.3.1)"] +[[package]] +name = "pyrsistent" +version = "0.20.0" +description = "Persistent/Functional/Immutable data structures" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "pyrsistent-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c3aba3e01235221e5b229a6c05f585f344734bd1ad42a8ac51493d74722bbce"}, + {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1beb78af5423b879edaf23c5591ff292cf7c33979734c99aa66d5914ead880f"}, + {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21cc459636983764e692b9eba7144cdd54fdec23ccdb1e8ba392a63666c60c34"}, + {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5ac696f02b3fc01a710427585c855f65cd9c640e14f52abe52020722bb4906b"}, + {file = "pyrsistent-0.20.0-cp310-cp310-win32.whl", hash = "sha256:0724c506cd8b63c69c7f883cc233aac948c1ea946ea95996ad8b1380c25e1d3f"}, + {file = "pyrsistent-0.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:8441cf9616d642c475684d6cf2520dd24812e996ba9af15e606df5f6fd9d04a7"}, + {file = "pyrsistent-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0f3b1bcaa1f0629c978b355a7c37acd58907390149b7311b5db1b37648eb6958"}, + {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cdd7ef1ea7a491ae70d826b6cc64868de09a1d5ff9ef8d574250d0940e275b8"}, + {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cae40a9e3ce178415040a0383f00e8d68b569e97f31928a3a8ad37e3fde6df6a"}, + {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6288b3fa6622ad8a91e6eb759cfc48ff3089e7c17fb1d4c59a919769314af224"}, + {file = "pyrsistent-0.20.0-cp311-cp311-win32.whl", hash = "sha256:7d29c23bdf6e5438c755b941cef867ec2a4a172ceb9f50553b6ed70d50dfd656"}, + {file = "pyrsistent-0.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:59a89bccd615551391f3237e00006a26bcf98a4d18623a19909a2c48b8e986ee"}, + {file = "pyrsistent-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:09848306523a3aba463c4b49493a760e7a6ca52e4826aa100ee99d8d39b7ad1e"}, + {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a14798c3005ec892bbada26485c2eea3b54109cb2533713e355c806891f63c5e"}, + {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b14decb628fac50db5e02ee5a35a9c0772d20277824cfe845c8a8b717c15daa3"}, + {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e2c116cc804d9b09ce9814d17df5edf1df0c624aba3b43bc1ad90411487036d"}, + {file = "pyrsistent-0.20.0-cp312-cp312-win32.whl", hash = "sha256:e78d0c7c1e99a4a45c99143900ea0546025e41bb59ebc10182e947cf1ece9174"}, + {file = "pyrsistent-0.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:4021a7f963d88ccd15b523787d18ed5e5269ce57aa4037146a2377ff607ae87d"}, + {file = "pyrsistent-0.20.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:79ed12ba79935adaac1664fd7e0e585a22caa539dfc9b7c7c6d5ebf91fb89054"}, + {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f920385a11207dc372a028b3f1e1038bb244b3ec38d448e6d8e43c6b3ba20e98"}, + {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f5c2d012671b7391803263419e31b5c7c21e7c95c8760d7fc35602353dee714"}, + {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef3992833fbd686ee783590639f4b8343a57f1f75de8633749d984dc0eb16c86"}, + {file = "pyrsistent-0.20.0-cp38-cp38-win32.whl", hash = "sha256:881bbea27bbd32d37eb24dd320a5e745a2a5b092a17f6debc1349252fac85423"}, + {file = "pyrsistent-0.20.0-cp38-cp38-win_amd64.whl", hash = "sha256:6d270ec9dd33cdb13f4d62c95c1a5a50e6b7cdd86302b494217137f760495b9d"}, + {file = "pyrsistent-0.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ca52d1ceae015859d16aded12584c59eb3825f7b50c6cfd621d4231a6cc624ce"}, + {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b318ca24db0f0518630e8b6f3831e9cba78f099ed5c1d65ffe3e023003043ba0"}, + {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed2c3216a605dc9a6ea50c7e84c82906e3684c4e80d2908208f662a6cbf9022"}, + {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e14c95c16211d166f59c6611533d0dacce2e25de0f76e4c140fde250997b3ca"}, + {file = "pyrsistent-0.20.0-cp39-cp39-win32.whl", hash = "sha256:f058a615031eea4ef94ead6456f5ec2026c19fb5bd6bfe86e9665c4158cf802f"}, + {file = "pyrsistent-0.20.0-cp39-cp39-win_amd64.whl", hash = "sha256:58b8f6366e152092194ae68fefe18b9f0b4f89227dfd86a07770c3d86097aebf"}, + {file = "pyrsistent-0.20.0-py3-none-any.whl", hash = "sha256:c55acc4733aad6560a7f5f818466631f07efc001fd023f34a6c203f8b6df0f0b"}, + {file = "pyrsistent-0.20.0.tar.gz", hash = "sha256:4c48f78f62ab596c679086084d0dd13254ae4f3d6c72a83ffdf5ebdef8f265a4"}, +] + [[package]] name = "pytest" version = "8.4.0" @@ -1377,7 +1425,7 @@ version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" -groups = ["main", "docs"] +groups = ["docs"] files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, @@ -1914,7 +1962,7 @@ version = "2.4.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" -groups = ["main", "docs"] +groups = ["docs"] files = [ {file = "urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813"}, {file = "urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466"}, @@ -1974,4 +2022,4 @@ docs = [] [metadata] lock-version = "2.1" python-versions = "^3.9.0" -content-hash = "cc97a2a2a1dabc2dd6aff33bfd9842bffbb3c0ac85434979d809fb2c4c63c5f4" +content-hash = "ea67a83adf2a39d5b8904bf095e3ecafade4ad9a7aed80d4850edb108e9abe24" diff --git a/pyproject.toml b/pyproject.toml index d5d3b6e..ce03731 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,7 +56,7 @@ include = [ jsonschema = "^4.24.0" openapi-schema-validator = "^0.6.0" python = "^3.9.0" -jsonschema-path = "^0.3.1" +jsonschema-path = {version = "^0.4.0b1", allow-prereleases = true} lazy-object-proxy = "^1.7.1" [tool.poetry.extras]