You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

55 lines
2.1 KiB

  1. """Functions that help us generate and use info.json files.
  2. """
  3. from functools import lru_cache
  4. from pathlib import Path
  5. import jsonschema
  6. from milc import cli
  7. from qmk.json_schema import keyboard_api_validate
  8. from qmk.keymap import list_keymaps
  9. from qmk.metadata import basic_info_json, info_log_error
  10. def _valid_community_layout(layout):
  11. """Validate that a declared community list exists
  12. """
  13. return (Path('layouts/default') / layout).exists()
  14. @lru_cache(maxsize=None)
  15. def info_json(keyboard):
  16. """Generate the info.json data for a specific keyboard.
  17. """
  18. info_data = basic_info_json(keyboard)
  19. # Populate the list of JSON keymaps
  20. for keymap in list_keymaps(keyboard, c=False, fullpath=True):
  21. info_data['keymaps'][keymap.name] = {'url': f'https://raw.githubusercontent.com/qmk/qmk_firmware/master/{keymap}/keymap.json'}
  22. # Validate against the jsonschema
  23. try:
  24. keyboard_api_validate(info_data)
  25. except jsonschema.ValidationError as e:
  26. json_path = '.'.join([str(p) for p in e.absolute_path])
  27. cli.log.error('Invalid API data: %s: %s: %s', keyboard, json_path, e.message)
  28. exit()
  29. # Make sure we have at least one layout
  30. if not info_data.get('layouts'):
  31. info_log_error(info_data, 'No LAYOUTs defined! Need at least one layout defined in the keyboard.h or info.json.')
  32. # Filter out any non-existing community layouts
  33. for layout in info_data.get('community_layouts', []):
  34. if not _valid_community_layout(layout):
  35. # Ignore layout from future checks
  36. info_data['community_layouts'].remove(layout)
  37. info_log_error(info_data, 'Claims to support a community layout that does not exist: %s' % (layout))
  38. # Make sure we supply layout macros for the community layouts we claim to support
  39. for layout in info_data.get('community_layouts', []):
  40. layout_name = 'LAYOUT_' + layout
  41. if layout_name not in info_data.get('layouts', {}) and layout_name not in info_data.get('layout_aliases', {}):
  42. info_log_error(info_data, 'Claims to support community layout %s but no %s() macro found' % (layout, layout_name))
  43. return info_data