logo

qmk_firmware

custom branch of QMK firmware git clone https://anongit.hacktivis.me/git/qmk_firmware.git

migrate.py (3576B)


  1. """Migrate keyboard configuration to "Data Driven"
  2. """
  3. import json
  4. from pathlib import Path
  5. from dotty_dict import dotty
  6. from milc import cli
  7. from qmk.keyboard import keyboard_completer, keyboard_folder, resolve_keyboard
  8. from qmk.info import info_json, find_info_json
  9. from qmk.json_encoders import InfoJSONEncoder
  10. from qmk.json_schema import json_load
  11. def _candidate_files(keyboard):
  12. kb_dir = Path(resolve_keyboard(keyboard))
  13. cur_dir = Path('keyboards')
  14. files = []
  15. for dir in kb_dir.parts:
  16. cur_dir = cur_dir / dir
  17. files.append(cur_dir / 'config.h')
  18. files.append(cur_dir / 'rules.mk')
  19. return [file for file in files if file.exists()]
  20. @cli.argument('-f', '--filter', arg_only=True, action='append', default=[], help="Filter the performed migrations based on the supplied value. Supported format is 'KEY' located from 'data/mappings'. May be passed multiple times.")
  21. @cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, required=True, help='The keyboard\'s name')
  22. @cli.subcommand('Migrate keyboard config to "Data Driven".', hidden=True)
  23. def migrate(cli):
  24. """Migrate keyboard configuration to "Data Driven"
  25. """
  26. # Merge mappings as we do not care to where "KEY" is found just that its removed
  27. info_config_map = json_load(Path('data/mappings/info_config.hjson'))
  28. info_rules_map = json_load(Path('data/mappings/info_rules.hjson'))
  29. info_map = {**info_config_map, **info_rules_map}
  30. # Parse target info.json which will receive updates
  31. target_info = Path(find_info_json(cli.args.keyboard)[0])
  32. info_data = dotty(json_load(target_info))
  33. # Already parsed used for updates
  34. kb_info_json = dotty(info_json(cli.args.keyboard))
  35. # List of candidate files
  36. files = _candidate_files(cli.args.keyboard)
  37. # Filter down keys if requested
  38. keys = list(filter(lambda key: info_map[key].get("to_json", True), info_map.keys()))
  39. if cli.args.filter:
  40. keys = list(set(keys) & set(cli.args.filter))
  41. rejected = set(cli.args.filter) - set(keys)
  42. for key in rejected:
  43. cli.log.info(f'{{fg_yellow}}Skipping {key} as migration not possible...')
  44. cli.log.info(f'{{fg_green}}Migrating keyboard {{fg_cyan}}{cli.args.keyboard}{{fg_green}}.{{fg_reset}}')
  45. # Start migration
  46. for file in files:
  47. cli.log.info(f' Migrating file {file}')
  48. file_contents = file.read_text(encoding='utf-8').split('\n')
  49. for key in keys:
  50. for num, line in enumerate(file_contents):
  51. if line.startswith(f'{key} =') or line.startswith(f'#define {key} '):
  52. cli.log.info(f' Migrating {key}...')
  53. while line.rstrip().endswith('\\'):
  54. file_contents.pop(num)
  55. line = file_contents[num]
  56. file_contents.pop(num)
  57. update_key = info_map[key]["info_key"]
  58. if update_key in kb_info_json:
  59. info_data[update_key] = kb_info_json[update_key]
  60. file.write_text('\n'.join(file_contents), encoding='utf-8')
  61. # Finally write out updated info.json
  62. cli.log.info(f' Updating {target_info}')
  63. target_info.write_text(json.dumps(info_data.to_dict(), cls=InfoJSONEncoder, sort_keys=True))
  64. cli.log.info(f'{{fg_green}}Migration of keyboard {{fg_cyan}}{cli.args.keyboard}{{fg_green}} complete!{{fg_reset}}')
  65. cli.log.info(f"Verify build with {{fg_yellow}}qmk compile -kb {cli.args.keyboard} -km default{{fg_reset}}.")