diff options
Diffstat (limited to 'lib/python')
| -rw-r--r-- | lib/python/milc.py | 88 | ||||
| -rw-r--r-- | lib/python/qmk/cli/__init__.py | 7 | ||||
| -rw-r--r-- | lib/python/qmk/cli/cformat.py | 5 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/doctor.py | 11 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/json2c.py | 8 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/kle2json.py | 8 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/new/keymap.py | 2 | ||||
| -rw-r--r-- | lib/python/qmk/keymap.py | 5 |
8 files changed, 74 insertions, 60 deletions
diff --git a/lib/python/milc.py b/lib/python/milc.py index 83edfc7f5..eb18984eb 100644 --- a/lib/python/milc.py +++ b/lib/python/milc.py | |||
| @@ -242,15 +242,24 @@ class SubparserWrapper(object): | |||
| 242 | 242 | ||
| 243 | This also stores the default for the argument in `self.cli.default_arguments`. | 243 | This also stores the default for the argument in `self.cli.default_arguments`. |
| 244 | """ | 244 | """ |
| 245 | if 'action' in kwargs and kwargs['action'] == 'store_boolean': | 245 | if kwargs.get('action') == 'store_boolean': |
| 246 | # Store boolean will call us again with the enable/disable flag arguments | 246 | # Store boolean will call us again with the enable/disable flag arguments |
| 247 | return handle_store_boolean(self, *args, **kwargs) | 247 | return handle_store_boolean(self, *args, **kwargs) |
| 248 | 248 | ||
| 249 | self.cli.acquire_lock() | 249 | self.cli.acquire_lock() |
| 250 | argument_name = self.cli.get_argument_name(*args, **kwargs) | ||
| 251 | |||
| 250 | self.subparser.add_argument(*args, **kwargs) | 252 | self.subparser.add_argument(*args, **kwargs) |
| 253 | |||
| 254 | if kwargs.get('action') == 'store_false': | ||
| 255 | self.cli._config_store_false.append(argument_name) | ||
| 256 | |||
| 257 | if kwargs.get('action') == 'store_true': | ||
| 258 | self.cli._config_store_true.append(argument_name) | ||
| 259 | |||
| 251 | if self.submodule not in self.cli.default_arguments: | 260 | if self.submodule not in self.cli.default_arguments: |
| 252 | self.cli.default_arguments[self.submodule] = {} | 261 | self.cli.default_arguments[self.submodule] = {} |
| 253 | self.cli.default_arguments[self.submodule][self.cli.get_argument_name(*args, **kwargs)] = kwargs.get('default') | 262 | self.cli.default_arguments[self.submodule][argument_name] = kwargs.get('default') |
| 254 | self.cli.release_lock() | 263 | self.cli.release_lock() |
| 255 | 264 | ||
| 256 | 265 | ||
| @@ -268,11 +277,13 @@ class MILC(object): | |||
| 268 | 277 | ||
| 269 | # Define some basic info | 278 | # Define some basic info |
| 270 | self.acquire_lock() | 279 | self.acquire_lock() |
| 280 | self._config_store_true = [] | ||
| 281 | self._config_store_false = [] | ||
| 271 | self._description = None | 282 | self._description = None |
| 272 | self._entrypoint = None | 283 | self._entrypoint = None |
| 273 | self._inside_context_manager = False | 284 | self._inside_context_manager = False |
| 274 | self.ansi = ansi_colors | 285 | self.ansi = ansi_colors |
| 275 | self.arg_only = [] | 286 | self.arg_only = {} |
| 276 | self.config = self.config_source = None | 287 | self.config = self.config_source = None |
| 277 | self.config_file = None | 288 | self.config_file = None |
| 278 | self.default_arguments = {} | 289 | self.default_arguments = {} |
| @@ -377,7 +388,7 @@ class MILC(object): | |||
| 377 | self.add_argument('--log-file', help='File to write log messages to') | 388 | self.add_argument('--log-file', help='File to write log messages to') |
| 378 | self.add_argument('--color', action='store_boolean', default=True, help='color in output') | 389 | self.add_argument('--color', action='store_boolean', default=True, help='color in output') |
| 379 | self.add_argument('--config-file', help='The location for the configuration file') | 390 | self.add_argument('--config-file', help='The location for the configuration file') |
| 380 | self.arg_only.append('config_file') | 391 | self.arg_only['config_file'] = ['general'] |
| 381 | 392 | ||
| 382 | def add_subparsers(self, title='Sub-commands', **kwargs): | 393 | def add_subparsers(self, title='Sub-commands', **kwargs): |
| 383 | if self._inside_context_manager: | 394 | if self._inside_context_manager: |
| @@ -427,17 +438,20 @@ class MILC(object): | |||
| 427 | raise RuntimeError('You must run this before the with statement!') | 438 | raise RuntimeError('You must run this before the with statement!') |
| 428 | 439 | ||
| 429 | def argument_function(handler): | 440 | def argument_function(handler): |
| 430 | if 'arg_only' in kwargs and kwargs['arg_only']: | 441 | subcommand_name = handler.__name__.replace("_", "-") |
| 442 | |||
| 443 | if kwargs.get('arg_only'): | ||
| 431 | arg_name = self.get_argument_name(*args, **kwargs) | 444 | arg_name = self.get_argument_name(*args, **kwargs) |
| 432 | self.arg_only.append(arg_name) | 445 | if arg_name not in self.arg_only: |
| 446 | self.arg_only[arg_name] = [] | ||
| 447 | self.arg_only[arg_name].append(subcommand_name) | ||
| 433 | del kwargs['arg_only'] | 448 | del kwargs['arg_only'] |
| 434 | 449 | ||
| 435 | name = handler.__name__.replace("_", "-") | ||
| 436 | if handler is self._entrypoint: | 450 | if handler is self._entrypoint: |
| 437 | self.add_argument(*args, **kwargs) | 451 | self.add_argument(*args, **kwargs) |
| 438 | 452 | ||
| 439 | elif name in self.subcommands: | 453 | elif subcommand_name in self.subcommands: |
| 440 | self.subcommands[name].add_argument(*args, **kwargs) | 454 | self.subcommands[subcommand_name].add_argument(*args, **kwargs) |
| 441 | 455 | ||
| 442 | else: | 456 | else: |
| 443 | raise RuntimeError('Decorated function is not entrypoint or subcommand!') | 457 | raise RuntimeError('Decorated function is not entrypoint or subcommand!') |
| @@ -511,35 +525,37 @@ class MILC(object): | |||
| 511 | if argument in ('subparsers', 'entrypoint'): | 525 | if argument in ('subparsers', 'entrypoint'): |
| 512 | continue | 526 | continue |
| 513 | 527 | ||
| 514 | if argument not in self.arg_only: | 528 | # Find the argument's section |
| 515 | # Find the argument's section | 529 | # Underscores in command's names are converted to dashes during initialization. |
| 516 | # Underscores in command's names are converted to dashes during initialization. | 530 | # TODO(Erovia) Find a better solution |
| 517 | # TODO(Erovia) Find a better solution | 531 | entrypoint_name = self._entrypoint.__name__.replace("_", "-") |
| 518 | entrypoint_name = self._entrypoint.__name__.replace("_", "-") | 532 | if entrypoint_name in self.default_arguments and argument in self.default_arguments[entrypoint_name]: |
| 519 | if entrypoint_name in self.default_arguments and argument in self.default_arguments[entrypoint_name]: | 533 | argument_found = True |
| 520 | argument_found = True | 534 | section = self._entrypoint.__name__ |
| 521 | section = self._entrypoint.__name__ | 535 | if argument in self.default_arguments['general']: |
| 522 | if argument in self.default_arguments['general']: | 536 | argument_found = True |
| 523 | argument_found = True | 537 | section = 'general' |
| 524 | section = 'general' | 538 | |
| 525 | 539 | if not argument_found: | |
| 526 | if not argument_found: | 540 | raise RuntimeError('Could not find argument in `self.default_arguments`. This should be impossible!') |
| 527 | raise RuntimeError('Could not find argument in `self.default_arguments`. This should be impossible!') | 541 | exit(1) |
| 528 | exit(1) | 542 | |
| 543 | if argument not in self.arg_only or section not in self.arg_only[argument]: | ||
| 544 | # Determine the arg value and source | ||
| 545 | arg_value = getattr(self.args, argument) | ||
| 546 | if argument in self._config_store_true and arg_value: | ||
| 547 | passed_on_cmdline = True | ||
| 548 | elif argument in self._config_store_false and not arg_value: | ||
| 549 | passed_on_cmdline = True | ||
| 550 | elif arg_value is not None: | ||
| 551 | passed_on_cmdline = True | ||
| 552 | else: | ||
| 553 | passed_on_cmdline = False | ||
| 529 | 554 | ||
| 530 | # Merge this argument into self.config | 555 | # Merge this argument into self.config |
| 531 | if argument in self.default_arguments['general'] or argument in self.default_arguments[entrypoint_name]: | 556 | if passed_on_cmdline and (argument in self.default_arguments['general'] or argument in self.default_arguments[entrypoint_name] or argument not in self.config[entrypoint_name]): |
| 532 | arg_value = getattr(self.args, argument) | 557 | self.config[section][argument] = arg_value |
| 533 | if arg_value is not None: | 558 | self.config_source[section][argument] = 'argument' |
| 534 | self.config[section][argument] = arg_value | ||
| 535 | self.config_source[section][argument] = 'argument' | ||
| 536 | else: | ||
| 537 | if argument not in self.config[entrypoint_name]: | ||
| 538 | # Check if the argument exist for this section | ||
| 539 | arg = getattr(self.args, argument) | ||
| 540 | if arg is not None: | ||
| 541 | self.config[section][argument] = arg | ||
| 542 | self.config_source[section][argument] = 'argument' | ||
| 543 | 559 | ||
| 544 | self.release_lock() | 560 | self.release_lock() |
| 545 | 561 | ||
diff --git a/lib/python/qmk/cli/__init__.py b/lib/python/qmk/cli/__init__.py index eb524217c..394a1353b 100644 --- a/lib/python/qmk/cli/__init__.py +++ b/lib/python/qmk/cli/__init__.py | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | 2 | ||
| 3 | We list each subcommand here explicitly because all the reliable ways of searching for modules are slow and delay startup. | 3 | We list each subcommand here explicitly because all the reliable ways of searching for modules are slow and delay startup. |
| 4 | """ | 4 | """ |
| 5 | import sys | ||
| 6 | |||
| 5 | from milc import cli | 7 | from milc import cli |
| 6 | 8 | ||
| 7 | from . import cformat | 9 | from . import cformat |
| @@ -19,5 +21,6 @@ from . import new | |||
| 19 | from . import pyformat | 21 | from . import pyformat |
| 20 | from . import pytest | 22 | from . import pytest |
| 21 | 23 | ||
| 22 | if not hasattr(cli, 'config_source'): | 24 | if sys.version_info[0] != 3 or sys.version_info[1] < 6: |
| 23 | cli.log.warning("Your QMK CLI is out of date. Please upgrade with `pip3 install --upgrade qmk` or by using your package manager.") | 25 | cli.log.error('Your Python is too old! Please upgrade to Python 3.6 or later.') |
| 26 | exit(127) | ||
diff --git a/lib/python/qmk/cli/cformat.py b/lib/python/qmk/cli/cformat.py index 536ee30fd..0cd8b6192 100644 --- a/lib/python/qmk/cli/cformat.py +++ b/lib/python/qmk/cli/cformat.py | |||
| @@ -22,9 +22,8 @@ def cformat_run(files, all_files): | |||
| 22 | cli.log.warn('No changes detected. Use "qmk cformat -a" to format all files') | 22 | cli.log.warn('No changes detected. Use "qmk cformat -a" to format all files') |
| 23 | return False | 23 | return False |
| 24 | if files and all_files: | 24 | if files and all_files: |
| 25 | cli.log.warning('Filenames passed with -a, only formatting: %s', ','.join(cli.args.files)) | 25 | cli.log.warning('Filenames passed with -a, only formatting: %s', ','.join(files)) |
| 26 | # 3.6+: Can remove the str casting, python will cast implicitly | 26 | subprocess.run(clang_format + [file for file in files], check=True) |
| 27 | subprocess.run(clang_format + [str(file) for file in files], check=True) | ||
| 28 | cli.log.info('Successfully formatted the C code.') | 27 | cli.log.info('Successfully formatted the C code.') |
| 29 | 28 | ||
| 30 | except subprocess.CalledProcessError: | 29 | except subprocess.CalledProcessError: |
diff --git a/lib/python/qmk/cli/doctor.py b/lib/python/qmk/cli/doctor.py index 3c74fae69..3c4624837 100755 --- a/lib/python/qmk/cli/doctor.py +++ b/lib/python/qmk/cli/doctor.py | |||
| @@ -135,16 +135,15 @@ def check_udev_rules(): | |||
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | if udev_dir.exists(): | 137 | if udev_dir.exists(): |
| 138 | udev_rules = [str(rule_file) for rule_file in udev_dir.glob('*.rules')] | 138 | udev_rules = [rule_file for rule_file in udev_dir.glob('*.rules')] |
| 139 | current_rules = set() | 139 | current_rules = set() |
| 140 | 140 | ||
| 141 | # Collect all rules from the config files | 141 | # Collect all rules from the config files |
| 142 | for rule_file in udev_rules: | 142 | for rule_file in udev_rules: |
| 143 | with open(rule_file, "r") as fd: | 143 | for line in rule_file.read_text().split('\n'): |
| 144 | for line in fd.readlines(): | 144 | line = line.strip() |
| 145 | line = line.strip() | 145 | if not line.startswith("#") and len(line): |
| 146 | if not line.startswith("#") and len(line): | 146 | current_rules.add(line) |
| 147 | current_rules.add(line) | ||
| 148 | 147 | ||
| 149 | # Check if the desired rules are among the currently present rules | 148 | # Check if the desired rules are among the currently present rules |
| 150 | for bootloader, rules in desired_rules.items(): | 149 | for bootloader, rules in desired_rules.items(): |
diff --git a/lib/python/qmk/cli/json2c.py b/lib/python/qmk/cli/json2c.py index 46c4d04bb..521840507 100755 --- a/lib/python/qmk/cli/json2c.py +++ b/lib/python/qmk/cli/json2c.py | |||
| @@ -10,29 +10,27 @@ import qmk.path | |||
| 10 | 10 | ||
| 11 | @cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to') | 11 | @cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to') |
| 12 | @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") | 12 | @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") |
| 13 | @cli.argument('filename', arg_only=True, help='Configurator JSON file') | 13 | @cli.argument('filename', type=qmk.path.normpath, arg_only=True, help='Configurator JSON file') |
| 14 | @cli.subcommand('Creates a keymap.c from a QMK Configurator export.') | 14 | @cli.subcommand('Creates a keymap.c from a QMK Configurator export.') |
| 15 | def json2c(cli): | 15 | def json2c(cli): |
| 16 | """Generate a keymap.c from a configurator export. | 16 | """Generate a keymap.c from a configurator export. |
| 17 | 17 | ||
| 18 | This command uses the `qmk.keymap` module to generate a keymap.c from a configurator export. The generated keymap is written to stdout, or to a file if -o is provided. | 18 | This command uses the `qmk.keymap` module to generate a keymap.c from a configurator export. The generated keymap is written to stdout, or to a file if -o is provided. |
| 19 | """ | 19 | """ |
| 20 | cli.args.filename = qmk.path.normpath(cli.args.filename) | ||
| 21 | |||
| 22 | # Error checking | 20 | # Error checking |
| 23 | if not cli.args.filename.exists(): | 21 | if not cli.args.filename.exists(): |
| 24 | cli.log.error('JSON file does not exist!') | 22 | cli.log.error('JSON file does not exist!') |
| 25 | cli.print_usage() | 23 | cli.print_usage() |
| 26 | exit(1) | 24 | exit(1) |
| 27 | 25 | ||
| 28 | if str(cli.args.filename) == '-': | 26 | if cli.args.filename.name == '-': |
| 29 | # TODO(skullydazed/anyone): Read file contents from STDIN | 27 | # TODO(skullydazed/anyone): Read file contents from STDIN |
| 30 | cli.log.error('Reading from STDIN is not (yet) supported.') | 28 | cli.log.error('Reading from STDIN is not (yet) supported.') |
| 31 | cli.print_usage() | 29 | cli.print_usage() |
| 32 | exit(1) | 30 | exit(1) |
| 33 | 31 | ||
| 34 | # Environment processing | 32 | # Environment processing |
| 35 | if cli.args.output == ('-'): | 33 | if cli.args.output.name == ('-'): |
| 36 | cli.args.output = None | 34 | cli.args.output = None |
| 37 | 35 | ||
| 38 | # Parse the configurator json | 36 | # Parse the configurator json |
diff --git a/lib/python/qmk/cli/kle2json.py b/lib/python/qmk/cli/kle2json.py index 3ed6594e0..5268462f9 100755 --- a/lib/python/qmk/cli/kle2json.py +++ b/lib/python/qmk/cli/kle2json.py | |||
| @@ -37,12 +37,12 @@ def kle2json(cli): | |||
| 37 | file_path = Path(os.environ['ORIG_CWD'], cli.args.filename) | 37 | file_path = Path(os.environ['ORIG_CWD'], cli.args.filename) |
| 38 | # Check for valid file_path for more graceful failure | 38 | # Check for valid file_path for more graceful failure |
| 39 | if not file_path.exists(): | 39 | if not file_path.exists(): |
| 40 | return cli.log.error('File {fg_cyan}%s{style_reset_all} was not found.', str(file_path)) | 40 | return cli.log.error('File {fg_cyan}%s{style_reset_all} was not found.', file_path) |
| 41 | out_path = file_path.parent | 41 | out_path = file_path.parent |
| 42 | raw_code = file_path.open().read() | 42 | raw_code = file_path.open().read() |
| 43 | # Check if info.json exists, allow overwrite with force | 43 | # Check if info.json exists, allow overwrite with force |
| 44 | if Path(out_path, "info.json").exists() and not cli.args.force: | 44 | if Path(out_path, "info.json").exists() and not cli.args.force: |
| 45 | cli.log.error('File {fg_cyan}%s/info.json{style_reset_all} already exists, use -f or --force to overwrite.', str(out_path)) | 45 | cli.log.error('File {fg_cyan}%s/info.json{style_reset_all} already exists, use -f or --force to overwrite.', out_path) |
| 46 | return False | 46 | return False |
| 47 | try: | 47 | try: |
| 48 | # Convert KLE raw to x/y coordinates (using kle2xy package from skullydazed) | 48 | # Convert KLE raw to x/y coordinates (using kle2xy package from skullydazed) |
| @@ -69,7 +69,7 @@ def kle2json(cli): | |||
| 69 | # Replace layout in keyboard json | 69 | # Replace layout in keyboard json |
| 70 | keyboard = keyboard.replace('"LAYOUT_JSON_HERE"', layout) | 70 | keyboard = keyboard.replace('"LAYOUT_JSON_HERE"', layout) |
| 71 | # Write our info.json | 71 | # Write our info.json |
| 72 | file = open(str(out_path) + "/info.json", "w") | 72 | file = open(out_path + "/info.json", "w") |
| 73 | file.write(keyboard) | 73 | file.write(keyboard) |
| 74 | file.close() | 74 | file.close() |
| 75 | cli.log.info('Wrote out {fg_cyan}%s/info.json', str(out_path)) | 75 | cli.log.info('Wrote out {fg_cyan}%s/info.json', out_path) |
diff --git a/lib/python/qmk/cli/new/keymap.py b/lib/python/qmk/cli/new/keymap.py index 5ae262856..474fe7974 100755 --- a/lib/python/qmk/cli/new/keymap.py +++ b/lib/python/qmk/cli/new/keymap.py | |||
| @@ -40,7 +40,7 @@ def new_keymap(cli): | |||
| 40 | exit(1) | 40 | exit(1) |
| 41 | 41 | ||
| 42 | # create user directory with default keymap files | 42 | # create user directory with default keymap files |
| 43 | shutil.copytree(str(keymap_path_default), str(keymap_path_new), symlinks=True) | 43 | shutil.copytree(keymap_path_default, keymap_path_new, symlinks=True) |
| 44 | 44 | ||
| 45 | # end message to user | 45 | # end message to user |
| 46 | cli.log.info("%s keymap directory created in: %s", keymap, keymap_path_new) | 46 | cli.log.info("%s keymap directory created in: %s", keymap, keymap_path_new) |
diff --git a/lib/python/qmk/keymap.py b/lib/python/qmk/keymap.py index 4aa87de20..69cdc8d5b 100644 --- a/lib/python/qmk/keymap.py +++ b/lib/python/qmk/keymap.py | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | """Functions that help you work with QMK keymaps. | 1 | """Functions that help you work with QMK keymaps. |
| 2 | """ | 2 | """ |
| 3 | import os | ||
| 4 | from pathlib import Path | 3 | from pathlib import Path |
| 5 | 4 | ||
| 6 | import qmk.path | 5 | import qmk.path |
| @@ -127,7 +126,7 @@ def list_keymaps(keyboard_name): | |||
| 127 | while kb_path != keyboards_dir: | 126 | while kb_path != keyboards_dir: |
| 128 | keymaps_dir = kb_path / "keymaps" | 127 | keymaps_dir = kb_path / "keymaps" |
| 129 | if keymaps_dir.exists(): | 128 | if keymaps_dir.exists(): |
| 130 | names = names.union([keymap for keymap in os.listdir(str(keymaps_dir)) if (keymaps_dir / keymap / "keymap.c").is_file()]) | 129 | names = names.union([keymap for keymap in keymaps_dir.iterdir() if (keymaps_dir / keymap / "keymap.c").is_file()]) |
| 131 | kb_path = kb_path.parent | 130 | kb_path = kb_path.parent |
| 132 | 131 | ||
| 133 | # if community layouts are supported, get them | 132 | # if community layouts are supported, get them |
| @@ -135,6 +134,6 @@ def list_keymaps(keyboard_name): | |||
| 135 | for layout in rules_mk["LAYOUTS"].split(): | 134 | for layout in rules_mk["LAYOUTS"].split(): |
| 136 | cl_path = Path.cwd() / "layouts" / "community" / layout | 135 | cl_path = Path.cwd() / "layouts" / "community" / layout |
| 137 | if cl_path.exists(): | 136 | if cl_path.exists(): |
| 138 | names = names.union([keymap for keymap in os.listdir(str(cl_path)) if (cl_path / keymap / "keymap.c").is_file()]) | 137 | names = names.union([keymap for keymap in cl_path.iterdir() if (cl_path / keymap / "keymap.c").is_file()]) |
| 139 | 138 | ||
| 140 | return sorted(names) | 139 | return sorted(names) |
