at master 3.7 kB view raw
1"""Keyboard information script. 2 3Compile an info.json for a particular keyboard and pretty-print it. 4""" 5import json 6 7from argcomplete.completers import FilesCompleter 8from jsonschema import Draft202012Validator, RefResolver, validators 9from milc import cli 10from pathlib import Path 11 12from qmk.decorators import automagic_keyboard, automagic_keymap 13from qmk.info import info_json 14from qmk.json_encoders import InfoJSONEncoder 15from qmk.json_schema import compile_schema_store 16from qmk.keyboard import keyboard_completer, keyboard_folder 17from qmk.path import is_keyboard, normpath 18 19 20def pruning_validator(validator_class): 21 """Extends Draft202012Validator to remove properties that aren't specified in the schema. 22 """ 23 validate_properties = validator_class.VALIDATORS["properties"] 24 25 def remove_additional_properties(validator, properties, instance, schema): 26 for prop in list(instance.keys()): 27 if prop not in properties: 28 del instance[prop] 29 30 for error in validate_properties(validator, properties, instance, schema): 31 yield error 32 33 return validators.extend(validator_class, {"properties": remove_additional_properties}) 34 35 36def strip_info_json(kb_info_json): 37 """Remove the API-only properties from the info.json. 38 """ 39 schema_store = compile_schema_store() 40 pruning_draft_validator = pruning_validator(Draft202012Validator) 41 schema = schema_store['qmk.keyboard.v1'] 42 resolver = RefResolver.from_schema(schema_store['qmk.keyboard.v1'], store=schema_store) 43 validator = pruning_draft_validator(schema, resolver=resolver).validate 44 45 return validator(kb_info_json) 46 47 48@cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='Keyboard to show info for.') 49@cli.argument('-km', '--keymap', help='Show the layers for a JSON keymap too.') 50@cli.argument('-o', '--output', arg_only=True, completer=FilesCompleter, help='Write the output the specified file, overwriting if necessary.') 51@cli.argument('-ow', '--overwrite', arg_only=True, action='store_true', help='Overwrite the existing info.json. (Overrides the location of --output)') 52@cli.subcommand('Generate an info.json file for a keyboard.', hidden=False if cli.config.user.developer else True) 53@automagic_keyboard 54@automagic_keymap 55def generate_info_json(cli): 56 """Generate an info.json file for a keyboard 57 """ 58 # Determine our keyboard(s) 59 if not cli.config.generate_info_json.keyboard: 60 cli.log.error('Missing parameter: --keyboard') 61 cli.subcommands['info'].print_help() 62 return False 63 64 if not is_keyboard(cli.config.generate_info_json.keyboard): 65 cli.log.error('Invalid keyboard: "%s"', cli.config.generate_info_json.keyboard) 66 return False 67 68 if cli.args.overwrite: 69 output_path = (Path('keyboards') / cli.config.generate_info_json.keyboard / 'info.json').resolve() 70 71 if cli.args.output: 72 cli.log.warning('Overwriting user supplied --output with %s', output_path) 73 74 cli.args.output = output_path 75 76 # Build the info.json file 77 kb_info_json = info_json(cli.config.generate_info_json.keyboard) 78 strip_info_json(kb_info_json) 79 info_json_text = json.dumps(kb_info_json, indent=4, cls=InfoJSONEncoder, sort_keys=True) 80 81 if cli.args.output: 82 # Write to a file 83 output_path = normpath(cli.args.output) 84 85 if output_path.exists(): 86 cli.log.warning('Overwriting output file %s', output_path) 87 88 output_path.write_text(info_json_text + '\n') 89 cli.log.info('Wrote info.json to %s.', output_path) 90 91 else: 92 # Display the results 93 print(info_json_text)