json_schema.py 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  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. import hjson
  7. import jsonschema
  8. from milc import cli
  9. def json_load(json_file):
  10. """Load a json file from disk.
  11. Note: file must be a Path object.
  12. """
  13. try:
  14. return hjson.load(json_file.open(encoding='utf-8'))
  15. except (json.decoder.JSONDecodeError, hjson.HjsonDecodeError) as e:
  16. cli.log.error('Invalid JSON encountered attempting to load {fg_cyan}%s{fg_reset}:\n\t{fg_red}%s', json_file, e)
  17. exit(1)
  18. except Exception as e:
  19. cli.log.error('Unknown error attempting to load {fg_cyan}%s{fg_reset}:\n\t{fg_red}%s', json_file, e)
  20. exit(1)
  21. def load_jsonschema(schema_name):
  22. """Read a jsonschema file from disk.
  23. FIXME(skullydazed/anyone): Refactor to make this a public function.
  24. """
  25. schema_path = Path(f'data/schemas/{schema_name}.jsonschema')
  26. if not schema_path.exists():
  27. schema_path = Path('data/schemas/false.jsonschema')
  28. return json_load(schema_path)
  29. def keyboard_validate(data):
  30. """Validates data against the keyboard jsonschema.
  31. """
  32. schema = load_jsonschema('keyboard')
  33. validator = jsonschema.Draft7Validator(schema).validate
  34. return validator(data)
  35. def keyboard_api_validate(data):
  36. """Validates data against the api_keyboard jsonschema.
  37. """
  38. base = load_jsonschema('keyboard')
  39. relative = load_jsonschema('api_keyboard')
  40. resolver = jsonschema.RefResolver.from_schema(base)
  41. validator = jsonschema.Draft7Validator(relative, resolver=resolver).validate
  42. return validator(data)
  43. def deep_update(origdict, newdict):
  44. """Update a dictionary in place, recursing to do a deep copy.
  45. """
  46. for key, value in newdict.items():
  47. if isinstance(value, Mapping):
  48. origdict[key] = deep_update(origdict.get(key, {}), value)
  49. else:
  50. origdict[key] = value
  51. return origdict