aboutsummaryrefslogtreecommitdiff
path: root/lib/python
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python')
-rw-r--r--lib/python/qmk/c_parse.py11
-rw-r--r--lib/python/qmk/cli/chibios/confmigrate.py8
-rwxr-xr-xlib/python/qmk/cli/generate/layouts.py4
-rwxr-xr-xlib/python/qmk/cli/info.py7
-rwxr-xr-xlib/python/qmk/cli/kle2json.py2
-rw-r--r--lib/python/qmk/info.py44
-rw-r--r--lib/python/qmk/keymap.py6
-rw-r--r--lib/python/qmk/os_helpers/linux/__init__.py2
-rw-r--r--lib/python/qmk/tests/test_cli_commands.py2
9 files changed, 56 insertions, 30 deletions
diff --git a/lib/python/qmk/c_parse.py b/lib/python/qmk/c_parse.py
index 89dd278b7..d4f39c883 100644
--- a/lib/python/qmk/c_parse.py
+++ b/lib/python/qmk/c_parse.py
@@ -46,7 +46,7 @@ def find_layouts(file):
46 parsed_layouts = {} 46 parsed_layouts = {}
47 47
48 # Search the file for LAYOUT macros and aliases 48 # Search the file for LAYOUT macros and aliases
49 file_contents = file.read_text() 49 file_contents = file.read_text(encoding='utf-8')
50 file_contents = comment_remover(file_contents) 50 file_contents = comment_remover(file_contents)
51 file_contents = file_contents.replace('\\\n', '') 51 file_contents = file_contents.replace('\\\n', '')
52 52
@@ -87,12 +87,7 @@ def find_layouts(file):
87 except ValueError: 87 except ValueError:
88 continue 88 continue
89 89
90 # Populate our aliases 90 return parsed_layouts, aliases
91 for alias, text in aliases.items():
92 if text in parsed_layouts and 'KEYMAP' not in alias:
93 parsed_layouts[alias] = parsed_layouts[text]
94
95 return parsed_layouts
96 91
97 92
98def parse_config_h_file(config_h_file, config_h=None): 93def parse_config_h_file(config_h_file, config_h=None):
@@ -104,7 +99,7 @@ def parse_config_h_file(config_h_file, config_h=None):
104 config_h_file = Path(config_h_file) 99 config_h_file = Path(config_h_file)
105 100
106 if config_h_file.exists(): 101 if config_h_file.exists():
107 config_h_text = config_h_file.read_text() 102 config_h_text = config_h_file.read_text(encoding='utf-8')
108 config_h_text = config_h_text.replace('\\\n', '') 103 config_h_text = config_h_text.replace('\\\n', '')
109 config_h_text = strip_multiline_comment(config_h_text) 104 config_h_text = strip_multiline_comment(config_h_text)
110 105
diff --git a/lib/python/qmk/cli/chibios/confmigrate.py b/lib/python/qmk/cli/chibios/confmigrate.py
index 3e348b2b0..89995931a 100644
--- a/lib/python/qmk/cli/chibios/confmigrate.py
+++ b/lib/python/qmk/cli/chibios/confmigrate.py
@@ -40,7 +40,7 @@ file_header = """\
40 40
41 41
42def collect_defines(filepath): 42def collect_defines(filepath):
43 with open(filepath, 'r') as f: 43 with open(filepath, 'r', encoding='utf-8') as f:
44 content = f.read() 44 content = f.read()
45 define_search = re.compile(r'(?m)^#\s*define\s+(?:.*\\\r?\n)*.*$', re.MULTILINE) 45 define_search = re.compile(r'(?m)^#\s*define\s+(?:.*\\\r?\n)*.*$', re.MULTILINE)
46 value_search = re.compile(r'^#\s*define\s+(?P<name>[a-zA-Z0-9_]+(\([^\)]*\))?)\s*(?P<value>.*)', re.DOTALL) 46 value_search = re.compile(r'^#\s*define\s+(?P<name>[a-zA-Z0-9_]+(\([^\)]*\))?)\s*(?P<value>.*)', re.DOTALL)
@@ -146,17 +146,17 @@ def chibios_confmigrate(cli):
146 if cli.args.input.name == "chconf.h" and ("CHCONF_H" in input_defs["dict"] or "_CHCONF_H_" in input_defs["dict"] or cli.args.force): 146 if cli.args.input.name == "chconf.h" and ("CHCONF_H" in input_defs["dict"] or "_CHCONF_H_" in input_defs["dict"] or cli.args.force):
147 migrate_chconf_h(to_override, outfile=sys.stdout) 147 migrate_chconf_h(to_override, outfile=sys.stdout)
148 if cli.args.overwrite: 148 if cli.args.overwrite:
149 with open(cli.args.input, "w") as out_file: 149 with open(cli.args.input, "w", encoding='utf-8') as out_file:
150 migrate_chconf_h(to_override, outfile=out_file) 150 migrate_chconf_h(to_override, outfile=out_file)
151 151
152 elif cli.args.input.name == "halconf.h" and ("HALCONF_H" in input_defs["dict"] or "_HALCONF_H_" in input_defs["dict"] or cli.args.force): 152 elif cli.args.input.name == "halconf.h" and ("HALCONF_H" in input_defs["dict"] or "_HALCONF_H_" in input_defs["dict"] or cli.args.force):
153 migrate_halconf_h(to_override, outfile=sys.stdout) 153 migrate_halconf_h(to_override, outfile=sys.stdout)
154 if cli.args.overwrite: 154 if cli.args.overwrite:
155 with open(cli.args.input, "w") as out_file: 155 with open(cli.args.input, "w", encoding='utf-8') as out_file:
156 migrate_halconf_h(to_override, outfile=out_file) 156 migrate_halconf_h(to_override, outfile=out_file)
157 157
158 elif cli.args.input.name == "mcuconf.h" and ("MCUCONF_H" in input_defs["dict"] or "_MCUCONF_H_" in input_defs["dict"] or cli.args.force): 158 elif cli.args.input.name == "mcuconf.h" and ("MCUCONF_H" in input_defs["dict"] or "_MCUCONF_H_" in input_defs["dict"] or cli.args.force):
159 migrate_mcuconf_h(to_override, outfile=sys.stdout) 159 migrate_mcuconf_h(to_override, outfile=sys.stdout)
160 if cli.args.overwrite: 160 if cli.args.overwrite:
161 with open(cli.args.input, "w") as out_file: 161 with open(cli.args.input, "w", encoding='utf-8') as out_file:
162 migrate_mcuconf_h(to_override, outfile=out_file) 162 migrate_mcuconf_h(to_override, outfile=out_file)
diff --git a/lib/python/qmk/cli/generate/layouts.py b/lib/python/qmk/cli/generate/layouts.py
index b7baae065..15b289522 100755
--- a/lib/python/qmk/cli/generate/layouts.py
+++ b/lib/python/qmk/cli/generate/layouts.py
@@ -82,6 +82,10 @@ def generate_layouts(cli):
82 layouts_h_lines.append(rows) 82 layouts_h_lines.append(rows)
83 layouts_h_lines.append('}') 83 layouts_h_lines.append('}')
84 84
85 for alias, target in kb_info_json.get('layout_aliases', {}).items():
86 layouts_h_lines.append('')
87 layouts_h_lines.append('#define %s %s' % (alias, target))
88
85 # Show the results 89 # Show the results
86 layouts_h = '\n'.join(layouts_h_lines) + '\n' 90 layouts_h = '\n'.join(layouts_h_lines) + '\n'
87 91
diff --git a/lib/python/qmk/cli/info.py b/lib/python/qmk/cli/info.py
index 87d7253d4..a7ce8abf0 100755
--- a/lib/python/qmk/cli/info.py
+++ b/lib/python/qmk/cli/info.py
@@ -29,7 +29,7 @@ def show_keymap(kb_info_json, title_caps=True):
29 else: 29 else:
30 cli.echo('{fg_blue}keymap_%s{fg_reset}:', cli.config.info.keymap) 30 cli.echo('{fg_blue}keymap_%s{fg_reset}:', cli.config.info.keymap)
31 31
32 keymap_data = json.load(keymap_path.open()) 32 keymap_data = json.load(keymap_path.open(encoding='utf-8'))
33 layout_name = keymap_data['layout'] 33 layout_name = keymap_data['layout']
34 34
35 for layer_num, layer in enumerate(keymap_data['layers']): 35 for layer_num, layer in enumerate(keymap_data['layers']):
@@ -57,7 +57,7 @@ def show_matrix(kb_info_json, title_caps=True):
57 # Build our label list 57 # Build our label list
58 labels = [] 58 labels = []
59 for key in layout['layout']: 59 for key in layout['layout']:
60 if key['matrix']: 60 if 'matrix' in key:
61 row = ROW_LETTERS[key['matrix'][0]] 61 row = ROW_LETTERS[key['matrix'][0]]
62 col = COL_LETTERS[key['matrix'][1]] 62 col = COL_LETTERS[key['matrix'][1]]
63 63
@@ -91,6 +91,9 @@ def print_friendly_output(kb_info_json):
91 cli.echo('{fg_blue}Size{fg_reset}: %s x %s' % (kb_info_json['width'], kb_info_json['height'])) 91 cli.echo('{fg_blue}Size{fg_reset}: %s x %s' % (kb_info_json['width'], kb_info_json['height']))
92 cli.echo('{fg_blue}Processor{fg_reset}: %s', kb_info_json.get('processor', 'Unknown')) 92 cli.echo('{fg_blue}Processor{fg_reset}: %s', kb_info_json.get('processor', 'Unknown'))
93 cli.echo('{fg_blue}Bootloader{fg_reset}: %s', kb_info_json.get('bootloader', 'Unknown')) 93 cli.echo('{fg_blue}Bootloader{fg_reset}: %s', kb_info_json.get('bootloader', 'Unknown'))
94 if 'layout_aliases' in kb_info_json:
95 aliases = [f'{key}={value}' for key, value in kb_info_json['layout_aliases'].items()]
96 cli.echo('{fg_blue}Layout aliases:{fg_reset} %s' % (', '.join(aliases),))
94 97
95 if cli.config.info.layouts: 98 if cli.config.info.layouts:
96 show_layouts(kb_info_json, True) 99 show_layouts(kb_info_json, True)
diff --git a/lib/python/qmk/cli/kle2json.py b/lib/python/qmk/cli/kle2json.py
index 66d504bfc..3bb744358 100755
--- a/lib/python/qmk/cli/kle2json.py
+++ b/lib/python/qmk/cli/kle2json.py
@@ -27,7 +27,7 @@ def kle2json(cli):
27 cli.log.error('File {fg_cyan}%s{style_reset_all} was not found.', file_path) 27 cli.log.error('File {fg_cyan}%s{style_reset_all} was not found.', file_path)
28 return False 28 return False
29 out_path = file_path.parent 29 out_path = file_path.parent
30 raw_code = file_path.open().read() 30 raw_code = file_path.read_text(encoding='utf-8')
31 # Check if info.json exists, allow overwrite with force 31 # Check if info.json exists, allow overwrite with force
32 if Path(out_path, "info.json").exists() and not cli.args.force: 32 if Path(out_path, "info.json").exists() and not cli.args.force:
33 cli.log.error('File {fg_cyan}%s/info.json{style_reset_all} already exists, use -f or --force to overwrite.', out_path) 33 cli.log.error('File {fg_cyan}%s/info.json{style_reset_all} already exists, use -f or --force to overwrite.', out_path)
diff --git a/lib/python/qmk/info.py b/lib/python/qmk/info.py
index 2accaba9e..cf5dc6640 100644
--- a/lib/python/qmk/info.py
+++ b/lib/python/qmk/info.py
@@ -45,7 +45,12 @@ def info_json(keyboard):
45 info_data['keymaps'][keymap.name] = {'url': f'https://raw.githubusercontent.com/qmk/qmk_firmware/master/{keymap}/keymap.json'} 45 info_data['keymaps'][keymap.name] = {'url': f'https://raw.githubusercontent.com/qmk/qmk_firmware/master/{keymap}/keymap.json'}
46 46
47 # Populate layout data 47 # Populate layout data
48 for layout_name, layout_json in _find_all_layouts(info_data, keyboard).items(): 48 layouts, aliases = _find_all_layouts(info_data, keyboard)
49
50 if aliases:
51 info_data['layout_aliases'] = aliases
52
53 for layout_name, layout_json in layouts.items():
49 if not layout_name.startswith('LAYOUT_kc'): 54 if not layout_name.startswith('LAYOUT_kc'):
50 layout_json['c_macro'] = True 55 layout_json['c_macro'] = True
51 info_data['layouts'][layout_name] = layout_json 56 info_data['layouts'][layout_name] = layout_json
@@ -92,7 +97,7 @@ def _json_load(json_file):
92 Note: file must be a Path object. 97 Note: file must be a Path object.
93 """ 98 """
94 try: 99 try:
95 return hjson.load(json_file.open()) 100 return hjson.load(json_file.open(encoding='utf-8'))
96 101
97 except json.decoder.JSONDecodeError as e: 102 except json.decoder.JSONDecodeError as e:
98 cli.log.error('Invalid JSON encountered attempting to load {fg_cyan}%s{fg_reset}:\n\t{fg_red}%s', json_file, e) 103 cli.log.error('Invalid JSON encountered attempting to load {fg_cyan}%s{fg_reset}:\n\t{fg_red}%s', json_file, e)
@@ -415,21 +420,28 @@ def _merge_layouts(info_data, new_info_data):
415 420
416def _search_keyboard_h(path): 421def _search_keyboard_h(path):
417 current_path = Path('keyboards/') 422 current_path = Path('keyboards/')
423 aliases = {}
418 layouts = {} 424 layouts = {}
425
419 for directory in path.parts: 426 for directory in path.parts:
420 current_path = current_path / directory 427 current_path = current_path / directory
421 keyboard_h = '%s.h' % (directory,) 428 keyboard_h = '%s.h' % (directory,)
422 keyboard_h_path = current_path / keyboard_h 429 keyboard_h_path = current_path / keyboard_h
423 if keyboard_h_path.exists(): 430 if keyboard_h_path.exists():
424 layouts.update(find_layouts(keyboard_h_path)) 431 new_layouts, new_aliases = find_layouts(keyboard_h_path)
432 layouts.update(new_layouts)
433
434 for alias, alias_text in new_aliases.items():
435 if alias_text in layouts:
436 aliases[alias] = alias_text
425 437
426 return layouts 438 return layouts, aliases
427 439
428 440
429def _find_all_layouts(info_data, keyboard): 441def _find_all_layouts(info_data, keyboard):
430 """Looks for layout macros associated with this keyboard. 442 """Looks for layout macros associated with this keyboard.
431 """ 443 """
432 layouts = _search_keyboard_h(Path(keyboard)) 444 layouts, aliases = _search_keyboard_h(Path(keyboard))
433 445
434 if not layouts: 446 if not layouts:
435 # If we don't find any layouts from info.json or keyboard.h we widen our search. This is error prone which is why we want to encourage people to follow the standard above. 447 # If we don't find any layouts from info.json or keyboard.h we widen our search. This is error prone which is why we want to encourage people to follow the standard above.
@@ -437,11 +449,15 @@ def _find_all_layouts(info_data, keyboard):
437 449
438 for file in glob('keyboards/%s/*.h' % keyboard): 450 for file in glob('keyboards/%s/*.h' % keyboard):
439 if file.endswith('.h'): 451 if file.endswith('.h'):
440 these_layouts = find_layouts(file) 452 these_layouts, these_aliases = find_layouts(file)
453
441 if these_layouts: 454 if these_layouts:
442 layouts.update(these_layouts) 455 layouts.update(these_layouts)
443 456
444 return layouts 457 if these_aliases:
458 aliases.update(these_aliases)
459
460 return layouts, aliases
445 461
446 462
447def _log_error(info_data, message): 463def _log_error(info_data, message):
@@ -540,11 +556,19 @@ def merge_info_jsons(keyboard, info_data):
540 cli.log.error('\t%s: %s', json_path, e.message) 556 cli.log.error('\t%s: %s', json_path, e.message)
541 continue 557 continue
542 558
543 # Mark the layouts as coming from json 559 # Merge layout data in
544 for layout in new_info_data.get('layouts', {}).values(): 560 for layout_name, layout in new_info_data.get('layouts', {}).items():
545 layout['c_macro'] = False 561 if layout_name in info_data['layouts']:
562 for new_key, existing_key in zip(layout['layout'], info_data['layouts'][layout_name]['layout']):
563 existing_key.update(new_key)
564 else:
565 layout['c_macro'] = False
566 info_data['layouts'][layout_name] = layout
546 567
547 # Update info_data with the new data 568 # Update info_data with the new data
569 if 'layouts' in new_info_data:
570 del (new_info_data['layouts'])
571
548 deep_update(info_data, new_info_data) 572 deep_update(info_data, new_info_data)
549 573
550 return info_data 574 return info_data
diff --git a/lib/python/qmk/keymap.py b/lib/python/qmk/keymap.py
index 266532f50..d8495c38b 100644
--- a/lib/python/qmk/keymap.py
+++ b/lib/python/qmk/keymap.py
@@ -42,7 +42,7 @@ def template_json(keyboard):
42 template_file = Path('keyboards/%s/templates/keymap.json' % keyboard) 42 template_file = Path('keyboards/%s/templates/keymap.json' % keyboard)
43 template = {'keyboard': keyboard} 43 template = {'keyboard': keyboard}
44 if template_file.exists(): 44 if template_file.exists():
45 template.update(json.loads(template_file.read_text())) 45 template.update(json.load(template_file.open(encoding='utf-8')))
46 46
47 return template 47 return template
48 48
@@ -58,7 +58,7 @@ def template_c(keyboard):
58 """ 58 """
59 template_file = Path('keyboards/%s/templates/keymap.c' % keyboard) 59 template_file = Path('keyboards/%s/templates/keymap.c' % keyboard)
60 if template_file.exists(): 60 if template_file.exists():
61 template = template_file.read_text() 61 template = template_file.read_text(encoding='utf-8')
62 else: 62 else:
63 template = DEFAULT_KEYMAP_C 63 template = DEFAULT_KEYMAP_C
64 64
@@ -469,7 +469,7 @@ def parse_keymap_c(keymap_file, use_cpp=True):
469 if use_cpp: 469 if use_cpp:
470 keymap_file = _c_preprocess(keymap_file) 470 keymap_file = _c_preprocess(keymap_file)
471 else: 471 else:
472 keymap_file = keymap_file.read_text() 472 keymap_file = keymap_file.read_text(encoding='utf-8')
473 473
474 keymap = dict() 474 keymap = dict()
475 keymap['layers'] = _get_layers(keymap_file) 475 keymap['layers'] = _get_layers(keymap_file)
diff --git a/lib/python/qmk/os_helpers/linux/__init__.py b/lib/python/qmk/os_helpers/linux/__init__.py
index a04ac4f8a..9e73964e4 100644
--- a/lib/python/qmk/os_helpers/linux/__init__.py
+++ b/lib/python/qmk/os_helpers/linux/__init__.py
@@ -95,7 +95,7 @@ def check_udev_rules():
95 95
96 # Collect all rules from the config files 96 # Collect all rules from the config files
97 for rule_file in udev_rules: 97 for rule_file in udev_rules:
98 for line in rule_file.read_text().split('\n'): 98 for line in rule_file.read_text(encoding='utf-8').split('\n'):
99 line = line.strip() 99 line = line.strip()
100 if not line.startswith("#") and len(line): 100 if not line.startswith("#") and len(line):
101 current_rules.add(line) 101 current_rules.add(line)
diff --git a/lib/python/qmk/tests/test_cli_commands.py b/lib/python/qmk/tests/test_cli_commands.py
index 3efeddb85..82c42a20e 100644
--- a/lib/python/qmk/tests/test_cli_commands.py
+++ b/lib/python/qmk/tests/test_cli_commands.py
@@ -16,7 +16,7 @@ def check_subcommand(command, *args):
16def check_subcommand_stdin(file_to_read, command, *args): 16def check_subcommand_stdin(file_to_read, command, *args):
17 """Pipe content of a file to a command and return output. 17 """Pipe content of a file to a command and return output.
18 """ 18 """
19 with open(file_to_read) as my_file: 19 with open(file_to_read, encoding='utf-8') as my_file:
20 cmd = ['bin/qmk', command, *args] 20 cmd = ['bin/qmk', command, *args]
21 result = run(cmd, stdin=my_file, stdout=PIPE, stderr=STDOUT, universal_newlines=True) 21 result = run(cmd, stdin=my_file, stdout=PIPE, stderr=STDOUT, universal_newlines=True)
22 return result 22 return result