diff options
author | Wojtek Kosior <koszko@koszko.org> | 2022-06-15 11:09:58 +0200 |
---|---|---|
committer | Wojtek Kosior <koszko@koszko.org> | 2022-06-15 11:09:58 +0200 |
commit | 22c722bf59e59246f47491c7229b17f9ef783614 (patch) | |
tree | bdcfbfae93f5e54d9b2b39465945419406b5e96a /src/hydrilla/util | |
parent | 6bc04f8097e44e55cbf543d811ccd90671faedbc (diff) | |
download | hydrilla-builder-upstream/1.1_beta1.tar.gz hydrilla-builder-upstream/1.1_beta1.zip |
New upstream version 1.1~beta1upstream/1.1_beta1debian-upstream
Diffstat (limited to 'src/hydrilla/util')
-rw-r--r-- | src/hydrilla/util/__init__.py | 3 | ||||
-rw-r--r-- | src/hydrilla/util/_util.py | 87 |
2 files changed, 74 insertions, 16 deletions
diff --git a/src/hydrilla/util/__init__.py b/src/hydrilla/util/__init__.py index fadb81c..4746fab 100644 --- a/src/hydrilla/util/__init__.py +++ b/src/hydrilla/util/__init__.py @@ -5,4 +5,5 @@ # Available under the terms of Creative Commons Zero v1.0 Universal. from ._util import strip_json_comments, normalize_version, parse_version, \ - version_string, validator_for, translation + version_string, validator_for, load_instance_from_file, translation, \ + UnknownSchemaError diff --git a/src/hydrilla/util/_util.py b/src/hydrilla/util/_util.py index 778e78f..de7435d 100644 --- a/src/hydrilla/util/_util.py +++ b/src/hydrilla/util/_util.py @@ -39,6 +39,13 @@ from jsonschema import RefResolver, Draft7Validator here = Path(__file__).resolve().parent +class UnknownSchemaError(Exception): + """ + Exception used to record problems with JSON documents for which not even + the appropriate validation schema could be determined. + """ + pass + _strip_comment_re = re.compile(r''' ^ # match from the beginning of each line ( # catch the part before '//' comment @@ -110,28 +117,78 @@ 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<name_base>[^/]*) +- +(?P<ver> + (?P<major>[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 path in (here.parent / 'schemas').glob('*-1.0.1.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] -resolver = RefResolver( - base_uri=f'file://{str(common_schema_path)}', - referrer=f'https://hydrilla.koszko.org/{common_schema_filename}', - store=schemas -) + if path not in schemas: + schemas[path] = json.loads(path.read_text()) + + return schemas[path] + +def validator_for(schema: Union[str, dict]) -> Draft7Validator: + """ + Prepare a validator for the provided schema. + + Other schemas under '../schemas' can be referenced. + """ + if isinstance(schema, str): + schema = _get_schema(schema) + + resolver = RefResolver( + base_uri=schema['$id'], + referrer=schema, + handlers={'https': _get_schema} + ) + + return Draft7Validator(schema, resolver=resolver) -def validator_for(schema_filename: str) -> Draft7Validator: +def load_instance_from_file(path: Path) -> tuple[dict, Optional[int]]: """ - Prepare a validator for one of the schemas in '../schemas'. + Open a file and load its contents as a JSON document (with additional + '//' comments support). Then parse its "$schema" property (if present) + and return a tuple of the document instance and the major number of + schema version. - This function is not thread-safe. + If no schema version number can be extracted, None is used instead. """ - return Draft7Validator(resolver.resolve(schema_filename)[1], - resolver=resolver) + instance = json.loads(strip_json_comments(path.read_text())) + major = None + + if type(instance) is dict and type(instance.get('$schema')) is str: + match = _schema_name_re.search(instance.get('$schema')) + major = match and int(match.group('major')) + + return instance, major def translation(localedir: Union[Path, str], lang: Optional[str]=None) \ -> gettext.GNUTranslations: |