aboutsummaryrefslogtreecommitdiff
path: root/src/hydrilla/util/_util.py
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2022-05-27 19:43:51 +0200
committerWojtek Kosior <koszko@koszko.org>2022-05-31 15:17:11 +0200
commitf42f5c1957e9c6ff8a61ef295b63dccead9b0ae8 (patch)
treeefc3d1eb06f6cabd95635d88f957537312985a2a /src/hydrilla/util/_util.py
parent496d90f70a58c0040f8493aa8a5e4e2f106bfac7 (diff)
downloadhydrilla-builder-f42f5c1957e9c6ff8a61ef295b63dccead9b0ae8.tar.gz
hydrilla-builder-f42f5c1957e9c6ff8a61ef295b63dccead9b0ae8.zip
incorporate version 2 of Hydrilla JSON schemas
Diffstat (limited to 'src/hydrilla/util/_util.py')
-rw-r--r--src/hydrilla/util/_util.py65
1 files changed, 52 insertions, 13 deletions
diff --git a/src/hydrilla/util/_util.py b/src/hydrilla/util/_util.py
index 778e78f..815b7fd 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
@@ -111,27 +118,59 @@ 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}')
schemas = {}
-for path in (here.parent / 'schemas').glob('*-1.0.1.schema.json'):
- schema = json.loads(path.read_text())
- schemas[schema['$id']] = schema
+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
-resolver = RefResolver(
- base_uri=f'file://{str(common_schema_path)}',
- referrer=f'https://hydrilla.koszko.org/{common_schema_filename}',
- store=schemas
-)
+def validator_for(schema: Union[str, dict]) -> Draft7Validator:
+ """
+ Prepare a validator for the provided schema.
-def validator_for(schema_filename: str) -> Draft7Validator:
+ Other schemas under '../schemas' can be referenced.
"""
- Prepare a validator for one of the schemas in '../schemas'.
+ if isinstance(schema, str):
+ schema = schemas[f'https://hydrilla.koszko.org/schemas/{schema}']
+
+ resolver = RefResolver(
+ base_uri=schema['$id'],
+ referrer=schema,
+ handlers={'https': lambda uri: schemas[uri]}
+ )
+
+ return Draft7Validator(schema, resolver=resolver)
+
+_major_version_re = re.compile(r'''
+-
+(?P<major>[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
+ '//' 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 = _major_version_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: