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 000000000..b4cd1776b --- /dev/null +++ b/lib/python/qmk/json_schema.py | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | """Functions that help us generate and use info.json files. | ||
| 2 | """ | ||
| 3 | import json | ||
| 4 | from collections.abc import Mapping | ||
| 5 | from pathlib import Path | ||
| 6 | |||
| 7 | import hjson | ||
| 8 | import jsonschema | ||
| 9 | from milc import cli | ||
| 10 | |||
| 11 | |||
| 12 | def json_load(json_file): | ||
| 13 | """Load a json file from disk. | ||
| 14 | |||
| 15 | Note: file must be a Path object. | ||
| 16 | """ | ||
| 17 | try: | ||
| 18 | return hjson.load(json_file.open()) | ||
| 19 | |||
| 20 | except json.decoder.JSONDecodeError as e: | ||
| 21 | cli.log.error('Invalid JSON encountered attempting to load {fg_cyan}%s{fg_reset}:\n\t{fg_red}%s', json_file, e) | ||
| 22 | exit(1) | ||
| 23 | |||
| 24 | |||
| 25 | def load_jsonschema(schema_name): | ||
| 26 | """Read a jsonschema file from disk. | ||
| 27 | |||
| 28 | FIXME(skullydazed/anyone): Refactor to make this a public function. | ||
| 29 | """ | ||
| 30 | schema_path = Path(f'data/schemas/{schema_name}.jsonschema') | ||
| 31 | |||
| 32 | if not schema_path.exists(): | ||
| 33 | schema_path = Path('data/schemas/false.jsonschema') | ||
| 34 | |||
| 35 | return json_load(schema_path) | ||
| 36 | |||
| 37 | |||
| 38 | def keyboard_validate(data): | ||
| 39 | """Validates data against the keyboard jsonschema. | ||
| 40 | """ | ||
| 41 | schema = load_jsonschema('keyboard') | ||
| 42 | validator = jsonschema.Draft7Validator(schema).validate | ||
| 43 | |||
| 44 | return validator(data) | ||
| 45 | |||
| 46 | |||
| 47 | def keyboard_api_validate(data): | ||
| 48 | """Validates data against the api_keyboard jsonschema. | ||
| 49 | """ | ||
| 50 | base = load_jsonschema('keyboard') | ||
| 51 | relative = load_jsonschema('api_keyboard') | ||
| 52 | resolver = jsonschema.RefResolver.from_schema(base) | ||
| 53 | validator = jsonschema.Draft7Validator(relative, resolver=resolver).validate | ||
| 54 | |||
| 55 | return validator(data) | ||
| 56 | |||
| 57 | |||
| 58 | def deep_update(origdict, newdict): | ||
| 59 | """Update a dictionary in place, recursing to do a deep copy. | ||
| 60 | """ | ||
| 61 | for key, value in newdict.items(): | ||
| 62 | if isinstance(value, Mapping): | ||
| 63 | origdict[key] = deep_update(origdict.get(key, {}), value) | ||
| 64 | |||
| 65 | else: | ||
| 66 | origdict[key] = value | ||
| 67 | |||
| 68 | return origdict | ||
