qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

migrate.py (3540B)


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