Skip to content

Commit 1393ec9

Browse files
authored
[ISSUE-156] - Add support for jsonschema version ^4.18 (networktocode#157)
* Add support for jsonschema version ^4.18 * Remove python version3.7 checks from CI.
1 parent 022a7e7 commit 1393ec9

File tree

10 files changed

+744
-464
lines changed

10 files changed

+744
-464
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ jobs:
7575
strategy:
7676
fail-fast: true
7777
matrix:
78-
python-version: ["3.7", "3.8", "3.9", "3.10"]
78+
python-version: ["3.8", "3.9", "3.10"]
7979
ansible-core-version: ["2.11.7"]
8080
runs-on: "ubuntu-20.04"
8181
env:
@@ -117,7 +117,7 @@ jobs:
117117
strategy:
118118
fail-fast: true
119119
matrix:
120-
python-version: ["3.7"]
120+
python-version: ["3.8"]
121121
ansible-core-version: ["2.11.7"]
122122
env:
123123
PYTHON_VER: "${{ matrix.python-version }}"
@@ -159,7 +159,7 @@ jobs:
159159
strategy:
160160
fail-fast: true
161161
matrix:
162-
python-version: ["3.7", "3.8", "3.9", "3.10"]
162+
python-version: ["3.8", "3.9", "3.10"]
163163
ansible-core-version: ["2.11.7"]
164164
runs-on: "ubuntu-20.04"
165165
env:

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## v1.2.2
4+
5+
- #156 Add support for jsonschema 4.18
6+
- Remove support for python version 3.7
7+
38
## v1.2.1
49

510
### Changes

poetry.lock

Lines changed: 537 additions & 442 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "schema-enforcer"
3-
version = "1.2.0"
3+
version = "1.2.2"
44
description = "Tool/Framework for testing structured data against schema definitions"
55
authors = ["Network to Code, LLC <info@networktocode.com>"]
66
license = "Apache-2.0"
@@ -14,7 +14,7 @@ include = [
1414
]
1515

1616
[tool.poetry.dependencies]
17-
python = "^3.7"
17+
python = "^3.8"
1818
click = "^7.1 || ^8.0"
1919
termcolor = "^1.1"
2020
toml = "^0.10"
@@ -72,7 +72,6 @@ no-docstring-rgx="^(_|test_)"
7272
# Pylint and Black disagree about how to format multi-line arrays; Black wins.
7373
disable = """,
7474
line-too-long,
75-
bad-continuation,
7675
"""
7776

7877
[tool.pylint.miscellaneous]
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$id": "http://json-schema.org/draft-07/schema#",
4+
"title": "Core schema meta-schema",
5+
"definitions": {
6+
"schemaArray": {
7+
"type": "array",
8+
"minItems": 1,
9+
"items": { "$ref": "#" }
10+
},
11+
"nonNegativeInteger": {
12+
"type": "integer",
13+
"minimum": 0
14+
},
15+
"nonNegativeIntegerDefault0": {
16+
"allOf": [
17+
{ "$ref": "#/definitions/nonNegativeInteger" },
18+
{ "default": 0 }
19+
]
20+
},
21+
"simpleTypes": {
22+
"enum": [
23+
"array",
24+
"boolean",
25+
"integer",
26+
"null",
27+
"number",
28+
"object",
29+
"string"
30+
]
31+
},
32+
"stringArray": {
33+
"type": "array",
34+
"items": { "type": "string" },
35+
"uniqueItems": true,
36+
"default": []
37+
}
38+
},
39+
"type": ["object", "boolean"],
40+
"properties": {
41+
"$id": {
42+
"type": "string",
43+
"format": "uri-reference"
44+
},
45+
"$schema": {
46+
"type": "string",
47+
"format": "uri"
48+
},
49+
"$ref": {
50+
"type": "string",
51+
"format": "uri-reference"
52+
},
53+
"$comment": {
54+
"type": "string"
55+
},
56+
"title": {
57+
"type": "string"
58+
},
59+
"description": {
60+
"type": "string"
61+
},
62+
"default": true,
63+
"readOnly": {
64+
"type": "boolean",
65+
"default": false
66+
},
67+
"writeOnly": {
68+
"type": "boolean",
69+
"default": false
70+
},
71+
"examples": {
72+
"type": "array",
73+
"items": true
74+
},
75+
"multipleOf": {
76+
"type": "number",
77+
"exclusiveMinimum": 0
78+
},
79+
"maximum": {
80+
"type": "number"
81+
},
82+
"exclusiveMaximum": {
83+
"type": "number"
84+
},
85+
"minimum": {
86+
"type": "number"
87+
},
88+
"exclusiveMinimum": {
89+
"type": "number"
90+
},
91+
"maxLength": { "$ref": "#/definitions/nonNegativeInteger" },
92+
"minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" },
93+
"pattern": {
94+
"type": "string",
95+
"format": "regex"
96+
},
97+
"additionalItems": { "$ref": "#" },
98+
"items": {
99+
"anyOf": [
100+
{ "$ref": "#" },
101+
{ "$ref": "#/definitions/schemaArray" }
102+
],
103+
"default": true
104+
},
105+
"maxItems": { "$ref": "#/definitions/nonNegativeInteger" },
106+
"minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" },
107+
"uniqueItems": {
108+
"type": "boolean",
109+
"default": false
110+
},
111+
"contains": { "$ref": "#" },
112+
"maxProperties": { "$ref": "#/definitions/nonNegativeInteger" },
113+
"minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" },
114+
"required": { "$ref": "#/definitions/stringArray" },
115+
"additionalProperties": { "$ref": "#" },
116+
"definitions": {
117+
"type": "object",
118+
"additionalProperties": { "$ref": "#" },
119+
"default": {}
120+
},
121+
"properties": {
122+
"type": "object",
123+
"additionalProperties": { "$ref": "#" },
124+
"default": {}
125+
},
126+
"patternProperties": {
127+
"type": "object",
128+
"additionalProperties": { "$ref": "#" },
129+
"propertyNames": { "format": "regex" },
130+
"default": {}
131+
},
132+
"dependencies": {
133+
"type": "object",
134+
"additionalProperties": {
135+
"anyOf": [
136+
{ "$ref": "#" },
137+
{ "$ref": "#/definitions/stringArray" }
138+
]
139+
}
140+
},
141+
"propertyNames": { "$ref": "#" },
142+
"const": true,
143+
"enum": {
144+
"type": "array",
145+
"items": true,
146+
"minItems": 1,
147+
"uniqueItems": true
148+
},
149+
"type": {
150+
"anyOf": [
151+
{ "$ref": "#/definitions/simpleTypes" },
152+
{
153+
"type": "array",
154+
"items": { "$ref": "#/definitions/simpleTypes" },
155+
"minItems": 1,
156+
"uniqueItems": true
157+
}
158+
]
159+
},
160+
"format": { "type": "string" },
161+
"contentMediaType": { "type": "string" },
162+
"contentEncoding": { "type": "string" },
163+
"if": { "$ref": "#" },
164+
"then": { "$ref": "#" },
165+
"else": { "$ref": "#" },
166+
"allOf": { "$ref": "#/definitions/schemaArray" },
167+
"anyOf": { "$ref": "#/definitions/schemaArray" },
168+
"oneOf": { "$ref": "#/definitions/schemaArray" },
169+
"not": { "$ref": "#" }
170+
},
171+
"default": true
172+
}

