First pass at supporting keyboard overrides at all levels

This commit is contained in:
Zach White 2021-09-09 11:13:50 -07:00
parent 93387f8941
commit 3f9e745b71
13 changed files with 104 additions and 87 deletions

View file

@ -6,6 +6,7 @@
"properties": { "properties": {
"author": {"type": "string"}, "author": {"type": "string"},
"keyboard": {"$ref": "qmk.definitions.v1#/text_identifier"}, "keyboard": {"$ref": "qmk.definitions.v1#/text_identifier"},
"keyboard_overrides": {"$ref": "qmk.keyboard.v1"},
"keymap": {"$ref": "qmk.definitions.v1#/text_identifier"}, "keymap": {"$ref": "qmk.definitions.v1#/text_identifier"},
"layout": {"$ref": "qmk.definitions.v1#/layout_macro"}, "layout": {"$ref": "qmk.definitions.v1#/layout_macro"},
"layers": { "layers": {
@ -15,10 +16,6 @@
"items": {"type": "string"} "items": {"type": "string"}
} }
}, },
"config": {"$ref": "qmk.keyboard.v1"}, "notes": { "type": "string" }
"notes": {
"type": "string",
"description": "asdf"
}
} }
} }

View file

@ -1,5 +1,6 @@
{ {
"keyboard":"clueboard/2x1800/2019", "keyboard":"clueboard/2x1800/2019",
"keyboard_overrides": {"keyboard_name": "keymap override"},
"keymap":"default", "keymap":"default",
"layout":"LAYOUT_all", "layout":"LAYOUT_all",
"layers":[ "layers":[

View file

@ -42,7 +42,7 @@ def format_json(cli):
if json_encoder == KeymapJSONEncoder and 'layout' in json_file: if json_encoder == KeymapJSONEncoder and 'layout' in json_file:
# Attempt to format the keycodes. # Attempt to format the keycodes.
layout = json_file['layout'] layout = json_file['layout']
info_data = info_json(json_file['keyboard']) info_data = info_json(json_file['keyboard'], overrides=json_file.get('keyboard_overrides'))
if layout in info_data.get('layout_aliases', {}): if layout in info_data.get('layout_aliases', {}):
layout = json_file['layout'] = info_data['layout_aliases'][layout] layout = json_file['layout'] = info_data['layout_aliases'][layout]

View file

@ -5,10 +5,9 @@ from pathlib import Path
from dotty_dict import dotty from dotty_dict import dotty
from milc import cli from milc import cli
from qmk.info import info_json from qmk.info import info_json, get_keyboard_overrides
from qmk.json_schema import json_load, validate from qmk.json_schema import json_load
from qmk.keyboard import keyboard_completer, keyboard_folder from qmk.keyboard import keyboard_completer, keyboard_folder
from qmk.keymap import locate_keymap
from qmk.path import normpath from qmk.path import normpath
@ -158,19 +157,11 @@ def generate_split_config(kb_info_json, config_h_lines):
@cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to') @cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, required=True, help='Keyboard to generate config.h for.') @cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, required=True, help='Keyboard to generate config.h for.')
@cli.argument('-km', '--keymap', arg_only=True, help='Keymap to generate config.h for.')
@cli.subcommand('Used by the make system to generate info_config.h from info.json', hidden=True) @cli.subcommand('Used by the make system to generate info_config.h from info.json', hidden=True)
def generate_config_h(cli): def generate_config_h(cli):
"""Generates the info_config.h file. """Generates the info_config.h file.
""" """
# Determine our keyboard/keymap kb_info_json = dotty(info_json(cli.args.keyboard, overrides=get_keyboard_overrides(cli.args.keyboard)))
if cli.args.keymap:
km = locate_keymap(cli.args.keyboard, cli.args.keymap)
km_json = json_load(km)
validate(km_json, 'qmk.keymap.v1')
kb_info_json = dotty(km_json.get('config', {}))
else:
kb_info_json = dotty(info_json(cli.args.keyboard))
# Build the info_config.h file. # Build the info_config.h file.
config_h_lines = ['/* This file was generated by `qmk generate-config-h`. Do not edit or copy.' ' */', '', '#pragma once'] config_h_lines = ['/* This file was generated by `qmk generate-config-h`. Do not edit or copy.' ' */', '', '#pragma once']

View file

@ -4,7 +4,7 @@ from dotty_dict import dotty
from milc import cli from milc import cli
from qmk.decorators import automagic_keyboard from qmk.decorators import automagic_keyboard
from qmk.info import info_json from qmk.info import info_json, get_keyboard_overrides
from qmk.path import is_keyboard, normpath from qmk.path import is_keyboard, normpath
from qmk.keyboard import keyboard_completer from qmk.keyboard import keyboard_completer
@ -28,7 +28,7 @@ def generate_dfu_header(cli):
return False return False
# Build the Keyboard.h file. # Build the Keyboard.h file.
kb_info_json = dotty(info_json(cli.config.generate_dfu_header.keyboard)) kb_info_json = dotty(info_json(cli.config.generate_dfu_header.keyboard, overrides=get_keyboard_overrides(cli.args.keyboard)))
keyboard_h_lines = ['/* This file was generated by `qmk generate-dfu-header`. Do not edit or copy.' ' */', '', '#pragma once'] keyboard_h_lines = ['/* This file was generated by `qmk generate-dfu-header`. Do not edit or copy.' ' */', '', '#pragma once']
keyboard_h_lines.append(f'#define MANUFACTURER {kb_info_json["manufacturer"]}') keyboard_h_lines.append(f'#define MANUFACTURER {kb_info_json["manufacturer"]}')

View file

@ -9,7 +9,7 @@ from jsonschema import Draft7Validator, RefResolver, validators
from milc import cli from milc import cli
from pathlib import Path from pathlib import Path
from qmk.decorators import automagic_keyboard, automagic_keymap from qmk.decorators import automagic_keyboard
from qmk.info import info_json from qmk.info import info_json
from qmk.json_encoders import InfoJSONEncoder from qmk.json_encoders import InfoJSONEncoder
from qmk.json_schema import compile_schema_store from qmk.json_schema import compile_schema_store
@ -46,12 +46,10 @@ def strip_info_json(kb_info_json):
@cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='Keyboard to show info for.') @cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='Keyboard to show info for.')
@cli.argument('-km', '--keymap', help='Show the layers for a JSON keymap too.')
@cli.argument('-o', '--output', arg_only=True, completer=FilesCompleter, help='Write the output the specified file, overwriting if necessary.') @cli.argument('-o', '--output', arg_only=True, completer=FilesCompleter, help='Write the output the specified file, overwriting if necessary.')
@cli.argument('-ow', '--overwrite', arg_only=True, action='store_true', help='Overwrite the existing info.json. (Overrides the location of --output)') @cli.argument('-ow', '--overwrite', arg_only=True, action='store_true', help='Overwrite the existing info.json. (Overrides the location of --output)')
@cli.subcommand('Generate an info.json file for a keyboard.', hidden=False if cli.config.user.developer else True) @cli.subcommand('Generate an info.json file for a keyboard.', hidden=False if cli.config.user.developer else True)
@automagic_keyboard @automagic_keyboard
@automagic_keymap
def generate_info_json(cli): def generate_info_json(cli):
"""Generate an info.json file for a keyboard """Generate an info.json file for a keyboard
""" """

View file

@ -2,7 +2,7 @@
""" """
from milc import cli from milc import cli
from qmk.info import info_json from qmk.info import info_json, get_keyboard_overrides
from qmk.keyboard import keyboard_completer, keyboard_folder from qmk.keyboard import keyboard_completer, keyboard_folder
from qmk.path import normpath from qmk.path import normpath
@ -11,7 +11,7 @@ def would_populate_layout_h(keyboard):
"""Detect if a given keyboard is doing data driven layouts """Detect if a given keyboard is doing data driven layouts
""" """
# Build the info.json file # Build the info.json file
kb_info_json = info_json(keyboard) kb_info_json = info_json(keyboard, overrides=get_keyboard_overrides(keyboard))
for layout_name in kb_info_json['layouts']: for layout_name in kb_info_json['layouts']:
if kb_info_json['layouts'][layout_name]['c_macro']: if kb_info_json['layouts'][layout_name]['c_macro']:

View file

@ -4,7 +4,7 @@ from milc import cli
from qmk.constants import COL_LETTERS, ROW_LETTERS from qmk.constants import COL_LETTERS, ROW_LETTERS
from qmk.decorators import automagic_keyboard, automagic_keymap from qmk.decorators import automagic_keyboard, automagic_keymap
from qmk.info import info_json from qmk.info import info_json, get_keyboard_overrides
from qmk.keyboard import keyboard_completer, keyboard_folder from qmk.keyboard import keyboard_completer, keyboard_folder
from qmk.path import is_keyboard, normpath from qmk.path import is_keyboard, normpath
@ -35,7 +35,7 @@ def generate_layouts(cli):
return False return False
# Build the info.json file # Build the info.json file
kb_info_json = info_json(cli.config.generate_layouts.keyboard) kb_info_json = info_json(cli.config.generate_layouts.keyboard, overrides=get_keyboard_overrides(cli.config.generate_layouts.keyboard))
# Build the layouts.h file. # Build the layouts.h file.
layouts_h_lines = ['/* This file was generated by `qmk generate-layouts`. Do not edit or copy.' ' */', '', '#pragma once'] layouts_h_lines = ['/* This file was generated by `qmk generate-layouts`. Do not edit or copy.' ' */', '', '#pragma once']

View file

@ -5,10 +5,9 @@ from pathlib import Path
from dotty_dict import dotty from dotty_dict import dotty
from milc import cli from milc import cli
from qmk.info import info_json from qmk.info import info_json, get_keyboard_overrides
from qmk.json_schema import json_load, validate from qmk.json_schema import json_load
from qmk.keyboard import keyboard_completer, keyboard_folder from qmk.keyboard import keyboard_completer, keyboard_folder
from qmk.keymap import locate_keymap
from qmk.path import normpath from qmk.path import normpath
@ -40,21 +39,12 @@ def process_mapping_rule(kb_info_json, rules_key, info_dict):
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
@cli.argument('-e', '--escape', arg_only=True, action='store_true', help="Escape spaces in quiet mode") @cli.argument('-e', '--escape', arg_only=True, action='store_true', help="Escape spaces in quiet mode")
@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, required=True, help='Keyboard to generate rules.mk for.') @cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, required=True, help='Keyboard to generate rules.mk for.')
@cli.argument('-km', '--keymap', arg_only=True, help='Keymap to generate rules.mk for.')
@cli.subcommand('Used by the make system to generate rules.mk from info.json', hidden=True) @cli.subcommand('Used by the make system to generate rules.mk from info.json', hidden=True)
def generate_rules_mk(cli): def generate_rules_mk(cli):
"""Generates a rules.mk file from info.json. """Generates a rules.mk file from info.json.
""" """
# Determine our keyboard/keymap
if cli.args.keymap:
km = locate_keymap(cli.args.keyboard, cli.args.keymap)
km_json = json_load(km)
validate(km_json, 'qmk.keymap.v1')
kb_info_json = dotty(km_json.get('config', {}))
else:
kb_info_json = dotty(info_json(cli.args.keyboard))
info_rules_map = json_load(Path('data/mappings/info_rules.json')) info_rules_map = json_load(Path('data/mappings/info_rules.json'))
kb_info_json = dotty(info_json(cli.args.keyboard, overrides=get_keyboard_overrides(cli.args.keyboard)))
rules_mk_lines = ['# This file was generated by `qmk generate-rules-mk`. Do not edit or copy.', ''] rules_mk_lines = ['# This file was generated by `qmk generate-rules-mk`. Do not edit or copy.', '']
# Iterate through the info_rules map to generate basic rules # Iterate through the info_rules map to generate basic rules

