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
This commit is contained in:
Matt Broadway 2023-01-03 22:06:04 +00:00 committed by GitHub
parent a51bcfb376
commit 351e2268cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 53 additions and 31 deletions

View File

@ -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):