schema_enforcer/schemas/jsonschema.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
"""class to manage jsonschema type schema."""
22
import copy
3-
import pkgutil
43
import json
4+
import os
5+
from functools import cached_property
56

6-
from jsonschema import Draft7Validator, draft7_format_checker # pylint: disable=import-self
7+
from jsonschema import Draft7Validator # pylint: disable=import-self
78
from schema_enforcer.schemas.validator import BaseValidation
89
from schema_enforcer.validation import ValidationResult, RESULT_FAIL, RESULT_PASS
910

10-
# TODO do we need to catch a possible exception here ?
11-
v7data = pkgutil.get_data("jsonschema", "schemas/draft7.json")
12-
v7schema = json.loads(v7data.decode("utf-8"))
13-
1411

1512
class JsonSchema(BaseValidation): # pylint: disable=too-many-instance-attributes
1613
"""class to manage jsonschema type schemas."""
@@ -33,7 +30,16 @@ def __init__(self, schema, filename, root):
3330
self.top_level_properties = set(self.data.get("properties"))
3431
self.validator = None
3532
self.strict_validator = None
36-
self.format_checker = draft7_format_checker
33+
self.format_checker = Draft7Validator.FORMAT_CHECKER
34+
35+
@cached_property
36+
def v7_schema(self):
37+
"""Draft7 Schema."""
38+
local_dirname = os.path.dirname(os.path.abspath(__file__))
39+
with open(os.path.join(local_dirname, "draft7_schema.json"), encoding="utf-8") as fhd:
40+
v7_schema = json.loads(fhd.read())
41+
42+
return v7_schema
3743

