Skip to content

Commit 043c02f

Browse files
rory-xuRory Xu
andauthored
Upgrade jsonschema to 4.25 and additional fixes to pass pre-commit (#1111)
Co-authored-by: Rory Xu <[email protected]>
1 parent 605c4c1 commit 043c02f

File tree

7 files changed

+71
-33
lines changed

7 files changed

+71
-33
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ repos:
5555
hooks:
5656
- id: bandit
5757
files: "^src/"
58+
additional_dependencies: [pbr]
5859
# have to skip B101, contract tests use it and there's no way to skip for specific files
5960
args: ["--skip", "B101"]
6061
- repo: local

setup.cfg

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ include_trailing_comma = true
2929
combine_as_imports = True
3030
force_grid_wrap = 0
3131
known_first_party = rpdk
32-
known_third_party = boto3,botocore,cfn_tools,cfnlint,colorama,docker,hypothesis,jinja2,jsonpatch,jsonschema,nested_lookup,ordered_set,pkg_resources,pytest,pytest_localserver,requests,setuptools,yaml
32+
known_third_party = boto3,botocore,cfn_tools,cfnlint,colorama,docker,hypothesis,jinja2,jsonpatch,jsonschema,nested_lookup,ordered_set,pkg_resources,pytest,pytest_localserver,referencing,requests,setuptools,yaml
3333

3434
[tool:pytest]
3535
# can't do anything about 3rd part modules, so don't spam us
3636
filterwarnings =
3737
ignore::DeprecationWarning:botocore
3838
ignore::DeprecationWarning:werkzeug
3939
ignore::DeprecationWarning:yaml
40+
addopts = --doctest-modules

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def find_version(*file_paths):
4242
"Jinja2>=3.1.2",
4343
"markupsafe>=2.1.0",
4444
"jsonpatch",
45-
"jsonschema>=3.0.0,<=4.17.3",
45+
"jsonschema<=4.25",
4646
"pytest>=4.5.0",
4747
"pytest-random-order>=1.0.4",
4848
"pytest-localserver>=0.5.0",

src/rpdk/core/contract/resource_generator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
text,
1818
tuples,
1919
)
20-
from jsonschema import RefResolver
20+
from jsonschema import RefResolver # pylint: disable=no-name-in-module
2121

2222
from ..jsonutils.utils import schema_merge
2323

src/rpdk/core/data_loaders.py

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@
77
from pathlib import Path
88

99
import pkg_resources
10+
import referencing
11+
import referencing.exceptions
1012
import yaml
11-
from jsonschema import Draft7Validator, RefResolver
12-
from jsonschema.exceptions import RefResolutionError, ValidationError
13+
from jsonschema import Draft7Validator
14+
from jsonschema.exceptions import ( # pylint: disable=no-name-in-module
15+
RefResolutionError,
16+
ValidationError,
17+
)
1318
from nested_lookup import nested_lookup
1419

1520
from .exceptions import InternalError, SpecValidationError
@@ -56,30 +61,52 @@ def copy_resource(package_name, resource_name, out_path):
5661
shutil.copyfileobj(fsrc, fdst)
5762

5863

59-
def get_schema_store(schema_search_path):
60-
"""Load all the schemas in schema_search_path and return a dict"""
61-
schema_store = {}
64+
def get_schema_registry(schema_search_path):
65+
"""Load all the schemas in schema_search_path and return a registry"""
66+
schemas = {}
6267
schema_fnames = os.listdir(schema_search_path)
6368
for schema_fname in schema_fnames:
6469
schema_path = os.path.join(schema_search_path, schema_fname)
6570
if schema_path.endswith(".json"):
6671
with open(schema_path, "r", encoding="utf-8") as schema_f:
6772
schema = json.load(schema_f)
6873
if "$id" in schema:
69-
schema_store[schema["$id"]] = schema
70-
return schema_store
74+
schemas[schema["$id"]] = schema
75+
76+
# Add HTTPS version of JSON Schema for compatibility
77+
if "http://json-schema.org/draft-07/schema#" in schemas:
78+
schemas["https://json-schema.org/draft-07/schema#"] = schemas[
79+
"http://json-schema.org/draft-07/schema#"
80+
]
81+
82+
# Create resources with proper specification
83+
resources = []
84+
for uri, schema in schemas.items():
85+
try:
86+
resource = referencing.Resource.from_contents(
87+
schema, default_specification=referencing.jsonschema.DRAFT7
88+
)
89+
resources.append((uri, resource))
90+
except (
91+
ValueError,
92+
TypeError,
93+
KeyError,
94+
): # pylint: disable=broad-exception-caught
95+
# Fallback for schemas without proper $schema
96+
resource = referencing.Resource.from_contents(
97+
schema, default_specification=referencing.jsonschema.DRAFT7
98+
)
99+
resources.append((uri, resource))
100+
101+
return referencing.Registry().with_resources(resources)
71102

72103

