diff options
Diffstat (limited to 'lib/python/qmk')
| -rwxr-xr-x | lib/python/qmk/cli/generate/config_h.py | 6 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/generate/develop_pr_list.py | 14 | ||||
| -rw-r--r-- | lib/python/qmk/cli/generate/version_h.py | 3 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/multibuild.py | 3 | ||||
| -rw-r--r-- | lib/python/qmk/cli/new/keyboard.py | 286 | ||||
| -rw-r--r-- | lib/python/qmk/commands.py | 2 | ||||
| -rw-r--r-- | lib/python/qmk/constants.py | 41 | ||||
| -rw-r--r-- | lib/python/qmk/info.py | 29 | ||||
| -rw-r--r-- | lib/python/qmk/path.py | 2 | ||||
| -rw-r--r-- | lib/python/qmk/tests/test_cli_commands.py | 2 | 
10 files changed, 287 insertions, 101 deletions
| diff --git a/lib/python/qmk/cli/generate/config_h.py b/lib/python/qmk/cli/generate/config_h.py index f16dca1de8..6b1012fae7 100755 --- a/lib/python/qmk/cli/generate/config_h.py +++ b/lib/python/qmk/cli/generate/config_h.py @@ -108,6 +108,12 @@ def generate_config_items(kb_info_json, config_h_lines):                  config_h_lines.append(f'#ifndef {key}')                  config_h_lines.append(f'#   define {key} {value}')                  config_h_lines.append(f'#endif // {key}') +        elif key_type == 'bcd_version': +            (major, minor, revision) = config_value.split('.') +            config_h_lines.append('') +            config_h_lines.append(f'#ifndef {config_key}') +            config_h_lines.append(f'#   define {config_key} 0x{major.zfill(2)}{minor}{revision}') +            config_h_lines.append(f'#endif // {config_key}')          else:              config_h_lines.append('')              config_h_lines.append(f'#ifndef {config_key}') diff --git a/lib/python/qmk/cli/generate/develop_pr_list.py b/lib/python/qmk/cli/generate/develop_pr_list.py index 07e46752a6..09236a7c42 100755 --- a/lib/python/qmk/cli/generate/develop_pr_list.py +++ b/lib/python/qmk/cli/generate/develop_pr_list.py @@ -12,6 +12,14 @@ fix_expr = re.compile(r'fix', flags=re.IGNORECASE)  clean1_expr = re.compile(r'\[(develop|keyboard|keymap|core|cli|bug|docs|feature)\]', flags=re.IGNORECASE)  clean2_expr = re.compile(r'^(develop|keyboard|keymap|core|cli|bug|docs|feature):', flags=re.IGNORECASE) +ignored_titles = ["Format code according to conventions"] + + +def _is_ignored(title): +    for ignore in ignored_titles: +        if ignore in title: +            return +  def _get_pr_info(cache, gh, pr_num):      pull = cache.get(f'pull:{pr_num}') @@ -81,7 +89,9 @@ def generate_develop_pr_list(cli):              else:                  normal_collection.append(info) -        if "dependencies" in commit_info['pr_labels']: +        if _is_ignored(commit_info['title']): +            return +        elif "dependencies" in commit_info['pr_labels']:              fix_or_normal(commit_info, pr_list_bugs, pr_list_dependencies)          elif "core" in commit_info['pr_labels']:              fix_or_normal(commit_info, pr_list_bugs, pr_list_core) @@ -97,7 +107,7 @@ def generate_develop_pr_list(cli):          match = git_expr.search(line)          if match:              pr_info = _get_pr_info(cache, gh, match.group("pr")) -            commit_info = {'hash': match.group("hash"), 'title': match.group("title"), 'pr_num': int(match.group("pr")), 'pr_labels': [label.name for label in pr_info.labels.items]} +            commit_info = {'hash': match.group("hash"), 'title': pr_info['title'], 'pr_num': int(match.group("pr")), 'pr_labels': [label.name for label in pr_info.labels.items]}              _categorise_commit(commit_info)      def _dump_commit_list(name, collection): diff --git a/lib/python/qmk/cli/generate/version_h.py b/lib/python/qmk/cli/generate/version_h.py index b8e52588c4..69341e36f0 100644 --- a/lib/python/qmk/cli/generate/version_h.py +++ b/lib/python/qmk/cli/generate/version_h.py @@ -20,6 +20,9 @@ def generate_version_h(cli):      version_h = create_version_h(cli.args.skip_git, cli.args.skip_all)      if cli.args.output: +        cli.args.output.parent.mkdir(parents=True, exist_ok=True) +        if cli.args.output.exists(): +            cli.args.output.replace(cli.args.output.parent / (cli.args.output.name + '.bak'))          cli.args.output.write_text(version_h)          if not cli.args.quiet: diff --git a/lib/python/qmk/cli/multibuild.py b/lib/python/qmk/cli/multibuild.py index 85ed0fa1e9..dff8c88422 100755 --- a/lib/python/qmk/cli/multibuild.py +++ b/lib/python/qmk/cli/multibuild.py @@ -32,6 +32,7 @@ def _is_split(keyboard_name):  @cli.argument('-c', '--clean', arg_only=True, action='store_true', help="Remove object files before compiling.")  @cli.argument('-f', '--filter', arg_only=True, action='append', default=[], help="Filter the list of keyboards based on the supplied value in rules.mk. Supported format is 'SPLIT_KEYBOARD=yes'. May be passed multiple times.")  @cli.argument('-km', '--keymap', type=str, default='default', help="The keymap name to build. Default is 'default'.") [email protected]('-e', '--env', arg_only=True, action='append', default=[], help="Set a variable to be passed to make. May be passed multiple times.")  @cli.subcommand('Compile QMK Firmware for all keyboards.', hidden=False if cli.config.user.developer else True)  def multibuild(cli):      """Compile QMK Firmware against all keyboards. @@ -68,7 +69,7 @@ def multibuild(cli):  all: {keyboard_safe}_binary  {keyboard_safe}_binary:  	@rm -f "{QMK_FIRMWARE}/.build/failed.log.{keyboard_safe}" || true -	+@$(MAKE) -C "{QMK_FIRMWARE}" -f "{QMK_FIRMWARE}/build_keyboard.mk" KEYBOARD="{keyboard_name}" KEYMAP="{cli.args.keymap}" REQUIRE_PLATFORM_KEY= COLOR=true SILENT=false \\ +	+@$(MAKE) -C "{QMK_FIRMWARE}" -f "{QMK_FIRMWARE}/builddefs/build_keyboard.mk" KEYBOARD="{keyboard_name}" KEYMAP="{cli.args.keymap}" REQUIRE_PLATFORM_KEY= COLOR=true SILENT=false {' '.join(cli.args.env)} \\  		>>"{QMK_FIRMWARE}/.build/build.log.{os.getpid()}.{keyboard_safe}" 2>&1 \\  		|| cp "{QMK_FIRMWARE}/.build/build.log.{os.getpid()}.{keyboard_safe}" "{QMK_FIRMWARE}/.build/failed.log.{os.getpid()}.{keyboard_safe}"  	@{{ grep '\[ERRORS\]' "{QMK_FIRMWARE}/.build/build.log.{os.getpid()}.{keyboard_safe}" >/dev/null 2>&1 && printf "Build %-64s \e[1;31m[ERRORS]\e[0m\\n" "{keyboard_name}:{cli.args.keymap}" ; }} \\ diff --git a/lib/python/qmk/cli/new/keyboard.py b/lib/python/qmk/cli/new/keyboard.py index 4093b8c90d..6fa9ad5b2c 100644 --- a/lib/python/qmk/cli/new/keyboard.py +++ b/lib/python/qmk/cli/new/keyboard.py @@ -1,15 +1,45 @@  """This script automates the creation of new keyboard directories using a starter template.  """ +import re +import json +import shutil  from datetime import date  from pathlib import Path -import re +from dotty_dict import dotty -from qmk.commands import git_get_username -import qmk.path  from milc import cli  from milc.questions import choice, question -KEYBOARD_TYPES = ['avr', 'ps2avrgb'] +from qmk.commands import git_get_username +from qmk.json_schema import load_jsonschema +from qmk.path import keyboard +from qmk.json_encoders import InfoJSONEncoder +from qmk.json_schema import deep_update +from qmk.constants import MCU2BOOTLOADER + +COMMUNITY = Path('layouts/default/') +TEMPLATE = Path('data/templates/keyboard/') + +# defaults +schema = dotty(load_jsonschema('keyboard')) +mcu_types = sorted(schema["properties.processor.enum"], key=str.casefold) +available_layouts = sorted([x.name for x in COMMUNITY.iterdir() if x.is_dir()]) + + +def mcu_type(mcu): +    """Callable for argparse validation. +    """ +    if mcu not in mcu_types: +        raise ValueError +    return mcu + + +def layout_type(layout): +    """Callable for argparse validation. +    """ +    if layout not in available_layouts: +        raise ValueError +    return layout  def keyboard_name(name): @@ -27,113 +57,193 @@ def validate_keyboard_name(name):      return bool(regex.match(name)) [email protected]('-kb', '--keyboard', help='Specify the name for the new keyboard directory', arg_only=True, type=keyboard_name) [email protected]('-t', '--type', help='Specify the keyboard type', arg_only=True, choices=KEYBOARD_TYPES) [email protected]('-u', '--username', help='Specify your username (default from Git config)', arg_only=True) [email protected]('-n', '--realname', help='Specify your real name if you want to use that. Defaults to username', arg_only=True) [email protected]('Creates a new keyboard directory') -def new_keyboard(cli): -    """Creates a new keyboard. +def select_default_bootloader(mcu): +    """Provide sane defaults for bootloader      """ -    cli.log.info('{style_bright}Generating a new QMK keyboard directory{style_normal}') -    cli.echo('') +    return MCU2BOOTLOADER.get(mcu, "custom") -    # Get keyboard name -    new_keyboard_name = None -    while not new_keyboard_name: -        new_keyboard_name = cli.args.keyboard if cli.args.keyboard else question('Keyboard Name:') -        if not validate_keyboard_name(new_keyboard_name): -            cli.log.error('Keyboard names must contain only {fg_cyan}lowercase a-z{fg_reset}, {fg_cyan}0-9{fg_reset}, and {fg_cyan}_{fg_reset}! Please choose a different name.') -            # Exit if passed by arg -            if cli.args.keyboard: -                return False +def replace_placeholders(src, dest, tokens): +    """Replaces the given placeholders in each template file. +    """ +    content = src.read_text() +    for key, value in tokens.items(): +        content = content.replace(f'%{key}%', value) -            new_keyboard_name = None -            continue +    dest.write_text(content) -        keyboard_path = qmk.path.keyboard(new_keyboard_name) -        if keyboard_path.exists(): -            cli.log.error(f'Keyboard {{fg_cyan}}{new_keyboard_name}{{fg_reset}} already exists! Please choose a different name.') -            # Exit if passed by arg -            if cli.args.keyboard: -                return False +def augment_community_info(src, dest): +    """Splice in any additional data into info.json +    """ +    info = json.loads(src.read_text()) +    template = json.loads(dest.read_text()) -            new_keyboard_name = None +    # merge community with template +    deep_update(info, template) -    # Get keyboard type -    keyboard_type = cli.args.type if cli.args.type else choice('Keyboard Type:', KEYBOARD_TYPES, default=0) +    # avoid assumptions on macro name by using the first available +    first_layout = next(iter(info["layouts"].values()))["layout"] -    # Get username -    user_name = None -    while not user_name: -        user_name = question('Your GitHub User Name:', default=find_user_name()) +    # guess at width and height now its optional +    width, height = (0, 0) +    for item in first_layout: +        width = max(width, int(item["x"]) + 1) +        height = max(height, int(item["y"]) + 1) -        if not user_name: -            cli.log.error('You didn\'t provide a username, and we couldn\'t find one set in your QMK or Git configs. Please try again.') +    info["matrix_pins"] = { +        "cols": ["C2"] * width, +        "rows": ["D1"] * height, +    } -            # Exit if passed by arg -            if cli.args.username: -                return False +    # assume a 1:1 mapping on matrix to electrical +    for item in first_layout: +        item["matrix"] = [int(item["y"]), int(item["x"])] -    real_name = None -    while not real_name: -        real_name = question('Your real name:', default=user_name) +    # finally write out the updated info.json +    dest.write_text(json.dumps(info, cls=InfoJSONEncoder)) -    keyboard_basename = keyboard_path.name -    replacements = { -        "YEAR": str(date.today().year), -        "KEYBOARD": keyboard_basename, -        "USER_NAME": user_name, -        "YOUR_NAME": real_name, -    } -    template_dir = Path('data/templates') -    template_tree(template_dir / 'base', keyboard_path, replacements) -    template_tree(template_dir / keyboard_type, keyboard_path, replacements) +def _question(*args, **kwargs): +    """Ugly workaround until 'milc' learns to display a repromt msg +    """ +    # TODO: Remove this once milc.questions.question handles reprompt messages -    cli.echo('') -    cli.log.info(f'{{fg_green}}Created a new keyboard called {{fg_cyan}}{new_keyboard_name}{{fg_green}}.{{fg_reset}}') -    cli.log.info(f'To start working on things, `cd` into {{fg_cyan}}{keyboard_path}{{fg_reset}},') -    cli.log.info('or open the directory in your preferred text editor.') +    reprompt = kwargs["reprompt"] +    del kwargs["reprompt"] +    validate = kwargs["validate"] +    del kwargs["validate"] +    prompt = args[0] +    ret = None +    while not ret: +        ret = question(prompt, **kwargs) +        if not validate(ret): +            ret = None +            prompt = reprompt -def find_user_name(): -    if cli.args.username: -        return cli.args.username -    elif cli.config.user.name: -        return cli.config.user.name -    else: -        return git_get_username() +    return ret -def template_tree(src: Path, dst: Path, replacements: dict): -    """Recursively copy template and replace placeholders +def prompt_keyboard(): +    prompt = """{fg_yellow}Name Your Keyboard Project{style_reset_all} +For more infomation, see: +https://docs.qmk.fm/#/hardware_keyboard_guidelines?id=naming-your-keyboardproject -    Args: -        src (Path) -            The source folder to copy from -        dst (Path) -            The destination folder to copy to -        replacements (dict) -            a dictionary with "key":"value" pairs to replace. +Keyboard Name? """ -    Raises: -        FileExistsError -            When trying to overwrite existing files +    errmsg = 'Keyboard already exists! Please choose a different name:' + +    return _question(prompt, reprompt=errmsg, validate=lambda x: not keyboard(x).exists()) + + +def prompt_user(): +    prompt = """ +{fg_yellow}Attribution{style_reset_all} +Used for maintainer, copyright, etc + +Your GitHub Username? """ +    return question(prompt, default=git_get_username()) + + +def prompt_name(def_name): +    prompt = """ +{fg_yellow}More Attribution{style_reset_all} +Used for maintainer, copyright, etc + +Your Real Name? """ +    return question(prompt, default=def_name) + + +def prompt_layout(): +    prompt = """ +{fg_yellow}Pick Base Layout{style_reset_all} +As a starting point, one of the common layouts can be used to bootstrap the process + +Default Layout? """ +    # avoid overwhelming user - remove some? +    filtered_layouts = [x for x in available_layouts if not any(xs in x for xs in ['_split', '_blocker', '_tsangan', '_f13'])] +    filtered_layouts.append("none of the above") + +    return choice(prompt, filtered_layouts, default=len(filtered_layouts) - 1) + + +def prompt_mcu(): +    prompt = """ +{fg_yellow}What Powers Your Project{style_reset_all} +For more infomation, see: +https://docs.qmk.fm/#/compatible_microcontrollers + +MCU? """ +    # remove any options strictly used for compatibility +    filtered_mcu = [x for x in mcu_types if not any(xs in x for xs in ['cortex', 'unknown'])] + +    return choice(prompt, filtered_mcu, default=filtered_mcu.index("atmega32u4")) + + [email protected]('-kb', '--keyboard', help='Specify the name for the new keyboard directory', arg_only=True, type=keyboard_name) [email protected]('-l', '--layout', help='Community layout to bootstrap with', arg_only=True, type=layout_type) [email protected]('-t', '--type', help='Specify the keyboard MCU type', arg_only=True, type=mcu_type) [email protected]('-u', '--username', help='Specify your username (default from Git config)', dest='name') [email protected]('-n', '--realname', help='Specify your real name if you want to use that. Defaults to username', arg_only=True) [email protected]('Creates a new keyboard directory') +def new_keyboard(cli): +    """Creates a new keyboard.      """ +    cli.log.info('{style_bright}Generating a new QMK keyboard directory{style_normal}') +    cli.echo('') + +    kb_name = cli.args.keyboard if cli.args.keyboard else prompt_keyboard() +    user_name = cli.config.new_keyboard.name if cli.config.new_keyboard.name else prompt_user() +    real_name = cli.args.realname or cli.config.new_keyboard.name if cli.args.realname or cli.config.new_keyboard.name else prompt_name(user_name) +    default_layout = cli.args.layout if cli.args.layout else prompt_layout() +    mcu = cli.args.type if cli.args.type else prompt_mcu() +    bootloader = select_default_bootloader(mcu) + +    if not validate_keyboard_name(kb_name): +        cli.log.error('Keyboard names must contain only {fg_cyan}lowercase a-z{fg_reset}, {fg_cyan}0-9{fg_reset}, and {fg_cyan}_{fg_reset}! Please choose a different name.') +        return 1 + +    if keyboard(kb_name).exists(): +        cli.log.error(f'Keyboard {{fg_cyan}}{kb_name}{{fg_reset}} already exists! Please choose a different name.') +        return 1 + +    tokens = {  # Comment here is to force multiline formatting +        'YEAR': str(date.today().year), +        'KEYBOARD': kb_name, +        'USER_NAME': user_name, +        'REAL_NAME': real_name, +        'LAYOUT': default_layout, +        'MCU': mcu, +        'BOOTLOADER': bootloader +    } + +    if cli.config.general.verbose: +        cli.log.info("Creating keyboard with:") +        for key, value in tokens.items(): +            cli.echo(f"    {key.ljust(10)}:   {value}") -    dst.mkdir(parents=True, exist_ok=True) +    # TODO: detach community layout and rename to just "LAYOUT" +    if default_layout == 'none of the above': +        default_layout = "ortho_4x4" -    for child in src.iterdir(): -        if child.is_dir(): -            template_tree(child, dst / child.name, replacements=replacements) +    # begin with making the deepest folder in the tree +    keymaps_path = keyboard(kb_name) / 'keymaps/' +    keymaps_path.mkdir(parents=True) -        if child.is_file(): -            file_name = dst / (child.name % replacements) +    # copy in keymap.c or keymap.json +    community_keymap = Path(COMMUNITY / f'{default_layout}/default_{default_layout}/') +    shutil.copytree(community_keymap, keymaps_path / 'default') -            with file_name.open(mode='x') as dst_f: -                with child.open() as src_f: -                    template = src_f.read() -                    dst_f.write(template % replacements) +    # process template files +    for file in list(TEMPLATE.iterdir()): +        replace_placeholders(file, keyboard(kb_name) / file.name, tokens) + +    # merge in infos +    community_info = Path(COMMUNITY / f'{default_layout}/info.json') +    augment_community_info(community_info, keyboard(kb_name) / community_info.name) + +    cli.log.info(f'{{fg_green}}Created a new keyboard called {{fg_cyan}}{kb_name}{{fg_green}}.{{fg_reset}}') +    cli.log.info(f'To start working on things, `cd` into {{fg_cyan}}keyboards/{kb_name}{{fg_reset}},') +    cli.log.info('or open the directory in your preferred text editor.') +    cli.log.info(f"And build with {{fg_yellow}}qmk compile -kb {kb_name} -km default{{fg_reset}}.") diff --git a/lib/python/qmk/commands.py b/lib/python/qmk/commands.py index 90a68ca3cd..275cd72e5c 100644 --- a/lib/python/qmk/commands.py +++ b/lib/python/qmk/commands.py @@ -213,7 +213,7 @@ def compile_configurator_json(user_keymap, bootloader=None, parallel=1, **env_va          '-r',          '-R',          '-f', -        'build_keyboard.mk', +        'builddefs/build_keyboard.mk',      ])      if bootloader: diff --git a/lib/python/qmk/constants.py b/lib/python/qmk/constants.py index 433b110523..e4b699cdb1 100644 --- a/lib/python/qmk/constants.py +++ b/lib/python/qmk/constants.py @@ -13,10 +13,49 @@ QMK_FIRMWARE_UPSTREAM = 'qmk/qmk_firmware'  MAX_KEYBOARD_SUBFOLDERS = 5  # Supported processor types -CHIBIOS_PROCESSORS = 'cortex-m0', 'cortex-m0plus', 'cortex-m3', 'cortex-m4', 'MKL26Z64', 'MK20DX128', 'MK20DX256', 'MK66FX1M0', 'STM32F042', 'STM32F072', 'STM32F103', 'STM32F303', 'STM32F401', 'STM32F405', 'STM32F407', 'STM32F411', 'STM32F446', 'STM32G431', 'STM32G474', 'STM32L412', 'STM32L422', 'STM32L433', 'STM32L443', 'GD32VF103', 'WB32F3G71' +CHIBIOS_PROCESSORS = 'cortex-m0', 'cortex-m0plus', 'cortex-m3', 'cortex-m4', 'MKL26Z64', 'MK20DX128', 'MK20DX256', 'MK66FX1M0', 'STM32F042', 'STM32F072', 'STM32F103', 'STM32F303', 'STM32F401', 'STM32F405', 'STM32F407', 'STM32F411', 'STM32F446', 'STM32G431', 'STM32G474', 'STM32L412', 'STM32L422', 'STM32L432', 'STM32L433', 'STM32L442', 'STM32L443', 'GD32VF103', 'WB32F3G71'  LUFA_PROCESSORS = 'at90usb162', 'atmega16u2', 'atmega32u2', 'atmega16u4', 'atmega32u4', 'at90usb646', 'at90usb647', 'at90usb1286', 'at90usb1287', None  VUSB_PROCESSORS = 'atmega32a', 'atmega328p', 'atmega328', 'attiny85' +# Bootloaders of the supported processors +MCU2BOOTLOADER = { +    "MKL26Z64": "halfkay", +    "MK20DX128": "halfkay", +    "MK20DX256": "halfkay", +    "MK66FX1M0": "halfkay", +    "STM32F042": "stm32-dfu", +    "STM32F072": "stm32-dfu", +    "STM32F103": "stm32duino", +    "STM32F303": "stm32-dfu", +    "STM32F401": "stm32-dfu", +    "STM32F405": "stm32-dfu", +    "STM32F407": "stm32-dfu", +    "STM32F411": "stm32-dfu", +    "STM32F446": "stm32-dfu", +    "STM32G431": "stm32-dfu", +    "STM32G474": "stm32-dfu", +    "STM32L412": "stm32-dfu", +    "STM32L422": "stm32-dfu", +    "STM32L432": "stm32-dfu", +    "STM32L433": "stm32-dfu", +    "STM32L442": "stm32-dfu", +    "STM32L443": "stm32-dfu", +    "GD32VF103": "gd32v-dfu", +    "WB32F3G71": "wb32-dfu", +    "atmega16u2": "atmel-dfu", +    "atmega32u2": "atmel-dfu", +    "atmega16u4": "atmel-dfu", +    "atmega32u4": "atmel-dfu", +    "at90usb162": "atmel-dfu", +    "at90usb646": "atmel-dfu", +    "at90usb647": "atmel-dfu", +    "at90usb1286": "atmel-dfu", +    "at90usb1287": "atmel-dfu", +    "atmega32a": "bootloadhid", +    "atmega328p": "usbasploader", +    "atmega328": "usbasploader", +} +  # Common format strings  DATE_FORMAT = '%Y-%m-%d'  DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S %Z' diff --git a/lib/python/qmk/info.py b/lib/python/qmk/info.py index 9a07fc842f..7e6f531f9c 100644 --- a/lib/python/qmk/info.py +++ b/lib/python/qmk/info.py @@ -49,6 +49,7 @@ def info_json(keyboard):          'parse_errors': [],          'parse_warnings': [],          'maintainer': 'qmk', +        'manufacturer': 'qmk',      }      # Populate the list of JSON keymaps @@ -387,6 +388,19 @@ def _extract_matrix_info(info_data, config_c):      return info_data +# TODO: kill off usb.device_ver in favor of usb.device_version +def _extract_device_version(info_data): +    if info_data.get('usb'): +        if info_data['usb'].get('device_version') and not info_data['usb'].get('device_ver'): +            (major, minor, revision) = info_data['usb']['device_version'].split('.', 3) +            info_data['usb']['device_ver'] = f'0x{major.zfill(2)}{minor}{revision}' +        if not info_data['usb'].get('device_version') and info_data['usb'].get('device_ver'): +            major = int(info_data['usb']['device_ver'][2:4]) +            minor = int(info_data['usb']['device_ver'][4]) +            revision = int(info_data['usb']['device_ver'][5]) +            info_data['usb']['device_version'] = f'{major}.{minor}.{revision}' + +  def _extract_config_h(info_data):      """Pull some keyboard information from existing config.h files      """ @@ -430,6 +444,13 @@ def _extract_config_h(info_data):                  elif key_type == 'int':                      dotty_info[info_key] = int(config_c[config_key]) +                elif key_type == 'bcd_version': +                    major = int(config_c[config_key][2:4]) +                    minor = int(config_c[config_key][4]) +                    revision = int(config_c[config_key][5]) + +                    dotty_info[info_key] = f'{major}.{minor}.{revision}' +                  else:                      dotty_info[info_key] = config_c[config_key] @@ -444,6 +465,7 @@ def _extract_config_h(info_data):      _extract_split_main(info_data, config_c)      _extract_split_transport(info_data, config_c)      _extract_split_right_pins(info_data, config_c) +    _extract_device_version(info_data)      return info_data @@ -622,12 +644,7 @@ def arm_processor_rules(info_data, rules):      info_data['protocol'] = 'ChibiOS'      if 'bootloader' not in info_data: -        if 'STM32' in info_data['processor']: -            info_data['bootloader'] = 'stm32-dfu' -        elif 'WB32' in info_data['processor']: -            info_data['bootloader'] = 'wb32-dfu' -        else: -            info_data['bootloader'] = 'unknown' +        info_data['bootloader'] = 'unknown'      if 'STM32' in info_data['processor']:          info_data['platform'] = 'STM32' diff --git a/lib/python/qmk/path.py b/lib/python/qmk/path.py index 72bae59273..dfb8371f84 100644 --- a/lib/python/qmk/path.py +++ b/lib/python/qmk/path.py @@ -46,7 +46,7 @@ def keymap(keyboard_name):      """      keyboard_folder = keyboard(keyboard_name) -    for i in range(MAX_KEYBOARD_SUBFOLDERS): +    for _ in range(MAX_KEYBOARD_SUBFOLDERS):          if (keyboard_folder / 'keymaps').exists():              return (keyboard_folder / 'keymaps').resolve() diff --git a/lib/python/qmk/tests/test_cli_commands.py b/lib/python/qmk/tests/test_cli_commands.py index 2973f81702..54b143c64f 100644 --- a/lib/python/qmk/tests/test_cli_commands.py +++ b/lib/python/qmk/tests/test_cli_commands.py @@ -113,7 +113,7 @@ def test_list_keymaps_community():  def test_list_keymaps_kb_only(): -    result = check_subcommand('list-keymaps', '-kb', 'niu_mini') +    result = check_subcommand('list-keymaps', '-kb', 'contra')      check_returncode(result)      assert 'default' and 'via' in result.stdout | 
