From 73a443f518be29a50981e7e137e2b4c2c37552dd Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 31 May 2022 16:52:14 +0200 Subject: improve loading of schema files --- src/hydrilla/builder/build.py | 13 +++------- src/hydrilla/util/_util.py | 58 ++++++++++++++++++++++++++++--------------- tests/test_build.py | 4 +-- 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/hydrilla/builder/build.py b/src/hydrilla/builder/build.py index 33838f3..a3c55a7 100644 --- a/src/hydrilla/builder/build.py +++ b/src/hydrilla/builder/build.py @@ -51,15 +51,6 @@ here = Path(__file__).resolve().parent _ = util.translation(here / 'locales').gettext -def index_validator(major_schema_version): - """ - Create an index.json schema validator specific to the requested schema - version series. - """ - exact_version = {1: '1.0.1', 2: '2'}[major_schema_version] - - return util.validator_for(f'package_source-{exact_version}.schema.json') - schemas_root = 'https://hydrilla.koszko.org/schemas' generated_by = { @@ -365,7 +356,9 @@ class Build: files and computed definitions of the source package and items defined in it. """ - index_validator(major_schema_version).validate(index_obj) + schema_name = f'package_source-{major_schema_version}.schema.json'; + + util.validator_for(schema_name).validate(index_obj) match = re.match(r'.*-((([1-9][0-9]*|0)\.)+)schema\.json$', index_obj['$schema']) diff --git a/src/hydrilla/util/_util.py b/src/hydrilla/util/_util.py index 815b7fd..de7435d 100644 --- a/src/hydrilla/util/_util.py +++ b/src/hydrilla/util/_util.py @@ -117,14 +117,43 @@ def version_string(ver: list[int], rev: Optional[int]=None) -> str: """ return '.'.join([str(n) for n in ver]) + ('' if rev is None else f'-{rev}') +_schema_name_re = re.compile(r''' +(?P[^/]*) +- +(?P + (?P[1-9][0-9]*) + (?: # this repeated group matches the remaining version numbers + \. + (?:[1-9][0-9]*|0) + )* +) +\.schema\.json +$ +''', re.VERBOSE) + +schema_paths = {} +for path in (here.parent / 'schemas').rglob('*.schema.json'): + match = _schema_name_re.search(path.name) + schema_name_base = match.group('name_base') + schema_ver_list = match.group('ver').split('.') + + for i in range(len(schema_ver_list)): + schema_ver = '.'.join(schema_ver_list[:i+1]) + schema_paths[f'{schema_name_base}-{schema_ver}.schema.json'] = path + +for name, path in [*schema_paths.items()]: + schema_paths[f'https://hydrilla.koszko.org/schemas/{name}'] = path + schemas = {} -for series_dir in (here.parent / 'schemas').glob('*.x'): - for path in series_dir.glob("*.schema.json"): - schema = json.loads(path.read_text()) - schemas[schema['$id']] = schema -common_schema_filename = 'common_definitions-1.schema.json' -common_schema_path = here.parent / "schemas" / common_schema_filename +def _get_schema(schema_name: str) -> dict: + """Return loaded JSON of the requested schema. Cache results.""" + path = schema_paths[schema_name] + + if path not in schemas: + schemas[path] = json.loads(path.read_text()) + + return schemas[path] def validator_for(schema: Union[str, dict]) -> Draft7Validator: """ @@ -133,27 +162,16 @@ def validator_for(schema: Union[str, dict]) -> Draft7Validator: Other schemas under '../schemas' can be referenced. """ if isinstance(schema, str): - schema = schemas[f'https://hydrilla.koszko.org/schemas/{schema}'] + schema = _get_schema(schema) resolver = RefResolver( base_uri=schema['$id'], referrer=schema, - handlers={'https': lambda uri: schemas[uri]} + handlers={'https': _get_schema} ) return Draft7Validator(schema, resolver=resolver) -_major_version_re = re.compile(r''' -- -(?P[1-9][0-9]*) -(?: # this repeated group matches the remaining version numbers - \. - (?:[1-9][0-9]*|0) -)* -\.schema\.json -$ -''', re.VERBOSE) - def load_instance_from_file(path: Path) -> tuple[dict, Optional[int]]: """ Open a file and load its contents as a JSON document (with additional @@ -167,7 +185,7 @@ def load_instance_from_file(path: Path) -> tuple[dict, Optional[int]]: major = None if type(instance) is dict and type(instance.get('$schema')) is str: - match = _major_version_re.search(instance.get('$schema')) + match = _schema_name_re.search(instance.get('$schema')) major = match and int(match.group('major')) return instance, major diff --git a/tests/test_build.py b/tests/test_build.py index c2d8ced..7fedbd5 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -20,7 +20,7 @@ from contextlib import contextmanager from jsonschema import ValidationError from hydrilla import util as hydrilla_util -from hydrilla.util._util import _major_version_re +from hydrilla.util._util import _schema_name_re from hydrilla.builder import build, _version, local_apt from hydrilla.builder.common_errors import * @@ -595,7 +595,7 @@ def try_validate(as_what, instance): Select the right JSON schema. Return without errors only if the instance validates against it. """ - major = _major_version_re.search(instance['$schema']).group('major') + major = _schema_name_re.search(instance['$schema']).group('major') exact_schema_version = {'1': '1.0.1', '2': '2'}[major] schema_filename = f'{as_what}-{exact_schema_version}.schema.json' hydrilla_util.validator_for(schema_filename).validate(instance) -- cgit v1.2.3