diff options
author | Zach White <skullydazed@gmail.com> | 2021-02-27 12:00:50 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-27 12:00:50 -0800 |
commit | 1581ea48dcd48d0d3f42cc09b388c468aedec45d (patch) | |
tree | 2d028036a4bf80c2e47b952931544f95ba2174e9 /lib/python | |
parent | 23ed6c4ec0bfb27612da8a7b78d1b484acc23f3f (diff) | |
download | qmk_firmware-1581ea48dcd48d0d3f42cc09b388c468aedec45d.tar.gz qmk_firmware-1581ea48dcd48d0d3f42cc09b388c468aedec45d.zip |
Fix develop (#12039)
Fixes file encoding errors on Windows, and layouts not correctly merging into info.json.
* force utf8 encoding
* correctly merge layouts and layout aliases
* show what aliases point to
Diffstat (limited to 'lib/python')
-rw-r--r-- | lib/python/qmk/c_parse.py | 11 | ||||
-rw-r--r-- | lib/python/qmk/cli/chibios/confmigrate.py | 8 | ||||
-rwxr-xr-x | lib/python/qmk/cli/generate/layouts.py | 4 | ||||
-rwxr-xr-x | lib/python/qmk/cli/info.py | 7 | ||||
-rwxr-xr-x | lib/python/qmk/cli/kle2json.py | 2 | ||||
-rw-r--r-- | lib/python/qmk/info.py | 44 | ||||
-rw-r--r-- | lib/python/qmk/keymap.py | 6 | ||||
-rw-r--r-- | lib/python/qmk/os_helpers/linux/__init__.py | 2 | ||||
-rw-r--r-- | lib/python/qmk/tests/test_cli_commands.py | 2 |
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 | ||
98 | def parse_config_h_file(config_h_file, config_h=None): | 93 | def 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 | ||
42 | def collect_defines(filepath): | 42 | def 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 | ||
416 | def _search_keyboard_h(path): | 421 | def _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 | ||
429 | def _find_all_layouts(info_data, keyboard): | 441 | def _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 | ||
447 | def _log_error(info_data, message): | 463 | def _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): | |||
16 | def check_subcommand_stdin(file_to_read, command, *args): | 16 | def 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 |