~ruther/qmk_firmware

370c02cb9a942ffccd493b38fa06afa5b52e24d8 — QMK Bot 2 years ago c952458 + 17fec52
Merge remote-tracking branch 'origin/master' into develop
1 files changed, 46 insertions(+), 53 deletions(-)

M lib/python/qmk/info.py
M lib/python/qmk/info.py => lib/python/qmk/info.py +46 -53
@@ 1,6 1,5 @@
"""Functions that help us generate and use info.json files.
"""
from glob import glob
from pathlib import Path

import jsonschema


@@ 26,6 25,50 @@ def _valid_community_layout(layout):
    return (Path('layouts/default') / layout).exists()


def _validate(keyboard, info_data):
    """Perform various validation on the provided info.json data
    """
    # First validate against the jsonschema
    try:
        validate(info_data, 'qmk.api.keyboard.v1')

    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)

    layouts = info_data.get('layouts', {})
    layout_aliases = info_data.get('layout_aliases', {})
    community_layouts = info_data.get('community_layouts', [])

    # Make sure we have at least one layout
    if len(layouts) == 0:
        _log_error(info_data, 'No LAYOUTs defined! Need at least one layout defined in info.json.')

    # Providing only LAYOUT_all "because I define my layouts in a 3rd party tool"
    if len(layouts) == 1 and 'LAYOUT_all' in layouts:
        _log_warning(info_data, '"LAYOUT_all" should be "LAYOUT" unless additional layouts are provided.')

    # Extended layout name checks
    name_fragments = keyboard.split('/')
    for layout in layouts.keys():
        if any(fragment in layout for fragment in name_fragments):
            _log_warning(info_data, f'Layout "{layout}" should not contain name of keyboard.')

    # Filter out any non-existing community layouts
    for layout in community_layouts:
        if not _valid_community_layout(layout):
            # Ignore layout from future checks
            info_data['community_layouts'].remove(layout)
            _log_error(info_data, 'Claims to support a community layout that does not exist: %s' % (layout))

    # Make sure we supply layout macros for the community layouts we claim to support
    for layout in community_layouts:
        layout_name = 'LAYOUT_' + layout
        if layout_name not in layouts and layout_name not in layout_aliases:
            _log_error(info_data, 'Claims to support community layout %s but no %s() macro found' % (layout, layout_name))


def info_json(keyboard):
    """Generate the info.json data for a specific keyboard.
    """


@@ 72,34 115,8 @@ def info_json(keyboard):
    # Merge in data from <keyboard.c>
    info_data = _extract_led_config(info_data, str(keyboard))

    # Validate against the jsonschema
    try:
        validate(info_data, 'qmk.api.keyboard.v1')

    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)

    # Make sure we have at least one layout
    if not info_data.get('layouts'):
        _find_missing_layouts(info_data, keyboard)

    if not info_data.get('layouts'):
        _log_error(info_data, 'No LAYOUTs defined! Need at least one layout defined in the keyboard.h or info.json.')

    # Filter out any non-existing community layouts
    for layout in info_data.get('community_layouts', []):
        if not _valid_community_layout(layout):
            # Ignore layout from future checks
            info_data['community_layouts'].remove(layout)
            _log_error(info_data, 'Claims to support a community layout that does not exist: %s' % (layout))

    # Make sure we supply layout macros for the community layouts we claim to support
    for layout in info_data.get('community_layouts', []):
        layout_name = 'LAYOUT_' + layout
        if layout_name not in info_data.get('layouts', {}) and layout_name not in info_data.get('layout_aliases', {}):
            _log_error(info_data, 'Claims to support community layout %s but no %s() macro found' % (layout, layout_name))
    # Validate
    _validate(keyboard, info_data)

    # Check that the reported matrix size is consistent with the actual matrix size
    _check_matrix(info_data)


@@ 701,30 718,6 @@ def _search_keyboard_h(keyboard):
    return layouts, aliases


def _find_missing_layouts(info_data, keyboard):
    """Looks for layout macros when they aren't found other places.

    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.
    """
    _log_warning(info_data, '%s: Falling back to searching for KEYMAP/LAYOUT macros.' % (keyboard))

    for file in glob('keyboards/%s/*.h' % keyboard):
        these_layouts, these_aliases = find_layouts(file)

        if these_layouts:
            for layout_name, layout_json in these_layouts.items():
                if not layout_name.startswith('LAYOUT_kc'):
                    layout_json['c_macro'] = True
                    info_data['layouts'][layout_name] = layout_json

        for alias, alias_text in these_aliases.items():
            if alias_text in these_layouts:
                if 'layout_aliases' not in info_data:
                    info_data['layout_aliases'] = {}

                info_data['layout_aliases'][alias] = alias_text


def _log_error(info_data, message):
    """Send an error message to both JSON and the log.
    """