Skip to content

Commit

Permalink
osbuild: experimentally switch to fastjsonschema
Browse files Browse the repository at this point in the history
Just a quick draft to see what it would take to move to fastjson
schema.
  • Loading branch information
mvo5 committed Sep 19, 2024
1 parent ed33869 commit b36d4c9
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 32 deletions.
32 changes: 17 additions & 15 deletions osbuild/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from collections import deque
from typing import Any, Deque, Dict, List, Optional, Sequence, Set, Tuple, Union

import jsonschema
import fastjsonschema

from .util import osrelease

Expand All @@ -55,8 +55,8 @@ def __init__(self, message: str):

@classmethod
def from_exception(cls, ex):
err = cls(ex.message)
err.path = ex.absolute_path
err = cls(str(ex))
#err.path = ex.absolute_path
return err

@property
Expand Down Expand Up @@ -217,9 +217,11 @@ class Schema:
"""

def __init__(self, schema: Optional[Dict], name: Optional[str] = None):
if schema:
schema["schema"] = "http://json-schema.org/draft-04/schema"
self.data = schema
self.name = name
self._validator: Optional[jsonschema.Draft4Validator] = None
self._validator: Optional[fastjsonschema.CodeGeneratorDraft04] = None

def check(self) -> ValidationResult:
"""Validate the `schema` data itself"""
Expand All @@ -243,10 +245,8 @@ def check(self) -> ValidationResult:
return res

try:
Validator = jsonschema.Draft4Validator
Validator.check_schema(self.data)
self._validator = Validator(self.data)
except jsonschema.exceptions.SchemaError as err:
self._validator = fastjsonschema.compile(self.data)
except fastjsonschema.JsonSchemaDefinitionException as err:
res += ValidationError.from_exception(err)

return res
Expand All @@ -266,8 +266,10 @@ def validate(self, target) -> ValidationResult:
if not self._validator:
raise RuntimeError("Trying to validate without validator.")

for error in self._validator.iter_errors(target):
res += ValidationError.from_exception(error)
try:
self._validator(target)
except fastjsonschema.JsonSchemaException as e:
res += ValidationError.from_exception(e)

return res

Expand All @@ -278,11 +280,11 @@ def __bool__(self):
META_JSON_SCHEMA = {
"type": "object",
"additionalProperties": False,
"propertyNames": {
"not": {
"const": "description",
},
},
#"propertyNames": {
# "not": {
# "const": "description",
# },
#},
"required": ["summary", "description"],
"anyOf": [
{
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
jsonschema
fastjsonschema
pytest
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
],
license='Apache-2.0',
install_requires=[
"jsonschema",
"fastjsonschema",
],
entry_points={
"console_scripts": [
Expand Down
8 changes: 4 additions & 4 deletions test/mod/test_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,20 +323,20 @@ def test_load_from_json_prefered(tmp_path):
(
# no description
{"summary": "some", "schema": {}},
"'description' is a required property",
"data must contain ['description'] properties",
), (
# no summary
{"description": ["yes"], "schema": {}},
"'summary' is a required property",
"data must contain ['summary'] properties",
), (
# schema{,_2} missing
{"summary": "some", "description": ["many", "strings"]},
" is not valid",
"data cannot be validated by any definition"
), (
# capabilities of wrong type
{"summary": "some", "description": ["many", "strings"], "schema": {},
"capabilities": [1, "cap1"]},
" is not of type 'string'",
" must be string"
),
])
def test_meta_json_validation_schema(test_input, expected_err):
Expand Down
8 changes: 3 additions & 5 deletions test/mod/test_util_sbom_spdx2_model.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
from datetime import datetime

import jsonschema
import fastjsonschema
import pytest

from osbuild.util.sbom.spdx2.model import (
Expand Down Expand Up @@ -474,7 +474,5 @@ def test_document_to_dict(test_case):
with open(spdx_2_3_1_schema_file, encoding="utf-8") as f:
spdx_schema = json.load(f)

validator = jsonschema.Draft4Validator
validator.check_schema(spdx_schema)
spdx_validator = validator(spdx_schema)
spdx_validator.validate(d.to_dict())
spdx_validator = fastjsonschema.compile(spdx_schema)
spdx_validator(d.to_dict())
8 changes: 3 additions & 5 deletions tools/test/test_depsolve.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from tempfile import TemporaryDirectory
from typing import Tuple

import jsonschema
import fastjsonschema
import pytest

REPO_PATHS = [
Expand Down Expand Up @@ -1305,10 +1305,8 @@ def test_depsolve(tmp_path, repo_servers, dnf_config, detect_fn, with_sbom, test
spdx_2_3_1_schema_file = './test/data/spdx/spdx-schema-v2.3.1.json'
with open(spdx_2_3_1_schema_file, encoding="utf-8") as f:
spdx_schema = json.load(f)
validator = jsonschema.Draft4Validator
validator.check_schema(spdx_schema)
spdx_validator = validator(spdx_schema)
spdx_validator.validate(res["sbom"])
spdx_validator = fastjsonschema.compile(spdx_schema)
spdx_validator(res["sbom"])

assert {pkg["name"] for pkg in res["sbom"]["packages"]} == test_case["results"]["packages"]
else:
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ description = "run osbuild unit tests"
deps =
pytest
pytest-xdist
jsonschema
fastjsonschema
mako
iniparse
pyyaml
Expand Down

0 comments on commit b36d4c9

Please sign in to comment.