aboutsummaryrefslogtreecommitdiff
path: root/src/hydrilla/util
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2022-06-15 11:09:58 +0200
committerWojtek Kosior <koszko@koszko.org>2022-06-15 11:09:58 +0200
commit22c722bf59e59246f47491c7229b17f9ef783614 (patch)
treebdcfbfae93f5e54d9b2b39465945419406b5e96a /src/hydrilla/util
parent6bc04f8097e44e55cbf543d811ccd90671faedbc (diff)
downloadhydrilla-builder-debian-upstream.tar.gz
hydrilla-builder-debian-upstream.zip
New upstream version 1.1~beta1upstream/1.1_beta1debian-upstream
Diffstat (limited to 'src/hydrilla/util')
-rw-r--r--src/hydrilla/util/__init__.py3
-rw-r--r--src/hydrilla/util/_util.py87
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: