From 351e2268cd26235346dd08e23ee0ce2fbb7d7d0b Mon Sep 17 00:00:00 2001 From: Matt Broadway Date: Tue, 3 Jan 2023 22:06:04 +0000 Subject: [PATCH] config: remove derived fields from config file when Solaar version changes * renamed variables * Restructured configuration loading and ignore config generated by other versions This fixes an issue where newer solaar versions may have better support for a device which are not utilised because it is reading a configuration file generated by an earlier version before support was added. * fixed formatting * discard only absent and battery * discard name property as well * do not discard name --- lib/solaar/configuration.py | 84 +++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/lib/solaar/configuration.py b/lib/solaar/configuration.py index 7cb84efc..c5f804c1 100644 --- a/lib/solaar/configuration.py +++ b/lib/solaar/configuration.py @@ -35,8 +35,8 @@ _log = getLogger(__name__) del getLogger _XDG_CONFIG_HOME = _os.environ.get('XDG_CONFIG_HOME') or _path.expanduser(_path.join('~', '.config')) -_file_path = _path.join(_XDG_CONFIG_HOME, 'solaar', 'config.json') _yaml_file_path = _path.join(_XDG_CONFIG_HOME, 'solaar', 'config.yaml') +_json_file_path = _path.join(_XDG_CONFIG_HOME, 'solaar', 'config.json') _KEY_VERSION = '_version' _KEY_NAME = '_NAME' @@ -50,24 +50,71 @@ _config = [] def _load(): - global _config loaded_config = [] if _path.isfile(_yaml_file_path): + path = _yaml_file_path try: with open(_yaml_file_path) as config_file: loaded_config = _yaml.safe_load(config_file) except Exception as e: _log.error('failed to load from %s: %s', _yaml_file_path, e) - elif _path.isfile(_file_path): + elif _path.isfile(_json_file_path): + path = _json_file_path try: - with open(_file_path) as config_file: + with open(_json_file_path) as config_file: loaded_config = _json.load(config_file) except Exception as e: - _log.error('failed to load from %s: %s', _file_path, e) + _log.error('failed to load from %s: %s', _json_file_path, e) loaded_config = _convert_json(loaded_config) + else: + path = None if _log.isEnabledFor(_DEBUG): _log.debug('load => %s', loaded_config) - _config = _cleanup_load(loaded_config) + global _config + _config = _parse_config(loaded_config, path) + + +def _parse_config(loaded_config, config_path): + current_version = __version__ + parsed_config = [current_version] + try: + if not loaded_config: + return parsed_config + + loaded_version = loaded_config[0] + discard_derived_properties = loaded_version != current_version + if discard_derived_properties: + _log.warning( + 'config file \'%s\' was generated by another version of solaar ' + '(config: %s, current: %s). refreshing detected device capabilities', config_path, loaded_version, + current_version + ) + + for device in loaded_config[1:]: + assert isinstance(device, dict) + parsed_config.append(_device_entry_from_config_dict(device, discard_derived_properties)) + except Exception as e: + _log.warning('Exception processing config file \'%s\', ignoring contents: %s', config_path, e) + return parsed_config + + +def _device_entry_from_config_dict(data, discard_derived_properties): + divert = data.get('divert-keys') + if divert: + sliding = data.get('dpi-sliding') + if sliding: # convert old-style dpi-sliding setting to divert-keys entry + divert[int(sliding)] = 3 + data.pop('dpi-sliding', None) + gestures = data.get('mouse-gestures') + if gestures: # convert old-style mouse-gestures setting to divert-keys entry + divert[int(gestures)] = 2 + data.pop('mouse-gestures', None) + # remove any string entries (from bad conversions) + data['divert-keys'] = {k: v for k, v in divert.items() if isinstance(k, int)} + if discard_derived_properties: + data.pop('_absent') + data.pop('_battery') + return _DeviceEntry(**data) save_timer = None @@ -133,31 +180,6 @@ def _convert_json(json_dict): return config -def _cleanup_load(c): - _config = [__version__] - try: - for element in c: - if isinstance(element, dict): - divert = element.get('divert-keys') - if divert: - sliding = element.get('dpi-sliding') - if sliding: # convert old-style dpi-sliding setting to divert-keys entry - divert[int(sliding)] = 3 - element.pop('dpi-sliding', None) - gestures = element.get('mouse-gestures') - if gestures: # convert old-style mouse-gestures setting to divert-keys entry - divert[int(gestures)] = 2 - element.pop('mouse-gestures', None) - # remove any string entries (from bad conversions) - element['divert-keys'] = {k: v for k, v in divert.items() if isinstance(k, int)} - # convert to device entries - element = _DeviceEntry(**element) - _config.append(element) - except Exception as e: - _log.warn('Exception processing config.yaml file, ignoring contents: %s', e) - return _config - - class _DeviceEntry(dict): def __init__(self, **kwargs):