3844
def get_id(self):
3945
"""Return the unique ID of the schema."""
@@ -131,7 +137,7 @@ def check_if_valid(self):
131137
Returns:
132138
List[ValidationResult]: A list of validation result objects.
133139
"""
134-
validator = Draft7Validator(v7schema, format_checker=self.format_checker)
140+
validator = Draft7Validator(self.v7_schema, format_checker=self.format_checker)
135141

136142
results = []
137143
has_error = False

schema_enforcer/schemas/manager.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def __init__(self, config):
4848
validators = load_validators(config.validator_directory)
4949
self.schemas.update(validators)
5050

51-
def create_schema_from_file(self, root, filename): # pylint: disable=no-self-use
51+
def create_schema_from_file(self, root, filename):
5252
"""Create a new JsonSchema object for a given file.
5353
5454
Load the content from disk and resolve all JSONRef within the schema file.
@@ -226,9 +226,13 @@ def test_schema_invalid(self, schema_id): # pylint: disable=too-many-locals
226226
results_sorted = sorted(tmp_results, key=lambda i: i.get("message", ""))
227227
expected_results_sorted = sorted(expected_results, key=lambda i: i.get("message", ""))
228228

229-
params = dict(
230-
schema_id=schema_id, instance_type="TEST", instance_name=test_dir, instance_location=invalid_test_dir
231-
)
229+
params = {
230+
"schema_id": schema_id,
231+
"instance_type": "TEST",
232+
"instance_name": test_dir,
233+
"instance_location": invalid_test_dir,
234+
}
235+
232236
if results_sorted != expected_results_sorted:
233237
params["result"] = RESULT_FAIL
234238
params[

schema_enforcer/utils.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from jsonschema import ( # pylint: disable=no-name-in-module
1111
RefResolver,
1212
Draft7Validator,
13-
draft7_format_checker,
1413
)
1514

1615
from termcolor import colored
@@ -167,7 +166,7 @@ def load_schema_from_json_file(schema_root_dir, schema_filepath):
167166
# these references must match the full filenames currently, unless we modify the RefResolver to handle other cases.
168167
validator = Draft7Validator(
169168
schema_definition,
170-
format_checker=draft7_format_checker,
169+
format_checker=Draft7Validator.FORMAT_CHECKER,
171170
resolver=RefResolver(base_uri=base_uri, referrer=schema_definition),
172171
)
173172
return validator

schema_enforcer/validation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class ValidationResult(BaseModel):
2828
message: Optional[str]
2929

3030
@validator("result")
31-
def result_must_be_pass_or_fail(cls, var): # pylint: disable=no-self-argument, no-self-use
31+
def result_must_be_pass_or_fail(cls, var): # pylint: disable=no-self-argument
3232
"""Validate that result either PASS or FAIL."""
3333
if var.upper() not in [RESULT_PASS, RESULT_FAIL]:
3434
raise ValueError("must be either PASS or FAIL")

tasks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def is_truthy(arg):
3636
TOOL_CONFIG = PYPROJECT_CONFIG["tool"]["poetry"]
3737

3838
# Can be set to a separate Python version to be used for launching or building image
39-
PYTHON_VER = os.getenv("PYTHON_VER", "3.7")
39+
PYTHON_VER = os.getenv("PYTHON_VER", "3.8")
4040
# Can be set to a separate ANsible version to be used for launching or building image
4141
ANSIBLE_VER = os.getenv("ANSIBLE_VER", "2.11.7")
4242
ANSIBLE_PACKAGE = os.getenv("ANSIBLE_PACKAGE", "ansible-core")

0 commit comments

Comments
 (0)