~ruther/qmk_firmware

0262161914133e6abfc306e675dbac3ba816a6ee — Nick Brassel 10 months ago d4654ab
[CLI] Don't `exit()` when certain exceptions occur. (#23442)

M lib/python/qmk/cli/find.py => lib/python/qmk/cli/find.py +3 -0
@@ 2,6 2,7 @@
"""
from milc import cli
from qmk.search import filter_help, search_keymap_targets
from qmk.util import maybe_exit_config


@cli.argument(


@@ 19,6 20,8 @@ from qmk.search import filter_help, search_keymap_targets
def find(cli):
    """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)
    for target in sorted(targets, key=lambda t: (t.keyboard, t.keymap)):
        print(f'{target}')

M lib/python/qmk/cli/generate/autocorrect_data.py => lib/python/qmk/cli/generate/autocorrect_data.py +6 -6
@@ 27,7 27,6 @@ Example:
For full documentation, see QMK Docs
"""

import sys
import textwrap
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.keymap import keymap_completer, locate_keymap
from qmk.path import normpath
from qmk.util import maybe_exit

KC_A = 4
KC_SPC = 0x2c


@@ 88,16 88,16 @@ def parse_file(file_name: str) -> List[Tuple[str, str]]:
        # Check that `typo` is valid.
        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)
            sys.exit(1)
            maybe_exit(1)
        for other_typo in typos:
            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)
                sys.exit(1)
                maybe_exit(1)
        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)
        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)
            sys.exit(1)
            maybe_exit(1)

        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)]
            if len(tokens) != 2 or not tokens[0]:
                print(f'Error:{line_number}: Invalid syntax: "{line}"')
                sys.exit(1)
                maybe_exit(1)

            typo, correction = tokens
            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']
    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.')
        sys.exit(1)
        maybe_exit(1)
    return [byte_offset & 255, byte_offset >> 8]



M lib/python/qmk/cli/mass_compile.py => lib/python/qmk/cli/mass_compile.py +3 -0
@@ 12,6 12,7 @@ from qmk.constants import QMK_FIRMWARE
from qmk.commands import find_make, get_make_parallel_args, build_environment
from qmk.search import search_keymap_targets, search_make_targets
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):


@@ 100,6 101,8 @@ all: {keyboard_safe}_{keymap_name}_binary
def mass_compile(cli):
    """Compile QMK Firmware against all keyboards.
    """
    maybe_exit_config(should_exit=False, should_reraise=True)

    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)])
        make_like_targets = list(filter(lambda e: Path(e) not in json_like_targets, cli.args.builds))

M lib/python/qmk/cli/userspace/compile.py => lib/python/qmk/cli/userspace/compile.py +3 -0
@@ 9,6 9,7 @@ from qmk.userspace import UserspaceDefs
from qmk.build_targets import JsonKeymapBuildTarget
from qmk.search import search_keymap_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.")


@@ 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.')
        return False

    maybe_exit_config(should_exit=False, should_reraise=True)

    userspace = UserspaceDefs(QMK_USERSPACE / 'qmk.json')

    build_targets = []

M lib/python/qmk/cli/userspace/list.py => lib/python/qmk/cli/userspace/list.py +3 -0
@@ 10,6 10,7 @@ from qmk.build_targets import BuildTarget
from qmk.keyboard import is_all_keyboards, keyboard_folder
from qmk.keymap import is_keymap_target
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.")


@@ 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.')
        return False

    maybe_exit_config(should_exit=False, should_reraise=True)

    userspace = UserspaceDefs(QMK_USERSPACE / 'qmk.json')

    if cli.args.expand:

M lib/python/qmk/cli/via2json.py => lib/python/qmk/cli/via2json.py +8 -2
@@ 69,7 69,7 @@ def _via_to_keymap(via_backup, keyboard_data, keymap_layout):
    layout_data = keyboard_data['layouts'].get(keymap_layout)
    if not layout_data:
        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']
    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)
    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.")
        exit(1)
        return False

    # Load the VIA backup json
    with cli.args.filename.open('r') as fd:


@@ 126,9 126,15 @@ def via2json(cli):

    # Generate keyboard metadata
    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
    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
    macro_data = list()

M lib/python/qmk/commands.py => lib/python/qmk/commands.py +2 -1
@@ 11,6 11,7 @@ import jsonschema
from qmk.constants import QMK_USERSPACE, HAS_QMK_USERSPACE
from qmk.json_schema import json_load, validate
from qmk.keyboard import keyboard_alias_definitions
from qmk.util import maybe_exit


def find_make():


@@ 52,7 53,7 @@ def parse_configurator_json(configurator_file):

    except jsonschema.ValidationError as e:
        cli.log.error(f'Invalid JSON keymap: {configurator_file} : {e.message}')
        exit(1)
        maybe_exit(1)

    keyboard = user_keymap['keyboard']
    aliases = keyboard_alias_definitions()

M lib/python/qmk/info.py => lib/python/qmk/info.py +2 -1
@@ 14,6 14,7 @@ from qmk.keyboard import config_h, rules_mk
from qmk.commands import parse_configurator_json
from qmk.makefile import parse_rules_mk_file
from qmk.math import compute
from qmk.util import maybe_exit

true_values = ['1', 'on', 'yes']
false_values = ['0', 'off', 'no']


@@ 208,7 209,7 @@ def _validate(keyboard, info_data):
    except jsonschema.ValidationError as e:
        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)
        exit(1)
        maybe_exit(1)


def info_json(keyboard):

M lib/python/qmk/json_schema.py => lib/python/qmk/json_schema.py +4 -2
@@ 11,6 11,8 @@ from copy import deepcopy

from milc import cli

from qmk.util import maybe_exit


def _dict_raise_on_duplicates(ordered_pairs):
    """Reject duplicate keys."""


@@ 38,10 40,10 @@ def _json_load_impl(json_file, strict=True):

    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)
        exit(1)
        maybe_exit(1)
    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)
        exit(1)
        maybe_exit(1)


def json_load(json_file, strict=True):

M lib/python/qmk/util.py => lib/python/qmk/util.py +21 -0
@@ 2,9 2,30 @@
"""
import contextlib
import multiprocessing
import sys

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
def parallelize():

Do not follow this link