diff options
Diffstat (limited to 'lib/python/qmk/json_schema.py')
| -rw-r--r-- | lib/python/qmk/json_schema.py | 68 | 
1 files changed, 68 insertions, 0 deletions
| diff --git a/lib/python/qmk/json_schema.py b/lib/python/qmk/json_schema.py new file mode 100644 index 0000000000..b4cd1776b2 --- /dev/null +++ b/lib/python/qmk/json_schema.py @@ -0,0 +1,68 @@ +"""Functions that help us generate and use info.json files. +""" +import json +from collections.abc import Mapping +from pathlib import Path + +import hjson +import jsonschema +from milc import cli + + +def json_load(json_file): +    """Load a json file from disk. + +    Note: file must be a Path object. +    """ +    try: +        return hjson.load(json_file.open()) + +    except json.decoder.JSONDecodeError as e: +        cli.log.error('Invalid JSON encountered attempting to load {fg_cyan}%s{fg_reset}:\n\t{fg_red}%s', json_file, e) +        exit(1) + + +def load_jsonschema(schema_name): +    """Read a jsonschema file from disk. + +    FIXME(skullydazed/anyone): Refactor to make this a public function. +    """ +    schema_path = Path(f'data/schemas/{schema_name}.jsonschema') + +    if not schema_path.exists(): +        schema_path = Path('data/schemas/false.jsonschema') + +    return json_load(schema_path) + + +def keyboard_validate(data): +    """Validates data against the keyboard jsonschema. +    """ +    schema = load_jsonschema('keyboard') +    validator = jsonschema.Draft7Validator(schema).validate + +    return validator(data) + + +def keyboard_api_validate(data): +    """Validates data against the api_keyboard jsonschema. +    """ +    base = load_jsonschema('keyboard') +    relative = load_jsonschema('api_keyboard') +    resolver = jsonschema.RefResolver.from_schema(base) +    validator = jsonschema.Draft7Validator(relative, resolver=resolver).validate + +    return validator(data) + + +def deep_update(origdict, newdict): +    """Update a dictionary in place, recursing to do a deep copy. +    """ +    for key, value in newdict.items(): +        if isinstance(value, Mapping): +            origdict[key] = deep_update(origdict.get(key, {}), value) + +        else: +            origdict[key] = value + +    return origdict | 
