Merge remote-tracking branch 'origin/master' into develop
This commit is contained in:
		
						commit
						0dc0516f0c
					
				
					 18 changed files with 614 additions and 106 deletions
				
			
		
							
								
								
									
										443
									
								
								data/mappings/keyboard_aliases.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										443
									
								
								data/mappings/keyboard_aliases.json
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,443 @@ | |||
| { | ||||
|     # Format for each entry: | ||||
|     # <alias>: { | ||||
|     #     target: <keyboard_folder>, | ||||
|     #     layouts: { | ||||
|     #         <layout_alias>: <layout_target> | ||||
|     #     } | ||||
|     # } | ||||
|     # | ||||
|     # Both target and layouts are optional. | ||||
|     '2_milk': { | ||||
|           target: 'spaceman/2_milk' | ||||
|     }, | ||||
|     'aeboards/ext65': { | ||||
|           target: 'aeboards/ext65/rev1' | ||||
|     }, | ||||
|     'ai03/equinox': { | ||||
|           target: 'ai03/equinox/rev1' | ||||
|     }, | ||||
|     aleth42: { | ||||
|           target: 'aleth42/rev1' | ||||
|     }, | ||||
|     alice: { | ||||
|           target: 'tgr/alice' | ||||
|     }, | ||||
|     angel17: { | ||||
|           target: 'angel17/alpha' | ||||
|     }, | ||||
|     angel64: { | ||||
|           target: 'angel64/alpha' | ||||
|     }, | ||||
|     at101_blackheart: { | ||||
|           target: 'at101_bh' | ||||
|     }, | ||||
|     'atom47/rev2': { | ||||
|           target: 'maartenwut/atom47/rev2' | ||||
|     }, | ||||
|     'atom47/rev3': { | ||||
|           target: 'maartenwut/atom47/rev3' | ||||
|     }, | ||||
|     bear_face: { | ||||
|           target: 'bear_face/v1' | ||||
|     }, | ||||
|     'bpiphany/pegasushoof': { | ||||
|           target: 'bpiphany/pegasushoof/2013' | ||||
|     }, | ||||
|     chavdai40: { | ||||
|           target: 'chavdai40/rev1' | ||||
|     }, | ||||
|     'candybar/lefty': { | ||||
|           target: 'tkc/candybar/lefty' | ||||
|     }, | ||||
|     'candybar/righty': { | ||||
|           target: 'tkc/candybar/righty' | ||||
|     }, | ||||
|     canoe: { | ||||
|           target: 'percent/canoe' | ||||
|     }, | ||||
|     'cmm_studio/saka68': { | ||||
|           target: 'cmm_studio/saka68/solder' | ||||
|     }, | ||||
|     'crkbd/rev1': { | ||||
|           target: 'crkbd/rev1/legacy' | ||||
|     }, | ||||
|     'doro67/multi': { | ||||
|           layouts: { | ||||
|                   LAYOUT_ansi: 'LAYOUT_65_ansi_blocker' | ||||
|           } | ||||
|     }, | ||||
|     'doro67/regular': { | ||||
|           layouts: { | ||||
|                   LAYOUT: 'LAYOUT_65_ansi_blocker' | ||||
|           } | ||||
|     }, | ||||
|     'doro67/rgb': { | ||||
|           layouts: { | ||||
|                   LAYOUT: 'LAYOUT_65_ansi_blocker' | ||||
|           } | ||||
|     }, | ||||
|     drakon: { | ||||
|           target: 'jagdpietr/drakon' | ||||
|     }, | ||||
|     'dztech/dz60rgb': { | ||||
|           target: 'dztech/dz60rgb/v1' | ||||
|     }, | ||||
|     'dztech/dz60rgb_ansi': { | ||||
|           target: 'dztech/dz60rgb_ansi/v1' | ||||
|     }, | ||||
|     'dztech/dz60rgb_wkl': { | ||||
|           target: 'dztech/dz60rgb_wkl/v1' | ||||
|     }, | ||||
|     'dztech/dz65rgb': { | ||||
|           target: 'dztech/dz65rgb/v1' | ||||
|     }, | ||||
|     eek: { | ||||
|           target: 'eek/silk_down' | ||||
|     }, | ||||
|     ergoinu: { | ||||
|           target: 'dm9records/ergoinu' | ||||
|     }, | ||||
|     'exclusive/e85': { | ||||
|           target: 'exclusive/e85/hotswap' | ||||
|     }, | ||||
|     gh60: { | ||||
|           target: 'gh60/revc' | ||||
|     }, | ||||
|     'handwired/ferris': { | ||||
|           target: 'ferris/0_1' | ||||
|     }, | ||||
|     'helix/pico/sc/back': { | ||||
|           target: 'helix/pico/sc' | ||||
|     }, | ||||
|     'helix/pico/sc/under': { | ||||
|           target: 'helix/pico/sc' | ||||
|     }, | ||||
|     'helix/rev2/back/oled': { | ||||
|           target: 'helix/rev2/back' | ||||
|     }, | ||||
|     'helix/rev2/oled': { | ||||
|           target: 'helix/rev2' | ||||
|     }, | ||||
|     'helix/rev2/oled/back': { | ||||
|           target: 'helix/rev2/back' | ||||
|     }, | ||||
|     'helix/rev2/oled/under': { | ||||
|           target: 'helix/rev2/under' | ||||
|     }, | ||||
|     'helix/rev2/sc/back': { | ||||
|           target: 'helix/rev2/sc' | ||||
|     }, | ||||
|     'helix/rev2/sc/oled': { | ||||
|           target: 'helix/rev2/sc' | ||||
|     }, | ||||
|     'helix/rev2/sc/oledback': { | ||||
|           target: 'helix/rev2/sc' | ||||
|     }, | ||||
|     'helix/rev2/sc/oledunder': { | ||||
|           target: 'helix/rev2/sc' | ||||
|     }, | ||||
|     'helix/rev2/sc/under': { | ||||
|           target: 'helix/rev2/sc' | ||||
|     }, | ||||
|     'helix/rev2/under': { | ||||
|           target: 'helix/rev2/sc' | ||||
|     }, | ||||
|     'helix/rev2/under/oled': { | ||||
|           target: 'helix/rev2/under' | ||||
|     }, | ||||
|     id80: { | ||||
|           target: 'id80/ansi' | ||||
|     }, | ||||
|     idb_60: { | ||||
|           target: 'idb/idb_60', | ||||
|           layouts: { | ||||
|                   LAYOUT: 'LAYOUT_all' | ||||
|           } | ||||
|     }, | ||||
|     jones: { | ||||
|           target: 'jones/v03_1' | ||||
|     }, | ||||
|     katana60: { | ||||
|           target: 'rominronin/katana60/rev1' | ||||
|     }, | ||||
|     'kbdfans/kbd67mkiirgb': { | ||||
|           target: 'kbdfans/kbd67/mkiirgb', | ||||
|           layouts: { | ||||
|                   LAYOUT: 'LAYOUT_65_ansi_blocker' | ||||
|           } | ||||
|     }, | ||||
|     'kbdfans/kbd67/mkiirgb': { | ||||
|           target: 'kbdfans/kbd67/mkiirgb/v1' | ||||
|     }, | ||||
|     'keebio/dsp40': { | ||||
|           target: 'keebio/dsp40/rev1' | ||||
|     }, | ||||
|     'keycapsss/plaid_pad': { | ||||
|           target: 'keycapsss/plaid_pad/rev1' | ||||
|     }, | ||||
|     kudox: { | ||||
|           target: 'kudox/rev1' | ||||
|     }, | ||||
|     'lfkeyboards/lfk78': { | ||||
|           target: 'lfkeyboards/lfk78/revj' | ||||
|     }, | ||||
|     'lfkeyboards/smk65': { | ||||
|           target: 'lfkeyboards/smk65/revb' | ||||
|     }, | ||||
|     'maartenwut/atom47/rev2': { | ||||
|           target: 'evyd13/atom47/rev2' | ||||
|     }, | ||||
|     'maartenwut/atom47/rev3': { | ||||
|           target: 'evyd13/atom47/rev3' | ||||
|     }, | ||||
|     'maartenwut/eon40': { | ||||
|           target: 'evyd13/eon40' | ||||
|     }, | ||||
|     'maartenwut/eon65': { | ||||
|           target: 'evyd13/eon65' | ||||
|     }, | ||||
|     'maartenwut/eon75': { | ||||
|           target: 'evyd13/eon75' | ||||
|     }, | ||||
|     'maartenwut/eon87': { | ||||
|           target: 'evyd13/eon87' | ||||
|     }, | ||||
|     'maartenwut/eon95': { | ||||
|           target: 'evyd13/eon95' | ||||
|     }, | ||||
|     'maartenwut/gh80_1800': { | ||||
|           target: 'evyd13/gh80_1800' | ||||
|     }, | ||||
|     'maartenwut/gh80_3700': { | ||||
|           target: 'evyd13/gh80_3700' | ||||
|     }, | ||||
|     'maartenwut/minitomic': { | ||||
|           target: 'evyd13/minitomic' | ||||
|     }, | ||||
|     'maartenwut/mx5160': { | ||||
|           target: 'evyd13/mx5160' | ||||
|     }, | ||||
|     'maartenwut/nt660': { | ||||
|           target: 'evyd13/nt660' | ||||
|     }, | ||||
|     'maartenwut/omrontkl': { | ||||
|           target: 'evyd13/omrontkl' | ||||
|     }, | ||||
|     'maartenwut/plain60': { | ||||
|           target: 'evyd13/plain60' | ||||
|     }, | ||||
|     'maartenwut/pockettype': { | ||||
|           target: 'evyd13/pockettype' | ||||
|     }, | ||||
|     'maartenwut/quackfire': { | ||||
|           target: 'evyd13/quackfire' | ||||
|     }, | ||||
|     'maartenwut/solheim68': { | ||||
|           target: 'evyd13/solheim68' | ||||
|     }, | ||||
|     'maartenwut/ta65': { | ||||
|           target: 'evyd13/ta65' | ||||
|     }, | ||||
|     'maartenwut/wasdat': { | ||||
|           target: 'evyd13/wasdat' | ||||
|     }, | ||||
|     'maartenwut/wasdat_code': { | ||||
|           target: 'evyd13/wasdat_code' | ||||
|     }, | ||||
|     'maartenwut/wonderland': { | ||||
|           target: 'evyd13/wonderland' | ||||
|     }, | ||||
|     'mechlovin/hannah910': { | ||||
|           target: 'mechlovin/hannah910/rev1' | ||||
|     }, | ||||
|     'mechlovin/adelais/rgb_led': { | ||||
|           target: 'mechlovin/adelais/rgb_led/rev1' | ||||
|     }, | ||||
|     'mechlovin/adelais/standard_led': { | ||||
|           target: 'mechlovin/adelais/standard_led/rev2' | ||||
|     }, | ||||
|     'mechlovin/delphine': { | ||||
|           target: 'mechlovin/delphine/mono_led' | ||||
|     }, | ||||
|     'mechlovin/hannah60rgb': { | ||||
|           target: 'mechlovin/hannah60rgb/rev1' | ||||
|     }, | ||||
|     'melgeek/z70ultra': { | ||||
|           target: 'melgeek/z70ultra/rev1' | ||||
|     }, | ||||
|     'mechlovin/hannah65': { | ||||
|           target: 'mechlovin/hannah65/rev1' | ||||
|     }, | ||||
|     model01: { | ||||
|           target: 'keyboardio/model01' | ||||
|     }, | ||||
|     m0lly: { | ||||
|           target: 'tkc/m0lly' | ||||
|     }, | ||||
|     'montsinger/rebound': { | ||||
|           target: 'montsinger/rebound/rev1' | ||||
|     }, | ||||
|     nomu30: { | ||||
|           target: 'nomu30/rev1' | ||||
|     }, | ||||
|     'noxary/268_2': { | ||||
|           layouts: { | ||||
|                   LAYOUT: 'LAYOUT_65_ansi_blocker' | ||||
|           } | ||||
|     }, | ||||
|     oddball: { | ||||
|           target: 'oddball/v1' | ||||
|     }, | ||||
|     omnikey_blackheart: { | ||||
|           target: 'omnikey_bh' | ||||
|     }, | ||||
|     'pabile/p20': { | ||||
|           target: 'pabile/p20/ver1' | ||||
|     }, | ||||
|     'pancake/feather': { | ||||
|           target: 'spaceman/pancake/feather' | ||||
|     }, | ||||
|     'pancake/promicro': { | ||||
|           target: 'spaceman/pancake/promicro' | ||||
|     }, | ||||
|     'percent/canoe': { | ||||
|           layouts: { | ||||
|                   LAYOUT_iso: 'LAYOUT_65_iso_blocker' | ||||
|           } | ||||
|     }, | ||||
|     plaid: { | ||||
|           target: 'dm9records/plaid' | ||||
|     }, | ||||
|     plain60: { | ||||
|           target: 'maartenwut/plain60' | ||||
|     }, | ||||
|     'ploopyco/trackball': { | ||||
|           target: 'ploopyco/trackball/rev1_005' | ||||
|     }, | ||||
|     polilla: { | ||||
|           target: 'polilla/rev1' | ||||
|     }, | ||||
|     'preonic/rev1': { | ||||
|           layouts: { | ||||
|                   LAYOUT_preonic_grid: 'LAYOUT_ortho_5x12' | ||||
|           } | ||||
|     }, | ||||
|     'preonic/rev2': { | ||||
|           layouts: { | ||||
|                   LAYOUT_preonic_grid: 'LAYOUT_ortho_5x12' | ||||
|           } | ||||
|     }, | ||||
|     'preonic/rev3': { | ||||
|           layouts: { | ||||
|                   LAYOUT_preonic_grid: 'LAYOUT_ortho_5x12' | ||||
|           } | ||||
|     }, | ||||
|     'primekb/prime_l': { | ||||
|           target: 'primekb/prime_l/v1' | ||||
|     }, | ||||
|     'primekb/prime_l_v2': { | ||||
|           target: 'primekb/prime_l/v2' | ||||
|     }, | ||||
|     'projectkb/alice': { | ||||
|           target: 'projectkb/alice/rev1' | ||||
|     }, | ||||
|     'rama/koyu': { | ||||
|           target: 'wilba_tech/rama_works_koyu' | ||||
|     }, | ||||
|     'rama/m6_a': { | ||||
|           target: 'wilba_tech/rama_works_m6_a' | ||||
|     }, | ||||
|     'rama/m6_b': { | ||||
|           target: 'wilba_tech/rama_works_m6_b' | ||||
|     }, | ||||
|     'rama/m10_b': { | ||||
|           target: 'wilba_tech/rama_works_m10_b' | ||||
|     }, | ||||
|     'rama/m60_a': { | ||||
|           target: 'wilba_tech/rama_works_m60_a' | ||||
|     }, | ||||
|     'rama/u80_a': { | ||||
|           target: 'wilba_tech/rama_works_u80_a' | ||||
|     }, | ||||
|     'ramonimbao/herringbone': { | ||||
|           target: 'ramonimbao/herringbone/v1' | ||||
|     }, | ||||
|     'rgbkb/pan': { | ||||
|           target: 'rgbkb/pan/rev1/32a' | ||||
|     }, | ||||
|     'rgbkb/pan/rev1': { | ||||
|           target: 'rgbkb/pan/rev1/32a' | ||||
|     }, | ||||
|     romac: { | ||||
|           target: 'kingly_keys/romac' | ||||
|     }, | ||||
|     ropro: { | ||||
|           target: 'kingly_keys/ropro' | ||||
|     }, | ||||
|     satan: { | ||||
|           target: 'gh60/satan' | ||||
|     }, | ||||
|     skog: { | ||||
|           target: 'percent/skog' | ||||
|     }, | ||||
|     speedo: { | ||||
|           target: 'cozykeys/speedo/v2' | ||||
|     }, | ||||
|     stoutgat: { | ||||
|           target: 'tkw/stoutgat/v1' | ||||
|     }, | ||||
|     suihankey: { | ||||
|           target: 'suihankey/split/alpha' | ||||
|     }, | ||||
|     ta65: { | ||||
|           target: 'maartenwut/ta65' | ||||
|     }, | ||||
|     tartan: { | ||||
|           target: 'dm9records/tartan' | ||||
|     }, | ||||
|     tkc1800: { | ||||
|           target: 'tkc/tkc1800' | ||||
|     }, | ||||
|     'tkw/stoutgat/v2': { | ||||
|           target: 'tkw/stoutgat/v2/f411' | ||||
|     }, | ||||
|     underscore33: { | ||||
|           target: 'underscore33/rev1' | ||||
|     }, | ||||
|     vinta: { | ||||
|           layouts: { | ||||
|                   LAYOUT_67_ansi: 'LAYOUT_65_ansi_blocker' | ||||
|           } | ||||
|     }, | ||||
|     wasdat: { | ||||
|           target: 'maartenwut/wasdat' | ||||
|     }, | ||||
|     'westfoxtrot/cypher': { | ||||
|           target: 'westfoxtrot/cypher/rev1' | ||||
|     }, | ||||
|     'whale/sk': { | ||||
|           target: 'whale/sk/v3' | ||||
|     }, | ||||
|     'xelus/dawn60': { | ||||
|           target: 'xelus/dawn60/rev1' | ||||
|     }, | ||||
|     'xelus/valor': { | ||||
|           target: 'xelus/valor/rev1' | ||||
|     }, | ||||
|     yd60mq: { | ||||
|           target: 'yd60mq/12led' | ||||
|     }, | ||||
|     ymd75: { | ||||
|           target: 'ymd75/rev1' | ||||
|     }, | ||||
|     z150_blackheart: { | ||||
|           target: 'z150_bh' | ||||
|     }, | ||||
|     zeal60: { | ||||
|           target: 'wilba_tech/zeal60' | ||||
|     }, | ||||
|     zeal65: { | ||||
|           target: 'wilba_tech/zeal65' | ||||
|     } | ||||
| } | ||||
|  | @ -7,12 +7,13 @@ from milc import cli | |||
| import qmk.keymap | ||||
| import qmk.path | ||||
| from qmk.info_json_encoder import InfoJSONEncoder | ||||
| from qmk.keyboard import keyboard_folder | ||||
| 
 | ||||
