Skip to content

Commit

Permalink
Implement initial reading from YAML
Browse files Browse the repository at this point in the history
  • Loading branch information
The-Compiler committed Jun 20, 2017
1 parent f990681 commit 6375530
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 15 deletions.
43 changes: 29 additions & 14 deletions qutebrowser/config/config.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def _prepare(self, key, mode):
return utils.normalize_keystr(key) return utils.normalize_keystr(key)
return key return key


def bind(self, key, command, *, mode, force=False): def bind(self, key, command, *, mode, force=False, save_yaml=False):
"""Add a new binding from key to command.""" """Add a new binding from key to command."""
key = self._prepare(key, mode) key = self._prepare(key, mode)


Expand All @@ -172,9 +172,9 @@ def bind(self, key, command, *, mode, force=False):
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() self._manager.update_mutables(save_yaml=save_yaml)


def unbind(self, key, *, mode='normal'): 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."""
key = self._prepare(key, mode) key = self._prepare(key, mode)
bindings = instance.get_obj('bindings.commands')[mode] bindings = instance.get_obj('bindings.commands')[mode]
Expand All @@ -183,7 +183,7 @@ def unbind(self, key, *, mode='normal'):
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() self._manager.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)."""
Expand Down Expand Up @@ -254,7 +254,7 @@ def _set_next(self, option, values):
if len(values) == 1: if len(values) == 1:
# If we have only one value, just set it directly (avoid # If we have only one value, just set it directly (avoid
# breaking stuff like aliases or other pseudo-settings) # breaking stuff like aliases or other pseudo-settings)
self._config.set_str(option, values[0]) self._config.set_str(option, values[0], save_yaml=True)
return return


# Use the next valid value from values, or the first if the current # Use the next valid value from values, or the first if the current
Expand All @@ -266,7 +266,7 @@ def _set_next(self, option, values):
value = values[idx] value = values[idx]
except ValueError: except ValueError:
value = values[0] value = values[0]
self._config.set_str(option, value) self._config.set_str(option, value, save_yaml=True)


@contextlib.contextmanager @contextlib.contextmanager
def _handle_config_error(self): def _handle_config_error(self):
Expand Down Expand Up @@ -310,7 +310,8 @@ def bind(self, key, command=None, *, mode='normal', force=False):
return return


try: try:
key_instance.bind(key, command, mode=mode, force=force) key_instance.bind(key, command, mode=mode, force=force,
save_yaml=True)
except configexc.DuplicateKeyError as e: except configexc.DuplicateKeyError as e:
raise cmdexc.CommandError(str(e) + " - use --force to override!") raise cmdexc.CommandError(str(e) + " - use --force to override!")
except configexc.KeybindingError as e: except configexc.KeybindingError as e:
Expand All @@ -325,7 +326,7 @@ def unbind(self, key, mode='normal'):
mode: A mode to unbind the key in (default: `normal`). mode: A mode to unbind the key in (default: `normal`).
""" """
try: try:
key_instance.unbind(key, mode=mode) key_instance.unbind(key, mode=mode, save_yaml=True)
except configexc.KeybindingError as e: except configexc.KeybindingError as e:
raise cmdexc.CommandError(str(e)) raise cmdexc.CommandError(str(e))


Expand All @@ -339,6 +340,7 @@ def __init__(self, parent=None):
self.options = {} self.options = {}
self._values = {} self._values = {}
self._mutables = [] self._mutables = []
self._yaml = configfiles.YamlConfig()


def _changed(self, name, value): def _changed(self, name, value):
self.changed.emit(name) self.changed.emit(name)
Expand All @@ -348,6 +350,13 @@ def read_defaults(self):
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):
self._yaml.load()
for name, value in self._yaml.values.items():
opt = self.get_opt(name)
opt.typ.to_py(value) # for validation
self._values[name] = value

def get_opt(self, name): def get_opt(self, name):
try: try:
return self.options[name] return self.options[name]
Expand Down Expand Up @@ -375,22 +384,27 @@ def get_str(self, 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): def set_obj(self, name, value, *, save_yaml=False):
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
self._changed(name, value) self._changed(name, value)
if save_yaml:
self._yaml.values[name] = value


def set_str(self, name, value): def set_str(self, name, value, *, save_yaml=False):
opt = self.get_opt(name) opt = self.get_opt(name)
self._values[name] = opt.typ.from_str(value) converted = opt.typ.from_str(value)
self._changed(name, value) self._values[name] = converted
self._changed(name, converted)
if save_yaml:
self._yaml.values[name] = converted


def update_mutables(self): def update_mutables(self, *, save_yaml=False):
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))
self.set_obj(name, new_value) self.set_obj(name, new_value, save_yaml=save_yaml)
self._mutables = [] self._mutables = []


def dump_userconfig(self): def dump_userconfig(self):
Expand Down Expand Up @@ -467,6 +481,7 @@ def init(parent=None):


new_config = NewConfigManager(parent) new_config = NewConfigManager(parent)
new_config.read_defaults() new_config.read_defaults()
new_config.read_yaml()
objreg.register('config', new_config) objreg.register('config', new_config)


config_commands = ConfigCommands(new_config) config_commands = ConfigCommands(new_config)
Expand Down
34 changes: 33 additions & 1 deletion qutebrowser/config/configfiles.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
"""Configuration files residing on disk.""" """Configuration files residing on disk."""


import os.path import os.path
import textwrap
import configparser import configparser


from PyQt5.QtCore import QSettings from PyQt5.QtCore import QSettings


from qutebrowser.utils import objreg, standarddir from qutebrowser.utils import objreg, standarddir, utils, qtutils




class StateConfig(configparser.ConfigParser): class StateConfig(configparser.ConfigParser):
Expand All @@ -51,6 +52,37 @@ def _save(self):
self.write(f) self.write(f)




class YamlConfig:

"""A config stored on disk as YAML file."""

def __init__(self):
save_manager = objreg.get('save-manager')
self._filename = os.path.join(standarddir.config(), 'autoconfig.yml')
save_manager.add_saveable('yaml-config', self._save)
self.values = {}

def _save(self):
"""Save the changed settings to the YAML file."""
data = {'global': self.values}
with qtutils.savefile_open(self._filename) as f:
f.write(textwrap.dedent("""
# DO NOT edit this file by hand, qutebrowser will overwrite it.
# Instead, create a config.py - see :help for details.
""".lstrip('\n')))
utils.yaml_dump(data, f)

def load(self):
"""Load self.values from the configured YAML file."""
# FIXME:conf error handling
try:
with open(self._filename, 'r', encoding='utf-8') as f:
self.values = utils.yaml_load(f)['global']
except FileNotFoundError:
pass


def init(config): def init(config):
"""Initialize config storage not related to the main config.""" """Initialize config storage not related to the main config."""
state = StateConfig() state = StateConfig()
Expand Down

0 comments on commit 6375530

Please sign in to comment.