[CLI] Don't `exit()` when certain exceptions occur. (#23442)
parent
d4654ab893
commit
0262161914
|
@ -2,6 +2,7 @@
|
||||||
"""
|
"""
|
||||||
from milc import cli
|
from milc import cli
|
||||||
from qmk.search import filter_help, search_keymap_targets
|
from qmk.search import filter_help, search_keymap_targets
|
||||||
|
from qmk.util import maybe_exit_config
|
||||||
|
|
||||||
|
|
||||||
@cli.argument(
|
@cli.argument(
|
||||||
|
@ -19,6 +20,8 @@ from qmk.search import filter_help, search_keymap_targets
|
||||||
def find(cli):
|
def find(cli):
|
||||||
"""Search through all keyboards and keymaps for a given search criteria.
|
"""Search through all keyboards and keymaps for a given search criteria.
|
||||||
"""
|
"""
|
||||||
|
maybe_exit_config(should_exit=False, should_reraise=True)
|
||||||
|
|
||||||
targets = search_keymap_targets([('all', cli.config.find.keymap)], cli.args.filter)
|
targets = search_keymap_targets([('all', cli.config.find.keymap)], cli.args.filter)
|
||||||
for target in sorted(targets, key=lambda t: (t.keyboard, t.keymap)):
|
for target in sorted(targets, key=lambda t: (t.keyboard, t.keymap)):
|
||||||
print(f'{target}')
|
print(f'{target}')
|
||||||
|
|
|
@ -27,7 +27,6 @@ Example:
|
||||||
For full documentation, see QMK Docs
|
For full documentation, see QMK Docs
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
|
||||||
import textwrap
|
import textwrap
|
||||||
from typing import Any, Dict, Iterator, List, Tuple
|
from typing import Any, Dict, Iterator, List, Tuple
|
||||||
|
|
||||||
|
@ -38,6 +37,7 @@ from qmk.constants import GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE
|
||||||
from qmk.keyboard import keyboard_completer, keyboard_folder
|
from qmk.keyboard import keyboard_completer, keyboard_folder
|
||||||
from qmk.keymap import keymap_completer, locate_keymap
|
from qmk.keymap import keymap_completer, locate_keymap
|
||||||
from qmk.path import normpath
|
from qmk.path import normpath
|
||||||
|
from qmk.util import maybe_exit
|
||||||
|
|
||||||
KC_A = 4
|
KC_A = 4
|
||||||
KC_SPC = 0x2c
|
KC_SPC = 0x2c
|
||||||
|
@ -88,16 +88,16 @@ def parse_file(file_name: str) -> List[Tuple[str, str]]:
|
||||||
# Check that `typo` is valid.
|
# Check that `typo` is valid.
|
||||||
if not (all([c in TYPO_CHARS for c in typo])):
|
if not (all([c in TYPO_CHARS for c in typo])):
|
||||||
cli.log.error('{fg_red}Error:%d:{fg_reset} Typo "{fg_cyan}%s{fg_reset}" has characters other than a-z, \' and :.', line_number, typo)
|
cli.log.error('{fg_red}Error:%d:{fg_reset} Typo "{fg_cyan}%s{fg_reset}" has characters other than a-z, \' and :.', line_number, typo)
|
||||||
sys.exit(1)
|
maybe_exit(1)
|
||||||
for other_typo in typos:
|
for other_typo in typos:
|
||||||
if typo in other_typo or other_typo in typo:
|
if typo in other_typo or other_typo in typo:
|
||||||
cli.log.error('{fg_red}Error:%d:{fg_reset} Typos may not be substrings of one another, otherwise the longer typo would never trigger: "{fg_cyan}%s{fg_reset}" vs. "{fg_cyan}%s{fg_reset}".', line_number, typo, other_typo)
|
cli.log.error('{fg_red}Error:%d:{fg_reset} Typos may not be substrings of one another, otherwise the longer typo would never trigger: "{fg_cyan}%s{fg_reset}" vs. "{fg_cyan}%s{fg_reset}".', line_number, typo, other_typo)
|
||||||
sys.exit(1)
|
maybe_exit(1)
|
||||||
if len(typo) < 5:
|
if len(typo) < 5:
|
||||||
cli.log.warning('{fg_yellow}Warning:%d:{fg_reset} It is suggested that typos are at least 5 characters long to avoid false triggers: "{fg_cyan}%s{fg_reset}"', line_number, typo)
|
cli.log.warning('{fg_yellow}Warning:%d:{fg_reset} It is suggested that typos are at least 5 characters long to avoid false triggers: "{fg_cyan}%s{fg_reset}"', line_number, typo)
|
||||||
if len(typo) > 127:
|
if len(typo) > 127:
|
||||||
cli.log.error('{fg_red}Error:%d:{fg_reset} Typo exceeds 127 chars: "{fg_cyan}%s{fg_reset}"', line_number, typo)
|
cli.log.error('{fg_red}Error:%d:{fg_reset} Typo exceeds 127 chars: "{fg_cyan}%s{fg_reset}"', line_number, typo)
|
||||||
sys.exit(1)
|
maybe_exit(1)
|
||||||
|
|
||||||
check_typo_against_dictionary(typo, line_number, correct_words)
|
check_typo_against_dictionary(typo, line_number, correct_words)
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ def parse_file_lines(file_name: str) -> Iterator[Tuple[int, str, str]]:
|
||||||
tokens = [token.strip() for token in line.split('->', 1)]
|
tokens = [token.strip() for token in line.split('->', 1)]
|
||||||
if len(tokens) != 2 or not tokens[0]:
|
if len(tokens) != 2 or not tokens[0]:
|
||||||
print(f'Error:{line_number}: Invalid syntax: "{line}"')
|
print(f'Error:{line_number}: Invalid syntax: "{line}"')
|
||||||
sys.exit(1)
|
maybe_exit(1)
|
||||||
|
|
||||||
typo, correction = tokens
|
typo, correction = tokens
|
||||||
typo = typo.lower() # Force typos to lowercase.
|
typo = typo.lower() # Force typos to lowercase.
|
||||||
|
@ -237,7 +237,7 @@ def encode_link(link: Dict[str, Any]) -> List[int]:
|
||||||
byte_offset = link['byte_offset']
|
byte_offset = link['byte_offset']
|
||||||
if not (0 <= byte_offset <= 0xffff):
|
if not (0 <= byte_offset <= 0xffff):
|
||||||
cli.log.error('{fg_red}Error:{fg_reset} The autocorrection table is too large, a node link exceeds 64KB limit. Try reducing the autocorrection dict to fewer entries.')
|
cli.log.error('{fg_red}Error:{fg_reset} The autocorrection table is too large, a node link exceeds 64KB limit. Try reducing the autocorrection dict to fewer entries.')
|
||||||
sys.exit(1)
|
maybe_exit(1)
|
||||||
return [byte_offset & 255, byte_offset >> 8]
|
return [byte_offset & 255, byte_offset >> 8]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ from qmk.constants import QMK_FIRMWARE
|
||||||
from qmk.commands import find_make, get_make_parallel_args, build_environment
|
from qmk.commands import find_make, get_make_parallel_args, build_environment
|
||||||
from qmk.search import search_keymap_targets, search_make_targets
|
from qmk.search import search_keymap_targets, search_make_targets
|
||||||
from qmk.build_targets import BuildTarget, JsonKeymapBuildTarget
|
from qmk.build_targets import BuildTarget, JsonKeymapBuildTarget
|
||||||
|
from qmk.util import maybe_exit_config
|
||||||
|
|
||||||
|
|
||||||
def mass_compile_targets(targets: List[BuildTarget], clean: bool, dry_run: bool, no_temp: bool, parallel: int, **env):
|
def mass_compile_targets(targets: List[BuildTarget], clean: bool, dry_run: bool, no_temp: bool, parallel: int, **env):
|
||||||
|
@ -100,6 +101,8 @@ all: {keyboard_safe}_{keymap_name}_binary
|
||||||
def mass_compile(cli):
|
def mass_compile(cli):
|
||||||
"""Compile QMK Firmware against all keyboards.
|
"""Compile QMK Firmware against all keyboards.
|
||||||
"""
|
"""
|
||||||
|
maybe_exit_config(should_exit=False, should_reraise=True)
|
||||||
|
|
||||||
if len(cli.args.builds) > 0:
|
if len(cli.args.builds) > 0:
|
||||||
json_like_targets = list([Path(p) for p in filter(lambda e: Path(e).exists() and Path(e).suffix == '.json', cli.args.builds)])
|
json_like_targets = list([Path(p) for p in filter(lambda e: Path(e).exists() and Path(e).suffix == '.json', cli.args.builds)])
|
||||||
make_like_targets = list(filter(lambda e: Path(e) not in json_like_targets, cli.args.builds))
|
make_like_targets = list(filter(lambda e: Path(e) not in json_like_targets, cli.args.builds))
|
||||||
|
|
|
@ -9,6 +9,7 @@ from qmk.userspace import UserspaceDefs
|
||||||
from qmk.build_targets import JsonKeymapBuildTarget
|
from qmk.build_targets import JsonKeymapBuildTarget
|
||||||
from qmk.search import search_keymap_targets
|
from qmk.search import search_keymap_targets
|
||||||
from qmk.cli.mass_compile import mass_compile_targets
|
from qmk.cli.mass_compile import mass_compile_targets
|
||||||
|
from qmk.util import maybe_exit_config
|
||||||
|
|
||||||
|
|
||||||
@cli.argument('-t', '--no-temp', arg_only=True, action='store_true', help="Remove temporary files during build.")
|
@cli.argument('-t', '--no-temp', arg_only=True, action='store_true', help="Remove temporary files during build.")
|
||||||
|
@ -22,6 +23,8 @@ def userspace_compile(cli):
|
||||||
cli.log.error('Could not determine QMK userspace location. Please run `qmk doctor` or `qmk userspace-doctor` to diagnose.')
|
cli.log.error('Could not determine QMK userspace location. Please run `qmk doctor` or `qmk userspace-doctor` to diagnose.')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
maybe_exit_config(should_exit=False, should_reraise=True)
|
||||||
|
|
||||||
userspace = UserspaceDefs(QMK_USERSPACE / 'qmk.json')
|
userspace = UserspaceDefs(QMK_USERSPACE / 'qmk.json')
|
||||||
|
|
||||||
build_targets = []
|
build_targets = []
|
||||||
|
|
|
@ -10,6 +10,7 @@ from qmk.build_targets import BuildTarget
|
||||||
from qmk.keyboard import is_all_keyboards, keyboard_folder
|
from qmk.keyboard import is_all_keyboards, keyboard_folder
|
||||||
from qmk.keymap import is_keymap_target
|
from qmk.keymap import is_keymap_target
|
||||||
from qmk.search import search_keymap_targets
|
from qmk.search import search_keymap_targets
|
||||||
|
from qmk.util import maybe_exit_config
|
||||||
|
|
||||||
|
|
||||||
@cli.argument('-e', '--expand', arg_only=True, action='store_true', help="Expands any use of `all` for either keyboard or keymap.")
|
@cli.argument('-e', '--expand', arg_only=True, action='store_true', help="Expands any use of `all` for either keyboard or keymap.")
|
||||||
|
@ -19,6 +20,8 @@ def userspace_list(cli):
|
||||||
cli.log.error('Could not determine QMK userspace location. Please run `qmk doctor` or `qmk userspace-doctor` to diagnose.')
|
cli.log.error('Could not determine QMK userspace location. Please run `qmk doctor` or `qmk userspace-doctor` to diagnose.')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
maybe_exit_config(should_exit=False, should_reraise=True)
|
||||||
|
|
||||||
userspace = UserspaceDefs(QMK_USERSPACE / 'qmk.json')
|
userspace = UserspaceDefs(QMK_USERSPACE / 'qmk.json')
|
||||||
|
|
||||||
if cli.args.expand:
|
if cli.args.expand:
|
||||||
|
|
|
@ -69,7 +69,7 @@ def _via_to_keymap(via_backup, keyboard_data, keymap_layout):
|
||||||
layout_data = keyboard_data['layouts'].get(keymap_layout)
|
layout_data = keyboard_data['layouts'].get(keymap_layout)
|
||||||
if not layout_data:
|
if not layout_data:
|
||||||
cli.log.error(f'LAYOUT macro {keymap_layout} is not a valid one for keyboard {cli.args.keyboard}!')
|
cli.log.error(f'LAYOUT macro {keymap_layout} is not a valid one for keyboard {cli.args.keyboard}!')
|
||||||
exit(1)
|
return None
|
||||||
|
|
||||||
layout_data = layout_data['layout']
|
layout_data = layout_data['layout']
|
||||||
sorting_hat = list()
|
sorting_hat = list()
|
||||||
|
@ -118,7 +118,7 @@ def via2json(cli):
|
||||||
keymap_layout = cli.args.layout if cli.args.layout else _find_via_layout_macro(cli.args.keyboard)
|
keymap_layout = cli.args.layout if cli.args.layout else _find_via_layout_macro(cli.args.keyboard)
|
||||||
if not keymap_layout:
|
if not keymap_layout:
|
||||||
cli.log.error(f"Couldn't find LAYOUT macro for keyboard {cli.args.keyboard}. Please specify it with the '-l' argument.")
|
cli.log.error(f"Couldn't find LAYOUT macro for keyboard {cli.args.keyboard}. Please specify it with the '-l' argument.")
|
||||||
exit(1)
|
return False
|
||||||
|
|
||||||
# Load the VIA backup json
|
# Load the VIA backup json
|
||||||
with cli.args.filename.open('r') as fd:
|
with cli.args.filename.open('r') as fd:
|
||||||
|
@ -126,9 +126,15 @@ def via2json(cli):
|
||||||
|
|
||||||
# Generate keyboard metadata
|
# Generate keyboard metadata
|
||||||
keyboard_data = info_json(cli.args.keyboard)
|
keyboard_data = info_json(cli.args.keyboard)
|
||||||
|
if not keyboard_data:
|
||||||
|
cli.log.error(f'LAYOUT macro {keymap_layout} is not a valid one for keyboard {cli.args.keyboard}!')
|
||||||
|
return False
|
||||||
|
|
||||||
# Get keycode array
|
# Get keycode array
|
||||||
keymap_data = _via_to_keymap(via_backup, keyboard_data, keymap_layout)
|
keymap_data = _via_to_keymap(via_backup, keyboard_data, keymap_layout)
|
||||||
|
if not keymap_data:
|
||||||
|
cli.log.error(f'Could not extract valid keycode data from VIA backup matching keyboard {cli.args.keyboard}!')
|
||||||
|
return False
|
||||||
|
|
||||||
# Convert macros
|
# Convert macros
|
||||||
macro_data = list()
|
macro_data = list()
|
||||||
|
|
|
@ -11,6 +11,7 @@ import jsonschema
|
||||||
from qmk.constants import QMK_USERSPACE, HAS_QMK_USERSPACE
|
from qmk.constants import QMK_USERSPACE, HAS_QMK_USERSPACE
|
||||||
from qmk.json_schema import json_load, validate
|
from qmk.json_schema import json_load, validate
|
||||||
from qmk.keyboard import keyboard_alias_definitions
|
from qmk.keyboard import keyboard_alias_definitions
|
||||||
|
from qmk.util import maybe_exit
|
||||||
|
|
||||||
|
|
||||||
def find_make():
|
def find_make():
|
||||||
|
@ -52,7 +53,7 @@ def parse_configurator_json(configurator_file):
|
||||||
|
|
||||||
except jsonschema.ValidationError as e:
|
except jsonschema.ValidationError as e:
|
||||||
cli.log.error(f'Invalid JSON keymap: {configurator_file} : {e.message}')
|
cli.log.error(f'Invalid JSON keymap: {configurator_file} : {e.message}')
|
||||||
exit(1)
|
maybe_exit(1)
|
||||||
|
|
||||||
keyboard = user_keymap['keyboard']
|
keyboard = user_keymap['keyboard']
|
||||||
aliases = keyboard_alias_definitions()
|
aliases = keyboard_alias_definitions()
|
||||||
|
|
|
@ -14,6 +14,7 @@ from qmk.keyboard import config_h, rules_mk
|
||||||
from qmk.commands import parse_configurator_json
|
from qmk.commands import parse_configurator_json
|
||||||
from qmk.makefile import parse_rules_mk_file
|
from qmk.makefile import parse_rules_mk_file
|
||||||
from qmk.math import compute
|
from qmk.math import compute
|
||||||
|
from qmk.util import maybe_exit
|
||||||
|
|
||||||
true_values = ['1', 'on', 'yes']
|
true_values = ['1', 'on', 'yes']
|
||||||
false_values = ['0', 'off', 'no']
|
false_values = ['0', 'off', 'no']
|
||||||
|
@ -208,7 +209,7 @@ def _validate(keyboard, info_data):
|
||||||
except jsonschema.ValidationError as e:
|
except jsonschema.ValidationError as e:
|
||||||
json_path = '.'.join([str(p) for p in e.absolute_path])
|
json_path = '.'.join([str(p) for p in e.absolute_path])
|
||||||
cli.log.error('Invalid API data: %s: %s: %s', keyboard, json_path, e.message)
|
cli.log.error('Invalid API data: %s: %s: %s', keyboard, json_path, e.message)
|
||||||
exit(1)
|
maybe_exit(1)
|
||||||
|
|
||||||
|
|
||||||
def info_json(keyboard):
|
def info_json(keyboard):
|
||||||
|
|
|
@ -11,6 +11,8 @@ from copy import deepcopy
|
||||||
|
|
||||||
from milc import cli
|
from milc import cli
|
||||||
|
|
||||||
|
from qmk.util import maybe_exit
|
||||||
|
|
||||||
|
|
||||||
def _dict_raise_on_duplicates(ordered_pairs):
|
def _dict_raise_on_duplicates(ordered_pairs):
|
||||||
"""Reject duplicate keys."""
|
"""Reject duplicate keys."""
|
||||||
|
@ -38,10 +40,10 @@ def _json_load_impl(json_file, strict=True):
|
||||||
|
|
||||||
except (json.decoder.JSONDecodeError, hjson.HjsonDecodeError) as e:
|
except (json.decoder.JSONDecodeError, hjson.HjsonDecodeError) as e:
|
||||||
cli.log.error('Invalid JSON encountered attempting to load {fg_cyan}%s{fg_reset}:\n\t{fg_red}%s', json_file, 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)
|
maybe_exit(1)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
cli.log.error('Unknown error attempting to load {fg_cyan}%s{fg_reset}:\n\t{fg_red}%s', json_file, e)
|
cli.log.error('Unknown error attempting to load {fg_cyan}%s{fg_reset}:\n\t{fg_red}%s', json_file, e)
|
||||||
exit(1)
|
maybe_exit(1)
|
||||||
|
|
||||||
|
|
||||||
def json_load(json_file, strict=True):
|
def json_load(json_file, strict=True):
|
||||||
|
|
|
@ -2,9 +2,30 @@
|
||||||
"""
|
"""
|
||||||
import contextlib
|
import contextlib
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
import sys
|
||||||
|
|
||||||
from milc import cli
|
from milc import cli
|
||||||
|
|
||||||
|
maybe_exit_should_exit = True
|
||||||
|
maybe_exit_reraise = False
|
||||||
|
|
||||||
|
|
||||||
|
# Controls whether or not early `exit()` calls should be made
|
||||||
|
def maybe_exit(rc):
|
||||||
|
if maybe_exit_should_exit:
|
||||||
|
sys.exit(rc)
|
||||||
|
if maybe_exit_reraise:
|
||||||
|
e = sys.exception()
|
||||||
|
if e:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
|
||||||
|
def maybe_exit_config(should_exit: bool = True, should_reraise: bool = False):
|
||||||
|
global maybe_exit_should_exit
|
||||||
|
global maybe_exit_reraise
|
||||||
|
maybe_exit_should_exit = should_exit
|
||||||
|
maybe_exit_reraise = should_reraise
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def parallelize():
|
def parallelize():
|
||||||
|
|
Loading…
Reference in New Issue