View file

@ -18,23 +18,19 @@ from qmk.path import is_keyboard
UNICODE_SUPPORT = sys.stdout.encoding.lower().startswith('utf') UNICODE_SUPPORT = sys.stdout.encoding.lower().startswith('utf')
def show_keymap(kb_info_json, title_caps=True): def show_keymap(kb_info_json, keymap_data, title_caps=True):
"""Render the keymap in ascii art. """Render the keymap in ascii art.
""" """
keymap_path = locate_keymap(cli.config.info.keyboard, cli.config.info.keymap) layout_name = keymap_data['layout']
layout_name = kb_info_json.get('layout_aliases', {}).get(layout_name, layout_name) # Resolve alias names
if keymap_path and keymap_path.suffix == '.json': for layer_num, layer in enumerate(keymap_data['layers']):
keymap_data = json.load(keymap_path.open(encoding='utf-8')) if title_caps:
layout_name = keymap_data['layout'] cli.echo('{fg_cyan}Keymap %s Layer %s{fg_reset}:', cli.config.info.keymap, layer_num)
layout_name = kb_info_json.get('layout_aliases', {}).get(layout_name, layout_name) # Resolve alias names else:
cli.echo('{fg_cyan}keymap.%s.layer.%s{fg_reset}:', cli.config.info.keymap, layer_num)
for layer_num, layer in enumerate(keymap_data['layers']): print(render_layout(kb_info_json['layouts'][layout_name]['layout'], cli.config.info.ascii, layer))
if title_caps:
cli.echo('{fg_cyan}Keymap %s Layer %s{fg_reset}:', cli.config.info.keymap, layer_num)
else:
cli.echo('{fg_cyan}keymap.%s.layer.%s{fg_reset}:', cli.config.info.keymap, layer_num)
print(render_layout(kb_info_json['layouts'][layout_name]['layout'], cli.config.info.ascii, layer))
def show_layouts(kb_info_json, title_caps=True): def show_layouts(kb_info_json, title_caps=True):
@ -161,19 +157,27 @@ def info(cli):
print_parsed_rules_mk(cli.config.info.keyboard) print_parsed_rules_mk(cli.config.info.keyboard)
return False return False
# Pull in keymap overrides if necessary
keymap_path = locate_keymap(cli.config.info.keyboard, cli.config.info.keymap) if cli.config.info.keymap else None
keymap_data = json.load(keymap_path.open(encoding='utf-8')) if keymap_path and keymap_path.suffix == '.json' else None
# Build the info.json file # Build the info.json file
kb_info_json = info_json(cli.config.info.keyboard) overrides = keymap_data.get('keyboard_overrides') if keymap_data else None
kb_info_json = info_json(cli.config.info.keyboard, overrides=overrides)
# Output in the requested format # Output in the requested format
if cli.args.format == 'json': if cli.args.format == 'json':
print(json.dumps(kb_info_json, cls=InfoJSONEncoder)) print(json.dumps(kb_info_json, cls=InfoJSONEncoder))
return True return True
elif cli.args.format == 'text': elif cli.args.format == 'text':
print_dotted_output(kb_info_json) print_dotted_output(kb_info_json)
title_caps = False title_caps = False
elif cli.args.format == 'friendly': elif cli.args.format == 'friendly':
print_friendly_output(kb_info_json) print_friendly_output(kb_info_json)
title_caps = True title_caps = True
else: else:
cli.log.error('Unknown format: %s', cli.args.format) cli.log.error('Unknown format: %s', cli.args.format)
return False return False
@ -184,5 +188,5 @@ def info(cli):
if cli.config.info.matrix: if cli.config.info.matrix:
show_matrix(kb_info_json, title_caps) show_matrix(kb_info_json, title_caps)
if cli.config_source.info.keymap and cli.config_source.info.keymap != 'config_file': if keymap_data:
show_keymap(kb_info_json, title_caps) show_keymap(kb_info_json, keymap_data, title_caps)

