134 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			134 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
| # -*- python-mode -*-
 | |
| # -*- coding: UTF-8 -*-
 | |
| 
 | |
| ## Copyright (C) 2012-2013  Daniel Pavel
 | |
| ##
 | |
| ## This program is free software; you can redistribute it and/or modify
 | |
| ## it under the terms of the GNU General Public License as published by
 | |
| ## the Free Software Foundation; either version 2 of the License, or
 | |
| ## (at your option) any later version.
 | |
| ##
 | |
| ## This program is distributed in the hope that it will be useful,
 | |
| ## but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| ## GNU General Public License for more details.
 | |
| ##
 | |
| ## You should have received a copy of the GNU General Public License along
 | |
| ## with this program; if not, write to the Free Software Foundation, Inc.,
 | |
| ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | |
| 
 | |
| import os as _os
 | |
| import os.path as _path
 | |
| from json import load as _json_load, dump as _json_save
 | |
| 
 | |
| from logging import getLogger, DEBUG as _DEBUG, INFO as _INFO
 | |
| _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')
 | |
| 
 | |
| 
 | |
| from solaar import __version__
 | |
| _KEY_VERSION = '_version'
 | |
| _KEY_NAME = '_name'
 | |
| _configuration = {}
 | |
| 
 | |
| 
 | |
| 
 | |
| def _load():
 | |
| 	if _path.isfile(_file_path):
 | |
| 		loaded_configuration = {}
 | |
| 		try:
 | |
| 			with open(_file_path, 'r') as config_file:
 | |
| 				loaded_configuration = _json_load(config_file)
 | |
| 		except:
 | |
| 			_log.error("failed to load from %s", _file_path)
 | |
| 
 | |
| 		# loaded_configuration.update(_configuration)
 | |
| 		_configuration.clear()
 | |
| 		_configuration.update(loaded_configuration)
 | |
| 
 | |
| 	if _log.isEnabledFor(_DEBUG):
 | |
| 		_log.debug("load => %s", _configuration)
 | |
| 
 | |
| 	_cleanup(_configuration)
 | |
| 	_configuration[_KEY_VERSION] = __version__
 | |
| 	return _configuration
 | |
| 
 | |
| 
 | |
| def save():
 | |
| 	# don't save if the configuration hasn't been loaded
 | |
| 	if _KEY_VERSION not in _configuration:
 | |
| 		return
 | |
| 
 | |
| 	dirname = _os.path.dirname(_file_path)
 | |
| 	if not _path.isdir(dirname):
 | |
| 		try:
 | |
| 			_os.makedirs(dirname)
 | |
| 		except:
 | |
| 			_log.error("failed to create %s", dirname)
 | |
| 			return False
 | |
| 
 | |
| 	_cleanup(_configuration)
 | |
| 
 | |
| 	try:
 | |
| 		with open(_file_path, 'w') as config_file:
 | |
| 			_json_save(_configuration, config_file, skipkeys=True, indent=2, sort_keys=True)
 | |
| 
 | |
| 		if _log.isEnabledFor(_INFO):
 | |
| 			_log.info("saved %s to %s", _configuration, _file_path)
 | |
| 		return True
 | |
| 	except:
 | |
| 		_log.error("failed to save to %s", _file_path)
 | |
| 
 | |
| 
 | |
| def _cleanup(d):
 | |
| 	# remove None values from the dict
 | |
| 	for key in list(d.keys()):
 | |
| 		value = d.get(key)
 | |
| 		if value is None:
 | |
| 			del d[key]
 | |
| 		elif isinstance(value, dict):
 | |
| 			_cleanup(value)
 | |
| 
 | |
| 
 | |
| def _device_key(device):
 | |
| 	return '%s:%s' % (device.wpid, device.serial)
 | |
| 
 | |
| 
 | |
| class _DeviceEntry(dict):
 | |
| 	def __init__(self, *args, **kwargs):
 | |
| 		super(_DeviceEntry, self).__init__(*args, **kwargs)
 | |
| 
 | |
| 	def __setitem__(self, key, value):
 | |
| 		super(_DeviceEntry, self).__setitem__(key, value)
 | |
| 		save()
 | |
| 
 | |
| 
 | |
| def _device_entry(device):
 | |
| 	if not _configuration:
 | |
| 		_load()
 | |
| 
 | |
| 	device_key = _device_key(device)
 | |
| 	c = _configuration.get(device_key) or {}
 | |
| 
 | |
| 	if not isinstance(c, _DeviceEntry):
 | |
| 		c[_KEY_NAME] = device.name
 | |
| 		c = _DeviceEntry(c)
 | |
| 		_configuration[device_key] = c
 | |
| 
 | |
| 	return c
 | |
| 
 | |
| 
 | |
| def attach_to(device):
 | |
| 	"""Apply the last saved configuration to a device."""
 | |
| 	if not _configuration:
 | |
| 		_load()
 | |
| 
 | |
| 	persister = _device_entry(device)
 | |
| 	for s in device.settings:
 | |
| 		if s.persister is None:
 | |
| 			s.persister = persister
 | |
| 		assert s.persister == persister
 |