73104
def make_validator(schema):
74105
schema_search_path = Path(os.path.dirname(os.path.realpath(__file__))).joinpath(
75106
"data/schema/"
76107
)
77-
resolver = RefResolver(
78-
base_uri=Draft7Validator.ID_OF(schema),
79-
store=get_schema_store(schema_search_path),
80-
referrer=schema,
81-
)
82-
return Draft7Validator(schema, resolver=resolver)
108+
registry = get_schema_registry(schema_search_path)
109+
return Draft7Validator(schema, registry=registry)
83110

84111

85112
def make_resource_validator():
@@ -379,7 +406,7 @@ def load_resource_spec(resource_spec_file): # pylint: disable=R # noqa: C901
379406
inliner = RefInliner(base_uri, resource_spec)
380407
try:
381408
inlined = inliner.inline()
382-
except RefResolutionError as e:
409+
except (RefResolutionError, referencing.exceptions.Unresolvable) as e:
383410
LOG.debug("Resource spec validation failed", exc_info=True)
384411
raise SpecValidationError(str(e)) from e
385412

@@ -444,7 +471,7 @@ def load_hook_spec(hook_spec_file): # pylint: disable=R # noqa: C901
444471
inliner = RefInliner(base_uri, hook_spec)
445472
try:
446473
inlined = inliner.inline()
447-
except RefResolutionError as e:
474+
except (RefResolutionError, referencing.exceptions.Unresolvable) as e:
448475
LOG.debug("Hook spec validation failed", exc_info=True)
449476
raise SpecValidationError(str(e)) from e
450477

src/rpdk/core/jsonutils/inliner.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import logging
22
from collections.abc import Iterable, Mapping
33

4-
from jsonschema import RefResolutionError, RefResolver
4+
from jsonschema import RefResolver # pylint: disable=no-name-in-module
5+
from jsonschema.exceptions import ( # pylint: disable=no-name-in-module
6+
RefResolutionError,
7+
)
58

69
from .renamer import RefRenamer
710
from .utils import BASE, rewrite_ref, traverse

tests/test_data_loaders.py

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@
1010

1111
import pytest
1212
import yaml
13-
from jsonschema.exceptions import RefResolutionError, ValidationError
13+
from jsonschema.exceptions import ( # pylint: disable=no-name-in-module
14+
RefResolutionError,
15+
ValidationError,
16+
)
1417
from pytest_localserver.http import Request, Response, WSGIServer
1518

1619
from rpdk.core.data_loaders import (
1720
STDIN_NAME,
1821
get_file_base_uri,
19-
get_schema_store,
22+
get_schema_registry,
2023
load_hook_spec,
2124
load_resource_spec,
2225
resource_json,
@@ -669,36 +672,39 @@ def test_resource_yaml():
669672
assert result == obj
670673

671674

672-
def test_get_schema_store_schemas_with_id():
673-
schema_store = get_schema_store(
675+
def test_get_schema_registry_schemas_with_id():
676+
schema_registry = get_schema_registry(
674677
BASEDIR.parent / "src" / "rpdk" / "core" / "data" / "schema"
675678
)
676-
assert len(schema_store) == 7
677-
assert "http://json-schema.org/draft-07/schema#" in schema_store
679+
assert len(schema_registry) == 8 # 7 original + HTTPS version of JSON Schema
680+
assert "http://json-schema.org/draft-07/schema#" in schema_registry
681+
assert (
682+
"https://json-schema.org/draft-07/schema#" in schema_registry
683+
) # HTTPS version
678684
assert (
679685
"https://schema.cloudformation.us-east-1.amazonaws.com/base.definition.schema.v1.json"
680-
in schema_store
686+
in schema_registry
681687
)
682688
assert (
683689
"https://schema.cloudformation.us-east-1.amazonaws.com/provider.configuration.definition.schema.v1.json"
684-
in schema_store
690+
in schema_registry
685691
)
686692
assert (
687693
"https://schema.cloudformation.us-east-1.amazonaws.com/provider.definition.schema.v1.json"
688-
in schema_store
694+
in schema_registry
689695
)
690696
assert (
691697
"https://schema.cloudformation.us-east-1.amazonaws.com/provider.definition.schema.hooks.v1.json"
692-
in schema_store
698+
in schema_registry
693699
)
694700
assert (
695701
"https://schema.cloudformation.us-east-1.amazonaws.com/provider.configuration.definition.schema.hooks.v1.json"
696-
in schema_store
702+
in schema_registry
697703
)
698704

699705

700-
def test_get_schema_store_schemas_with_out_id():
701-
schema_store = get_schema_store(
706+
def test_get_schema_registry_schemas_with_out_id():
707+
schema_registry = get_schema_registry(
702708
BASEDIR.parent / "src" / "rpdk" / "core" / "data" / "examples" / "resource"
703709
)
704-
assert len(schema_store) == 0
710+
assert len(schema_registry) == 0

0 commit comments

Comments
 (0)