qmk_firmware

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

info_json.py (3675B)


      1 """Keyboard information script.
      2 
      3 Compile an info.json for a particular keyboard and pretty-print it.
      4 """
      5 import json
      6 
      7 from argcomplete.completers import FilesCompleter
      8 from jsonschema import Draft202012Validator, RefResolver, validators
      9 from milc import cli
     10 from pathlib import Path
     11 
     12 from qmk.decorators import automagic_keyboard, automagic_keymap
     13 from qmk.info import info_json
     14 from qmk.json_encoders import InfoJSONEncoder
     15 from qmk.json_schema import compile_schema_store
     16 from qmk.keyboard import keyboard_completer, keyboard_folder
     17 from qmk.path import is_keyboard, normpath
     18 
     19 
     20 def 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 
     36 def 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
     55 def 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)