Clean up code

This commit is contained in:
Florian Bruhin 2017-06-20 17:13:46 +02:00
parent 67cb6a9802
commit 0ed0a6db57

View File

@ -118,10 +118,18 @@ class change_filter: # pylint: disable=invalid-name
return wrapper return wrapper
class NewKeyConfig: class KeyConfig:
def __init__(self, manager): """Utilities related to keybindings.
self._manager = manager
Note that the actual values are saved in the config itself, not here.
Attributes:
_config: The Config object to be used.
"""
def __init__(self, config):
self._config = config
def get_reverse_bindings_for(self, mode): def get_reverse_bindings_for(self, mode):
"""Get a dict of commands to a list of bindings for the mode.""" """Get a dict of commands to a list of bindings for the mode."""
@ -172,7 +180,7 @@ class NewKeyConfig:
if key in bindings and not force: if key in bindings and not force:
raise configexc.DuplicateKeyError(key) raise configexc.DuplicateKeyError(key)
bindings[key] = command bindings[key] = command
self._manager.update_mutables(save_yaml=save_yaml) self._config.update_mutables(save_yaml=save_yaml)
def unbind(self, key, *, mode='normal', save_yaml=False): def unbind(self, key, *, mode='normal', save_yaml=False):
"""Unbind the given key in the given mode.""" """Unbind the given key in the given mode."""
@ -183,7 +191,7 @@ class NewKeyConfig:
except KeyError: except KeyError:
raise configexc.KeybindingError("Can't find binding '{}' in section '{}'!" raise configexc.KeybindingError("Can't find binding '{}' in section '{}'!"
.format(key, mode)) .format(key, mode))
self._manager.update_mutables(save_yaml=save_yaml) self._config.update_mutables(save_yaml=save_yaml)
def get_command(self, key, mode): def get_command(self, key, mode):
"""Get the command for a given key (or None).""" """Get the command for a given key (or None)."""
@ -193,6 +201,8 @@ class NewKeyConfig:
class ConfigCommands: class ConfigCommands:
"""qutebrowser commands related to the configuration."""
def __init__(self, config): def __init__(self, config):
self._config = config self._config = config
@ -330,7 +340,20 @@ class ConfigCommands:
raise cmdexc.CommandError(str(e)) raise cmdexc.CommandError(str(e))
class NewConfigManager(QObject): class Config(QObject):
"""Main config object.
Attributes:
options: A dict mapping setting names to configdata.Option objects.
Those contain the type, default value, etc.
_values: A dict mapping setting names to their values.
_mutables: A list of mutable objects to be checked for changes.
_yaml: A YamlConfig object.
Signals:
changed: Emitted with the option name when an option changed.
"""
changed = pyqtSignal(str) changed = pyqtSignal(str)
@ -342,14 +365,17 @@ class NewConfigManager(QObject):
self._yaml = configfiles.YamlConfig() self._yaml = configfiles.YamlConfig()
def _changed(self, name, value): def _changed(self, name, value):
"""Emit changed signal and log change."""
self.changed.emit(name) self.changed.emit(name)
log.config.debug("Config option changed: {} = {}".format(name, value)) log.config.debug("Config option changed: {} = {}".format(name, value))
def read_defaults(self): def read_configdata(self):
"""Read the option objects from configdata."""
for name, option in configdata.DATA.items(): for name, option in configdata.DATA.items():
self.options[name] = option self.options[name] = option
def read_yaml(self): def read_yaml(self):
"""Read the YAML settings from self._yaml."""
self._yaml.load() self._yaml.load()
for name, value in self._yaml.values.items(): for name, value in self._yaml.values.items():
opt = self.get_opt(name) opt = self.get_opt(name)
@ -357,17 +383,23 @@ class NewConfigManager(QObject):
self._values[name] = value self._values[name] = value
def get_opt(self, name): def get_opt(self, name):
"""Get a configdata.Option object for the given setting."""
try: try:
return self.options[name] return self.options[name]
except KeyError: except KeyError:
raise configexc.NoOptionError(name) raise configexc.NoOptionError(name)
def get(self, name): def get(self, name):
"""Get the given setting converted for Python code."""
opt = self.get_opt(name) opt = self.get_opt(name)
obj = self.get_obj(name, mutable=False) obj = self.get_obj(name, mutable=False)
return opt.typ.to_py(obj) return opt.typ.to_py(obj)
def get_obj(self, name, *, mutable=True): def get_obj(self, name, *, mutable=True):
"""Get the given setting as object (for YAML/config.py).
If mutable=True is set, watch the returned object for mutations.
"""
opt = self.get_opt(name) opt = self.get_opt(name)
obj = self._values.get(name, opt.default) obj = self._values.get(name, opt.default)
if isinstance(obj, (dict, list)): if isinstance(obj, (dict, list)):
@ -379,11 +411,16 @@ class NewConfigManager(QObject):
return obj return obj
def get_str(self, name): def get_str(self, name):
"""Get the given setting as string."""
opt = self.get_opt(name) opt = self.get_opt(name)
value = self._values.get(name, opt.default) value = self._values.get(name, opt.default)
return opt.typ.to_str(value) return opt.typ.to_str(value)
def set_obj(self, name, value, *, save_yaml=False): def set_obj(self, name, value, *, save_yaml=False):
"""Set the given setting from a YAML/config.py object.
If save_yaml=True is given, store the new value to YAML.
"""
opt = self.get_opt(name) opt = self.get_opt(name)
opt.typ.to_py(value) # for validation opt.typ.to_py(value) # for validation
self._values[name] = value self._values[name] = value
@ -392,6 +429,10 @@ class NewConfigManager(QObject):
self._yaml.values[name] = value self._yaml.values[name] = value
def set_str(self, name, value, *, save_yaml=False): def set_str(self, name, value, *, save_yaml=False):
"""Set the given setting from a string.
If save_yaml=True is given, store the new value to YAML.
"""
opt = self.get_opt(name) opt = self.get_opt(name)
converted = opt.typ.from_str(value) converted = opt.typ.from_str(value)
self._values[name] = converted self._values[name] = converted
@ -400,6 +441,14 @@ class NewConfigManager(QObject):
self._yaml.values[name] = converted self._yaml.values[name] = converted
def update_mutables(self, *, save_yaml=False): def update_mutables(self, *, save_yaml=False):
"""Update mutable settings if they changed.
Every time someone calls get_obj() on a mutable object, we save a
reference to the original object and a copy.
Here, we check all those saved copies for mutations, and if something
mutated, we call set_obj again so we save the new value.
"""
for name, old_value, new_value in self._mutables: for name, old_value, new_value in self._mutables:
if old_value != new_value: if old_value != new_value:
log.config.debug("{} was mutated, updating".format(name)) log.config.debug("{} was mutated, updating".format(name))
@ -424,16 +473,16 @@ class ConfigContainer:
"""An object implementing config access via __getattr__. """An object implementing config access via __getattr__.
Attributes: Attributes:
_manager: The ConfigManager object. _config: The Config object.
_prefix: The __getattr__ chain leading up to this object. _prefix: The __getattr__ chain leading up to this object.
""" """
def __init__(self, manager, prefix=''): def __init__(self, config, prefix=''):
self._manager = manager self._config = config
self._prefix = prefix self._prefix = prefix
def __repr__(self): def __repr__(self):
return utils.get_repr(self, constructor=True, manager=self._manager, return utils.get_repr(self, constructor=True, config=self._config,
prefix=self._prefix) prefix=self._prefix)
def __getattr__(self, attr): def __getattr__(self, attr):
@ -450,20 +499,22 @@ class ConfigContainer:
name = self._join(attr) name = self._join(attr)
if configdata.is_valid_prefix(name): if configdata.is_valid_prefix(name):
return ConfigContainer(manager=self._manager, prefix=name) return ConfigContainer(config=self._config, prefix=name)
try: try:
return self._manager.get(name) return self._config.get(name)
except configexc.NoOptionError as e: except configexc.NoOptionError as e:
# If it's not a valid prefix - re-raise to improve error text. # If it's not a valid prefix - re-raise to improve error text.
raise configexc.NoOptionError(name) raise configexc.NoOptionError(name)
def __setattr__(self, attr, value): def __setattr__(self, attr, value):
"""Set the given option in the config."""
if attr.startswith('_'): if attr.startswith('_'):
return super().__setattr__(attr, value) return super().__setattr__(attr, value)
self._manager.set_obj(self._join(attr), value) self._config.set_obj(self._join(attr), value)
def _join(self, attr): def _join(self, attr):
"""Get the prefix joined with the given attribute."""
if self._prefix: if self._prefix:
return '{}.{}'.format(self._prefix, attr) return '{}.{}'.format(self._prefix, attr)
else: else:
@ -478,18 +529,18 @@ def init(parent=None):
""" """
configdata.init() configdata.init()
new_config = NewConfigManager(parent) config = Config(parent)
new_config.read_defaults() config.read_configdata()
new_config.read_yaml() config.read_yaml()
objreg.register('config', new_config) objreg.register('config', config)
config_commands = ConfigCommands(new_config) config_commands = ConfigCommands(config)
objreg.register('config-commands', config_commands) objreg.register('config-commands', config_commands)
global val, instance, key_instance global val, instance, key_instance
val = ConfigContainer(new_config) val = ConfigContainer(config)
instance = new_config instance = config
key_instance = NewKeyConfig(new_config) key_instance = KeyConfig(config)
for cf in _change_filters: for cf in _change_filters:
cf.validate() cf.validate()