| 
 | ||||
| @cli.argument('--no-cpp', arg_only=True, action='store_false', help='Do not use \'cpp\' on keymap.c') | ||||
| @cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to') | ||||
| @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") | ||||
| @cli.argument('-kb', '--keyboard', arg_only=True, required=True, help='The keyboard\'s name') | ||||
| @cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, required=True, help='The keyboard\'s name') | ||||
| @cli.argument('-km', '--keymap', arg_only=True, required=True, help='The keymap\'s name') | ||||
| @cli.argument('filename', arg_only=True, help='keymap.c file') | ||||
| @cli.subcommand('Creates a keymap.json from a keymap.c file.') | ||||
|  |  | |||
|  | @ -7,10 +7,11 @@ from milc import cli | |||
| import qmk.path | ||||
| from qmk.decorators import automagic_keyboard, automagic_keymap | ||||
| from qmk.commands import compile_configurator_json, create_make_command, parse_configurator_json | ||||
| from qmk.keyboard import keyboard_folder | ||||
| 
 | ||||
| 
 | ||||
| @cli.argument('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), help='The configurator export to compile') | ||||
| @cli.argument('-kb', '--keyboard', help='The keyboard to build a firmware for. Ignored when a configurator export is supplied.') | ||||
| @cli.argument('-kb', '--keyboard', type=keyboard_folder, help='The keyboard to build a firmware for. Ignored when a configurator export is supplied.') | ||||
| @cli.argument('-km', '--keymap', help='The keymap to build a firmware for. Ignored when a configurator export is supplied.') | ||||
| @cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the make command to be run.") | ||||
| @cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs to run.") | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ from milc import cli | |||
| import qmk.path | ||||
| from qmk.decorators import automagic_keyboard, automagic_keymap | ||||
| from qmk.commands import compile_configurator_json, create_make_command, parse_configurator_json | ||||
| from qmk.keyboard import keyboard_folder | ||||
| 
 | ||||
| 
 | ||||
| def print_bootloader_help(): | ||||
|  | @ -33,7 +34,7 @@ def print_bootloader_help(): | |||
| @cli.argument('-b', '--bootloaders', action='store_true', help='List the available bootloaders.') | ||||
| @cli.argument('-bl', '--bootloader', default='flash', help='The flash command, corresponding to qmk\'s make options of bootloaders.') | ||||
| @cli.argument('-km', '--keymap', help='The keymap to build a firmware for. Use this if you dont have a configurator file. Ignored when a configurator file is supplied.') | ||||
| @cli.argument('-kb', '--keyboard', help='The keyboard to build a firmware for. Use this if you dont have a configurator file. Ignored when a configurator file is supplied.') | ||||
| @cli.argument('-kb', '--keyboard', type=keyboard_folder, help='The keyboard to build a firmware for. Use this if you dont have a configurator file. Ignored when a configurator file is supplied.') | ||||
| @cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the make command to be run.") | ||||
| @cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs to run.") | ||||
| @cli.argument('-e', '--env', arg_only=True, action='append', default=[], help="Set a variable to be passed to make. May be passed multiple times.") | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ from milc import cli | |||
| from qmk.datetime import current_datetime | ||||
| from qmk.info import info_json | ||||
| from qmk.info_json_encoder import InfoJSONEncoder | ||||
| from qmk.json_schema import json_load | ||||
| from qmk.keyboard import list_keyboards | ||||
| 
 | ||||
| 
 | ||||
|  | @ -18,43 +19,58 @@ def generate_api(cli): | |||
|     """ | ||||
|     api_data_dir = Path('api_data') | ||||
|     v1_dir = api_data_dir / 'v1' | ||||
|     keyboard_list = v1_dir / 'keyboard_list.json' | ||||
|     keyboard_all = v1_dir / 'keyboards.json' | ||||
|     usb_file = v1_dir / 'usb.json' | ||||
|     keyboard_all_file = v1_dir / 'keyboards.json'               # A massive JSON containing everything | ||||
|     keyboard_list_file = v1_dir / 'keyboard_list.json'          # A simple list of keyboard targets | ||||
|     keyboard_aliases_file = v1_dir / 'keyboard_aliases.json'    # A list of historical keyboard names and their new name | ||||
|     keyboard_metadata_file = v1_dir / 'keyboard_metadata.json'  # All the data configurator/via needs for initialization | ||||
|     usb_file = v1_dir / 'usb.json'                         # A mapping of USB VID/PID -> keyboard target | ||||
| 
 | ||||
|     if not api_data_dir.exists(): | ||||
|         api_data_dir.mkdir() | ||||
| 
 | ||||
|     kb_all = {'last_updated': current_datetime(), 'keyboards': {}} | ||||
|     usb_list = {'last_updated': current_datetime(), 'devices': {}} | ||||
|     kb_all = {} | ||||
|     usb_list = {} | ||||
| 
 | ||||
|     # Generate and write keyboard specific JSON files | ||||
|     for keyboard_name in list_keyboards(): | ||||
|         kb_all['keyboards'][keyboard_name] = info_json(keyboard_name) | ||||
|         kb_all[keyboard_name] = info_json(keyboard_name) | ||||
|         keyboard_dir = v1_dir / 'keyboards' / keyboard_name | ||||
|         keyboard_info = keyboard_dir / 'info.json' | ||||
|         keyboard_readme = keyboard_dir / 'readme.md' | ||||
|         keyboard_readme_src = Path('keyboards') / keyboard_name / 'readme.md' | ||||
| 
 | ||||
|         keyboard_dir.mkdir(parents=True, exist_ok=True) | ||||
|         keyboard_info.write_text(json.dumps({'last_updated': current_datetime(), 'keyboards': {keyboard_name: kb_all['keyboards'][keyboard_name]}})) | ||||
|         keyboard_info.write_text(json.dumps({'last_updated': current_datetime(), 'keyboards': {keyboard_name: kb_all[keyboard_name]}})) | ||||
| 
 | ||||
|         if keyboard_readme_src.exists(): | ||||
|             copyfile(keyboard_readme_src, keyboard_readme) | ||||
| 
 | ||||
|         if 'usb' in kb_all['keyboards'][keyboard_name]: | ||||
|             usb = kb_all['keyboards'][keyboard_name]['usb'] | ||||
|         if 'usb' in kb_all[keyboard_name]: | ||||
|             usb = kb_all[keyboard_name]['usb'] | ||||
| 
 | ||||
|             if 'vid' in usb and usb['vid'] not in usb_list['devices']: | ||||
|                 usb_list['devices'][usb['vid']] = {} | ||||
|             if 'vid' in usb and usb['vid'] not in usb_list: | ||||
|                 usb_list[usb['vid']] = {} | ||||
| 
 | ||||
|             if 'pid' in usb and usb['pid'] not in usb_list['devices'][usb['vid']]: | ||||
|                 usb_list['devices'][usb['vid']][usb['pid']] = {} | ||||
|             if 'pid' in usb and usb['pid'] not in usb_list[usb['vid']]: | ||||
|                 usb_list[usb['vid']][usb['pid']] = {} | ||||
| 
 | ||||
|             if 'vid' in usb and 'pid' in usb: | ||||
|                 usb_list['devices'][usb['vid']][usb['pid']][keyboard_name] = usb | ||||
|                 usb_list[usb['vid']][usb['pid']][keyboard_name] = usb | ||||
| 
 | ||||
|     # Write the global JSON files | ||||
|     keyboard_list.write_text(json.dumps({'last_updated': current_datetime(), 'keyboards': sorted(kb_all['keyboards'])}, cls=InfoJSONEncoder)) | ||||
|     keyboard_all.write_text(json.dumps(kb_all, cls=InfoJSONEncoder)) | ||||
|     usb_file.write_text(json.dumps(usb_list, cls=InfoJSONEncoder)) | ||||
|     keyboard_all_file.write_text(json.dumps({'last_updated': current_datetime(), 'keyboards': kb_all}, cls=InfoJSONEncoder)) | ||||
|     usb_file.write_text(json.dumps({'last_updated': current_datetime(), 'usb': usb_list}, cls=InfoJSONEncoder)) | ||||
| 
 | ||||
|     keyboard_list = sorted(kb_all) | ||||
|     keyboard_list_file.write_text(json.dumps({'last_updated': current_datetime(), 'keyboards': keyboard_list}, cls=InfoJSONEncoder)) | ||||
| 
 | ||||
|     keyboard_aliases = json_load(Path('data/mappings/keyboard_aliases.json')) | ||||
|     keyboard_aliases_file.write_text(json.dumps({'last_updated': current_datetime(), 'keyboard_aliases': keyboard_aliases}, cls=InfoJSONEncoder)) | ||||
| 
 | ||||
|     keyboard_metadata = { | ||||
|         'last_updated': current_datetime(), | ||||
|         'keyboards': keyboard_list, | ||||
|         'keyboard_aliases': keyboard_aliases, | ||||
|         'usb': usb_list | ||||
|     } | ||||
|     keyboard_metadata_file.write_text(json.dumps(keyboard_metadata, cls=InfoJSONEncoder)) | ||||
|  |  | |||
|  | @ -6,7 +6,9 @@ from dotty_dict import dotty | |||
| from milc import cli | ||||
| 
 | ||||
| from qmk.decorators import automagic_keyboard, automagic_keymap | ||||
| from qmk.info import _json_load, info_json | ||||
| from qmk.info import info_json | ||||
| from qmk.json_schema import json_load | ||||
| from qmk.keyboard import keyboard_folder | ||||
| from qmk.path import is_keyboard, normpath | ||||
| 
 | ||||
| 
 | ||||
|  | @ -73,7 +75,7 @@ def matrix_pins(matrix_pins): | |||
| 
 | ||||
| @cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to') | ||||
| @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") | ||||
| @cli.argument('-kb', '--keyboard', help='Keyboard to generate config.h for.') | ||||
| @cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to generate config.h for.') | ||||
| @cli.subcommand('Used by the make system to generate info_config.h from info.json', hidden=True) | ||||
| @automagic_keyboard | ||||
| @automagic_keymap | ||||
|  | @ -92,7 +94,7 @@ def generate_config_h(cli): | |||
| 
 | ||||
|     # Build the info_config.h file. | ||||
|     kb_info_json = dotty(info_json(cli.config.generate_config_h.keyboard)) | ||||
|     info_config_map = _json_load(Path('data/mappings/info_config.json')) | ||||
|     info_config_map = json_load(Path('data/mappings/info_config.json')) | ||||
| 
 | ||||
|     config_h_lines = ['/* This file was generated by `qmk generate-config-h`. Do not edit or copy.' ' */', '', '#pragma once'] | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,8 +8,10 @@ from jsonschema import Draft7Validator, validators | |||
| from milc import cli | ||||
| 
 | ||||
| from qmk.decorators import automagic_keyboard, automagic_keymap | ||||
| from qmk.info import info_json, _jsonschema | ||||
| from qmk.info import info_json | ||||
| from qmk.info_json_encoder import InfoJSONEncoder | ||||
| from qmk.json_schema import load_jsonschema | ||||
| from qmk.keyboard import keyboard_folder | ||||
| from qmk.path import is_keyboard | ||||
| 
 | ||||
| 
 | ||||
|  | @ -33,13 +35,13 @@ def strip_info_json(kb_info_json): | |||
|     """Remove the API-only properties from the info.json. | ||||
|     """ | ||||
|     pruning_draft_7_validator = pruning_validator(Draft7Validator) | ||||
|     schema = _jsonschema('keyboard') | ||||
|     schema = load_jsonschema('keyboard') | ||||
|     validator = pruning_draft_7_validator(schema).validate | ||||
| 
 | ||||
|     return validator(kb_info_json) | ||||
| 
 | ||||
| 
 | ||||
| @cli.argument('-kb', '--keyboard', help='Keyboard to show info for.') | ||||
| @cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to show info for.') | ||||
| @cli.argument('-km', '--keymap', help='Show the layers for a JSON keymap too.') | ||||
| @cli.subcommand('Generate an info.json file for a keyboard.', hidden=False if cli.config.user.developer else True) | ||||
| @automagic_keyboard | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ from milc import cli | |||
| from qmk.constants import COL_LETTERS, ROW_LETTERS | ||||
| from qmk.decorators import automagic_keyboard, automagic_keymap | ||||
| from qmk.info import info_json | ||||
| from qmk.keyboard import keyboard_folder | ||||
| from qmk.path import is_keyboard, normpath | ||||
| 
 | ||||
| usb_properties = { | ||||
|  | @ -16,7 +17,7 @@ usb_properties = { | |||
| 
 | ||||
| @cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to') | ||||
| @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") | ||||
| @cli.argument('-kb', '--keyboard', help='Keyboard to generate config.h for.') | ||||
| @cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to generate config.h for.') | ||||
| @cli.subcommand('Used by the make system to generate layouts.h from info.json', hidden=True) | ||||
| @automagic_keyboard | ||||
| @automagic_keymap | ||||
|  |  | |||
|  | @ -6,7 +6,9 @@ from dotty_dict import dotty | |||
| from milc import cli | ||||
| 
 | ||||
| from qmk.decorators import automagic_keyboard, automagic_keymap | ||||
| from qmk.info import _json_load, info_json | ||||
| from qmk.info import info_json | ||||
| from qmk.json_schema import json_load | ||||
| from qmk.keyboard import keyboard_folder | ||||
| from qmk.path import is_keyboard, normpath | ||||
| 
 | ||||
| 
 | ||||
|  | @ -37,7 +39,7 @@ def process_mapping_rule(kb_info_json, rules_key, info_dict): | |||
| @cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to') | ||||
| @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") | ||||
| @cli.argument('-e', '--escape', arg_only=True, action='store_true', help="Escape spaces in quiet mode") | ||||
| @cli.argument('-kb', '--keyboard', help='Keyboard to generate config.h for.') | ||||
| @cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to generate config.h for.') | ||||
| @cli.subcommand('Used by the make system to generate info_config.h from info.json', hidden=True) | ||||
| @automagic_keyboard | ||||
| @automagic_keymap | ||||
|  | @ -54,7 +56,7 @@ def generate_rules_mk(cli): | |||
|         return False | ||||
| 
 | ||||
|     kb_info_json = dotty(info_json(cli.config.generate_rules_mk.keyboard)) | ||||
|     info_rules_map = _json_load(Path('data/mappings/info_rules.json')) | ||||
|     info_rules_map = json_load(Path('data/mappings/info_rules.json')) | ||||
|     rules_mk_lines = ['# This file was generated by `qmk generate-rules-mk`. Do not edit or copy.', ''] | ||||
| 
 | ||||
|     # Iterate through the info_rules map to generate basic rules | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ from milc import cli | |||
| from qmk.info_json_encoder import InfoJSONEncoder | ||||
| from qmk.constants import COL_LETTERS, ROW_LETTERS | ||||
| from qmk.decorators import automagic_keyboard, automagic_keymap | ||||
| from qmk.keyboard import render_layouts, render_layout | ||||
| from qmk.keyboard import keyboard_folder, render_layouts, render_layout | ||||
| from qmk.keymap import locate_keymap | ||||
| from qmk.info import info_json | ||||
| from qmk.path import is_keyboard | ||||
|  | @ -124,7 +124,7 @@ def print_text_output(kb_info_json): | |||
|         show_keymap(kb_info_json, False) | ||||
| 
 | ||||
| 
 | ||||
| @cli.argument('-kb', '--keyboard', help='Keyboard to show info for.') | ||||
| @cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to show info for.') | ||||
| @cli.argument('-km', '--keymap', help='Show the layers for a JSON keymap too.') | ||||
| @cli.argument('-l', '--layouts', action='store_true', help='Render the layouts.') | ||||
| @cli.argument('-m', '--matrix', action='store_true', help='Render the layouts with matrix information.') | ||||
|  |  | |||
|  | @ -4,18 +4,14 @@ from milc import cli | |||
| 
 | ||||
| import qmk.keymap | ||||
| from qmk.decorators import automagic_keyboard | ||||
| from qmk.path import is_keyboard | ||||
| from qmk.keyboard import keyboard_folder | ||||
| 
 | ||||
| 
 | ||||
| @cli.argument("-kb", "--keyboard", help="Specify keyboard name. Example: 1upkeyboards/1up60hse") | ||||
| @cli.argument("-kb", "--keyboard", type=keyboard_folder, help="Specify keyboard name. Example: 1upkeyboards/1up60hse") | ||||
| @cli.subcommand("List the keymaps for a specific keyboard") | ||||
| @automagic_keyboard | ||||
| def list_keymaps(cli): | ||||
|     """List the keymaps for a specific keyboard | ||||
|     """ | ||||
|     if not is_keyboard(cli.config.list_keymaps.keyboard): | ||||
|         cli.log.error('Keyboard %s does not exist!', cli.config.list_keymaps.keyboard) | ||||
|         return False | ||||
| 
 | ||||
|     for name in qmk.keymap.list_keymaps(cli.config.list_keymaps.keyboard): | ||||
|         print(name) | ||||
|  |  | |||
|  | @ -5,10 +5,11 @@ from pathlib import Path | |||
| 
 | ||||
| import qmk.path | ||||
| from qmk.decorators import automagic_keyboard, automagic_keymap | ||||
| from qmk.keyboard import keyboard_folder | ||||
| from milc import cli | ||||
| 
 | ||||
| 
 | ||||
| @cli.argument('-kb', '--keyboard', help='Specify keyboard name. Example: 1upkeyboards/1up60hse') | ||||
| @cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Specify keyboard name. Example: 1upkeyboards/1up60hse') | ||||
| @cli.argument('-km', '--keymap', help='Specify the name for the new keymap directory') | ||||
| @cli.subcommand('Creates a new keymap for the keyboard of your choosing') | ||||
| @automagic_keyboard | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ from milc import cli | |||
| 
 | ||||
| import qmk.keymap | ||||
| from qmk.constants import KEYBOARD_OUTPUT_PREFIX | ||||
| from qmk.json_schema import json_load | ||||
| 
 | ||||
| time_fmt = '%Y-%m-%d-%H:%M:%S' | ||||
| 
 | ||||
|  | @ -191,6 +192,15 @@ def parse_configurator_json(configurator_file): | |||
|     """ | ||||
|     # FIXME(skullydazed/anyone): Add validation here | ||||
|     user_keymap = json.load(configurator_file) | ||||
|     orig_keyboard = user_keymap['keyboard'] | ||||
|     aliases = json_load(Path('data/mappings/keyboard_aliases.json')) | ||||
| 
 | ||||
|     if orig_keyboard in aliases: | ||||
|         if 'target' in aliases[orig_keyboard]: | ||||
|             user_keymap['keyboard'] = aliases[orig_keyboard]['target'] | ||||
| 
 | ||||
|         if 'layouts' in aliases[orig_keyboard] and user_keymap['layout'] in aliases[orig_keyboard]['layouts']: | ||||
|             user_keymap['layout'] = aliases[orig_keyboard]['layouts'][user_keymap['layout']] | ||||
| 
 | ||||
|     return user_keymap | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,17 +1,15 @@ | |||
| """Functions that help us generate and use info.json files. | ||||
| """ | ||||
| import json | ||||
| from collections.abc import Mapping | ||||
| from glob import glob | ||||
| from pathlib import Path | ||||
| 
 | ||||
| import hjson | ||||
| import jsonschema | ||||
| from dotty_dict import dotty | ||||
| from milc import cli | ||||
| 
 | ||||
| from qmk.constants import CHIBIOS_PROCESSORS, LUFA_PROCESSORS, VUSB_PROCESSORS | ||||
| from qmk.c_parse import find_layouts | ||||
| from qmk.json_schema import deep_update, json_load, keyboard_validate, keyboard_api_validate | ||||
| from qmk.keyboard import config_h, rules_mk | ||||
| from qmk.keymap import list_keymaps | ||||
| from qmk.makefile import parse_rules_mk_file | ||||
|  | @ -82,52 +80,6 @@ def info_json(keyboard): | |||
|     return info_data | ||||
| 
 | ||||
| 
 | ||||
| def _json_load(json_file): | ||||
|     """Load a json file from disk. | ||||
| 
 | ||||
|     Note: file must be a Path object. | ||||
|     """ | ||||
|     try: | ||||
|         return hjson.load(json_file.open(encoding='utf-8')) | ||||
| 
 | ||||
|     except json.decoder.JSONDecodeError as e: | ||||
|         cli.log.error('Invalid JSON encountered attempting to load {fg_cyan}%s{fg_reset}:\n\t{fg_red}%s', json_file, e) | ||||
|         exit(1) | ||||
| 
 | ||||
| 
 | ||||
| def _jsonschema(schema_name): | ||||
|     """Read a jsonschema file from disk. | ||||
| 
 | ||||
|     FIXME(skullydazed/anyone): Refactor to make this a public function. | ||||
|     """ | ||||
|     schema_path = Path(f'data/schemas/{schema_name}.jsonschema') | ||||
| 
 | ||||
|     if not schema_path.exists(): | ||||
|         schema_path = Path('data/schemas/false.jsonschema') | ||||
| 
 | ||||
|     return _json_load(schema_path) | ||||
| 
 | ||||
| 
 | ||||
| def keyboard_validate(data): | ||||
|     """Validates data against the keyboard jsonschema. | ||||
|     """ | ||||
|     schema = _jsonschema('keyboard') | ||||
|     validator = jsonschema.Draft7Validator(schema).validate | ||||
| 
 | ||||
|     return validator(data) | ||||
| 
 | ||||
| 
 | ||||
| def keyboard_api_validate(data): | ||||
|     """Validates data against the api_keyboard jsonschema. | ||||
|     """ | ||||
|     base = _jsonschema('keyboard') | ||||
|     relative = _jsonschema('api_keyboard') | ||||
|     resolver = jsonschema.RefResolver.from_schema(base) | ||||
|     validator = jsonschema.Draft7Validator(relative, resolver=resolver).validate | ||||
| 
 | ||||
|     return validator(data) | ||||
| 
 | ||||
| 
 | ||||
| def _extract_features(info_data, rules): | ||||
|     """Find all the features enabled in rules.mk. | ||||
|     """ | ||||
|  | @ -258,7 +210,7 @@ def _extract_config_h(info_data): | |||
| 
 | ||||
|     # Pull in data from the json map | ||||
|     dotty_info = dotty(info_data) | ||||
|     info_config_map = _json_load(Path('data/mappings/info_config.json')) | ||||
|     info_config_map = json_load(Path('data/mappings/info_config.json')) | ||||
| 
 | ||||
|     for config_key, info_dict in info_config_map.items(): | ||||
|         info_key = info_dict['info_key'] | ||||
|  | @ -326,7 +278,7 @@ def _extract_rules_mk(info_data): | |||
| 
 | ||||
|     # Pull in data from the json map | ||||
|     dotty_info = dotty(info_data) | ||||
|     info_rules_map = _json_load(Path('data/mappings/info_rules.json')) | ||||
|     info_rules_map = json_load(Path('data/mappings/info_rules.json')) | ||||
| 
 | ||||
|     for rules_key, info_dict in info_rules_map.items(): | ||||
|         info_key = info_dict['info_key'] | ||||
|  | @ -516,25 +468,12 @@ def unknown_processor_rules(info_data, rules): | |||
|     return info_data | ||||
| 
 | ||||
| 
 | ||||
| def deep_update(origdict, newdict): | ||||
|     """Update a dictionary in place, recursing to do a deep copy. | ||||
|     """ | ||||
|     for key, value in newdict.items(): | ||||
|         if isinstance(value, Mapping): | ||||
|             origdict[key] = deep_update(origdict.get(key, {}), value) | ||||
| 
 | ||||
|         else: | ||||
|             origdict[key] = value | ||||
| 
 | ||||
|     return origdict | ||||
| 
 | ||||
| 
 | ||||
| def merge_info_jsons(keyboard, info_data): | ||||
|     """Return a merged copy of all the info.json files for a keyboard. | ||||
|     """ | ||||
|     for info_file in find_info_json(keyboard): | ||||
|         # Load and validate the JSON data | ||||
|         new_info_data = _json_load(info_file) | ||||
|         new_info_data = json_load(info_file) | ||||
| 
 | ||||
|         if not isinstance(new_info_data, dict): | ||||
|             _log_error(info_data, "Invalid file %s, root object should be a dictionary." % (str(info_file),)) | ||||
|  |  | |||
							
								
								
									
										68
									
								
								lib/python/qmk/json_schema.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								lib/python/qmk/json_schema.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,68 @@ | |||
| """Functions that help us generate and use info.json files. | ||||
| """ | ||||
| import json | ||||
| from collections.abc import Mapping | ||||
| from pathlib import Path | ||||
| 
 | ||||
| import hjson | ||||
| import jsonschema | ||||
| from milc import cli | ||||
| 
 | ||||
| 
 | ||||
| def json_load(json_file): | ||||
|     """Load a json file from disk. | ||||
| 
 | ||||
|     Note: file must be a Path object. | ||||
|     """ | ||||
|     try: | ||||
|         return hjson.load(json_file.open()) | ||||
| 
 | ||||
|     except json.decoder.JSONDecodeError as e: | ||||
|         cli.log.error('Invalid JSON encountered attempting to load {fg_cyan}%s{fg_reset}:\n\t{fg_red}%s', json_file, e) | ||||
|         exit(1) | ||||
| 
 | ||||
| 
 | ||||
| def load_jsonschema(schema_name): | ||||
|     """Read a jsonschema file from disk. | ||||
| 
 | ||||
|     FIXME(skullydazed/anyone): Refactor to make this a public function. | ||||
|     """ | ||||
|     schema_path = Path(f'data/schemas/{schema_name}.jsonschema') | ||||
| 
 | ||||
|     if not schema_path.exists(): | ||||
|         schema_path = Path('data/schemas/false.jsonschema') | ||||
| 
 | ||||
|     return json_load(schema_path) | ||||
| 
 | ||||
| 
 | ||||
| def keyboard_validate(data): | ||||
|     """Validates data against the keyboard jsonschema. | ||||
|     """ | ||||
|     schema = load_jsonschema('keyboard') | ||||
|     validator = jsonschema.Draft7Validator(schema).validate | ||||
| 
 | ||||
|     return validator(data) | ||||
| 
 | ||||
| 
 | ||||
| def keyboard_api_validate(data): | ||||
|     """Validates data against the api_keyboard jsonschema. | ||||
|     """ | ||||
|     base = load_jsonschema('keyboard') | ||||
|     relative = load_jsonschema('api_keyboard') | ||||
|     resolver = jsonschema.RefResolver.from_schema(base) | ||||
|     validator = jsonschema.Draft7Validator(relative, resolver=resolver).validate | ||||
| 
 | ||||
|     return validator(data) | ||||
| 
 | ||||
| 
 | ||||
| def deep_update(origdict, newdict): | ||||
|     """Update a dictionary in place, recursing to do a deep copy. | ||||
|     """ | ||||
|     for key, value in newdict.items(): | ||||
|         if isinstance(value, Mapping): | ||||
|             origdict[key] = deep_update(origdict.get(key, {}), value) | ||||
| 
 | ||||
|         else: | ||||
|             origdict[key] = value | ||||
| 
 | ||||
|     return origdict | ||||
|  | @ -7,7 +7,9 @@ import os | |||
| from glob import glob | ||||
| 
 | ||||
| from qmk.c_parse import parse_config_h_file | ||||
| from qmk.json_schema import json_load | ||||
| from qmk.makefile import parse_rules_mk_file | ||||
| from qmk.path import is_keyboard | ||||
| 
 | ||||
| BOX_DRAWING_CHARACTERS = { | ||||
|     "unicode": { | ||||
|  | @ -31,6 +33,28 @@ BOX_DRAWING_CHARACTERS = { | |||
| base_path = os.path.join(os.getcwd(), "keyboards") + os.path.sep | ||||
| 
 | ||||
| 
 | ||||
| def keyboard_folder(keyboard): | ||||
|     """Returns the actual keyboard folder. | ||||
| 
 | ||||
|     This checks aliases and DEFAULT_FOLDER to resolve the actual path for a keyboard. | ||||
|     """ | ||||
|     aliases = json_load(Path('data/mappings/keyboard_aliases.json')) | ||||
| 
 | ||||
|     if keyboard in aliases: | ||||
|         keyboard = aliases[keyboard].get('target', keyboard) | ||||
| 
 | ||||
|     rules_mk_file = Path(base_path, keyboard, 'rules.mk') | ||||
| 
 | ||||
|     if rules_mk_file.exists(): | ||||
|         rules_mk = parse_rules_mk_file(rules_mk_file) | ||||
|         keyboard = rules_mk.get('DEFAULT_FOLDER', keyboard) | ||||
| 
 | ||||
|     if not is_keyboard(keyboard): | ||||
|         raise ValueError(f'Invalid keyboard: {keyboard}') | ||||
| 
 | ||||
|     return keyboard | ||||
| 
 | ||||
| 
 | ||||
| def _find_name(path): | ||||
|     """Determine the keyboard name by stripping off the base_path and rules.mk. | ||||
|     """ | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ def is_keyboard(keyboard_name): | |||
|     if keyboard_name: | ||||
|         keyboard_path = QMK_FIRMWARE / 'keyboards' / keyboard_name | ||||
|         rules_mk = keyboard_path / 'rules.mk' | ||||
| 
 | ||||
|         return rules_mk.exists() | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -134,8 +134,8 @@ def test_list_keymaps_vendor_kb_rev(): | |||
| 
 | ||||
| def test_list_keymaps_no_keyboard_found(): | ||||
|     result = check_subcommand('list-keymaps', '-kb', 'asdfghjkl') | ||||
|     check_returncode(result, [1]) | ||||
|     assert 'does not exist' in result.stdout | ||||
|     check_returncode(result, [2]) | ||||
|     assert 'invalid keyboard_folder value' in result.stdout | ||||
| 
 | ||||
| 
 | ||||
| def test_json2c(): | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 QMK Bot
						QMK Bot