View file

@ -76,10 +76,12 @@ def lint(cli):
cli.log.warning('Both --all-kb and --keyboard passed, --all-kb takes presidence.') cli.log.warning('Both --all-kb and --keyboard passed, --all-kb takes presidence.')
keyboard_list = list_keyboards() keyboard_list = list_keyboards()
elif not cli.config.lint.keyboard: elif not cli.config.lint.keyboard:
cli.log.error('Missing required arguments: --keyboard or --all-kb') cli.log.error('Missing required arguments: --keyboard or --all-kb')
cli.print_help() cli.print_help()
return False return False
else: else:
keyboard_list = cli.config.lint.keyboard.split(',') keyboard_list = cli.config.lint.keyboard.split(',')

View file

@ -12,7 +12,7 @@ from milc import cli
import qmk.keymap import qmk.keymap
from qmk.constants import QMK_FIRMWARE, KEYBOARD_OUTPUT_PREFIX from qmk.constants import QMK_FIRMWARE, KEYBOARD_OUTPUT_PREFIX
from qmk.json_schema import json_load from qmk.json_schema import json_load, validate
time_fmt = '%Y-%m-%d-%H:%M:%S' time_fmt = '%Y-%m-%d-%H:%M:%S'
@ -194,6 +194,15 @@ def compile_configurator_json(user_keymap, bootloader=None, parallel=1, **env_va
version_h = Path('quantum/version.h') version_h = Path('quantum/version.h')
version_h.write_text(create_version_h()) version_h.write_text(create_version_h())
# Write the overrides file, if needed
override_file = keyboard_output / 'keyboard_overrides.json'
if 'keyboard_overrides' in user_keymap:
keyboard_output.mkdir(exist_ok=True, parents=True)
json.dump(user_keymap['keyboard_overrides'], override_file.open('w', encoding='utf-8'))
elif override_file.exists():
override_file.unlink()
# Return a command that can be run to make the keymap and flash if given # Return a command that can be run to make the keymap and flash if given
verbose = 'true' if cli.config.general.verbose else 'false' verbose = 'true' if cli.config.general.verbose else 'false'
color = 'true' if cli.config.general.color else 'false' color = 'true' if cli.config.general.color else 'false'
@ -242,8 +251,10 @@ def compile_configurator_json(user_keymap, bootloader=None, parallel=1, **env_va
def parse_configurator_json(configurator_file): def parse_configurator_json(configurator_file):
"""Open and parse a configurator json export """Open and parse a configurator json export
""" """
# FIXME(skullydazed/anyone): Add validation here
user_keymap = json.load(configurator_file) user_keymap = json.load(configurator_file)
validate(user_keymap, 'qmk.keymap.v1')
orig_keyboard = user_keymap['keyboard'] orig_keyboard = user_keymap['keyboard']
aliases = json_load(Path('data/mappings/keyboard_aliases.json')) aliases = json_load(Path('data/mappings/keyboard_aliases.json'))

View file

@ -1,5 +1,6 @@
"""Functions that help us generate and use info.json files. """Functions that help us generate and use info.json files.
""" """
import json
from glob import glob from glob import glob
from pathlib import Path from pathlib import Path
@ -7,7 +8,7 @@ import jsonschema
from dotty_dict import dotty from dotty_dict import dotty
from milc import cli from milc import cli
from qmk.constants import CHIBIOS_PROCESSORS, LUFA_PROCESSORS, VUSB_PROCESSORS from qmk.constants import CHIBIOS_PROCESSORS, KEYBOARD_OUTPUT_PREFIX, LUFA_PROCESSORS, VUSB_PROCESSORS
from qmk.c_parse import find_layouts from qmk.c_parse import find_layouts
from qmk.json_schema import deep_update, json_load, validate from qmk.json_schema import deep_update, json_load, validate
from qmk.keyboard import config_h, rules_mk from qmk.keyboard import config_h, rules_mk
@ -25,7 +26,7 @@ def _valid_community_layout(layout):
return (Path('layouts/default') / layout).exists() return (Path('layouts/default') / layout).exists()
def info_json(keyboard): def info_json(keyboard, *, overrides=None):
"""Generate the info.json data for a specific keyboard. """Generate the info.json data for a specific keyboard.
""" """
cur_dir = Path('keyboards') cur_dir = Path('keyboards')
@ -59,11 +60,14 @@ def info_json(keyboard):
layout_json['c_macro'] = True layout_json['c_macro'] = True
info_data['layouts'][layout_name] = layout_json info_data['layouts'][layout_name] = layout_json
# Merge in the data from info.json, config.h, and rules.mk # Merge in the data from info.json, config.h, rules.mk, and overrides
info_data = merge_info_jsons(keyboard, info_data) info_data = merge_info_jsons(keyboard, info_data)
info_data = _extract_rules_mk(info_data) info_data = _extract_rules_mk(info_data)
info_data = _extract_config_h(info_data) info_data = _extract_config_h(info_data)
if overrides:
info_data = merge_info_data(info_data, overrides)
# Ensure that we have matrix row and column counts # Ensure that we have matrix row and column counts
info_data = _matrix_size(info_data) info_data = _matrix_size(info_data)
@ -102,6 +106,17 @@ def info_json(keyboard):
return info_data return info_data
def get_keyboard_overrides(keyboard):
"""Checks for keyboard_overrides.json in the keyboard build directory and returns them if it exists.
"""
keyboard_filesafe = keyboard.replace('/', '_')
keyboard_output = Path(f'{KEYBOARD_OUTPUT_PREFIX}{keyboard_filesafe}')
keyboard_overrides_file = keyboard_output / 'keyboard_overrides.json'
if keyboard_overrides_file.exists():
return json.load(keyboard_overrides_file.open('r', encoding='utf-8'))
def _extract_features(info_data, rules): def _extract_features(info_data, rules):
"""Find all the features enabled in rules.mk. """Find all the features enabled in rules.mk.
""" """
@ -660,6 +675,38 @@ def unknown_processor_rules(info_data, rules):
return info_data return info_data
def merge_info_data(info_data, new_info_data):
"""Return a merged copy of info_data and new_info_data.
"""
if 'layout_aliases' in new_info_data:
info_data['layout_aliases'] = {**info_data.get('layout_aliases', {}), **new_info_data['layout_aliases']}
del new_info_data['layout_aliases']
for layout_name, layout in new_info_data.get('layouts', {}).items():
if layout_name in info_data.get('layout_aliases', {}):
_log_warning(info_data, f"info.json uses alias name {layout_name} instead of {info_data['layout_aliases'][layout_name]}")
layout_name = info_data['layout_aliases'][layout_name]
if layout_name in info_data['layouts']:
if len(info_data['layouts'][layout_name]['layout']) != len(layout['layout']):
msg = '%s: %s: Number of elements in info.json does not match! info.json:%s != %s:%s'
_log_error(info_data, msg % (info_data['keyboard_folder'], layout_name, len(layout['layout']), layout_name, len(info_data['layouts'][layout_name]['layout'])))
else:
for new_key, existing_key in zip(layout['layout'], info_data['layouts'][layout_name]['layout']):
existing_key.update(new_key)
else:
layout['c_macro'] = False
info_data['layouts'][layout_name] = layout
# Update info_data with the new data
if 'layouts' in new_info_data:
del new_info_data['layouts']
deep_update(info_data, new_info_data)
return info_data
def merge_info_jsons(keyboard, info_data): def merge_info_jsons(keyboard, info_data):
"""Return a merged copy of all the info.json files for a keyboard. """Return a merged copy of all the info.json files for a keyboard.
""" """
@ -680,31 +727,7 @@ def merge_info_jsons(keyboard, info_data):
continue continue
# Merge layout data in # Merge layout data in
if 'layout_aliases' in new_info_data: merge_info_data(info_data, new_info_data)
info_data['layout_aliases'] = {**info_data.get('layout_aliases', {}), **new_info_data['layout_aliases']}
del new_info_data['layout_aliases']
for layout_name, layout in new_info_data.get('layouts', {}).items():
if layout_name in info_data.get('layout_aliases', {}):
_log_warning(info_data, f"info.json uses alias name {layout_name} instead of {info_data['layout_aliases'][layout_name]}")
layout_name = info_data['layout_aliases'][layout_name]
if layout_name in info_data['layouts']:
if len(info_data['layouts'][layout_name]['layout']) != len(layout['layout']):
msg = '%s: %s: Number of elements in info.json does not match! info.json:%s != %s:%s'
_log_error(info_data, msg % (info_data['keyboard_folder'], layout_name, len(layout['layout']), layout_name, len(info_data['layouts'][layout_name]['layout'])))
else:
for new_key, existing_key in zip(layout['layout'], info_data['layouts'][layout_name]['layout']):
existing_key.update(new_key)
else:
layout['c_macro'] = False
info_data['layouts'][layout_name] = layout
# Update info_data with the new data
if 'layouts' in new_info_data:
del new_info_data['layouts']
deep_update(info_data, new_info_data)
return info_data return info_data