Merge branch 'conflayers'
This commit is contained in:
commit
fb6d0a5c62
@ -172,14 +172,16 @@ class Config(QObject):
|
|||||||
else:
|
else:
|
||||||
lines += wrapper.wrap('Valid values: {}'.format(', '.join(
|
lines += wrapper.wrap('Valid values: {}'.format(', '.join(
|
||||||
valid_values)))
|
valid_values)))
|
||||||
lines += wrapper.wrap('Default: {}'.format(option.default))
|
lines += wrapper.wrap('Default: {}'.format(
|
||||||
|
option.values['default']))
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
def _str_items(self, section):
|
def _str_items(self, section):
|
||||||
"""Get the option items as string for section."""
|
"""Get the option items as string for section."""
|
||||||
lines = []
|
lines = []
|
||||||
for optname, option in section.items():
|
for optname, option in section.items():
|
||||||
keyval = '{} = {}'.format(optname, option)
|
keyval = '{} = {}'.format(optname, option.get_first_value(
|
||||||
|
startlayer='conf'))
|
||||||
lines.append(keyval)
|
lines.append(keyval)
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
@ -272,11 +274,26 @@ class Config(QObject):
|
|||||||
"""
|
"""
|
||||||
# FIXME completion for values
|
# FIXME completion for values
|
||||||
try:
|
try:
|
||||||
self.set(section, option, value)
|
self.set('conf', section, option, value)
|
||||||
except (NoOptionError, NoSectionError, ValidationError) as e:
|
except (NoOptionError, NoSectionError, ValidationError) as e:
|
||||||
message.error("set: {} - {}".format(e.__class__.__name__, e))
|
message.error("set: {} - {}".format(e.__class__.__name__, e))
|
||||||
|
|
||||||
def set(self, section, option, value):
|
@cmdutils.register(name='set_temp', instance='config',
|
||||||
|
completion=['section', 'option'])
|
||||||
|
def set_temp_wrapper(self, section, option, value):
|
||||||
|
"""Set a temporary option.
|
||||||
|
|
||||||
|
Wrapper for self.set() to output exceptions in the status bar.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
*args: Get passed to self.set().
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.set('temp', section, option, value)
|
||||||
|
except (NoOptionError, NoSectionError, ValidationError) as e:
|
||||||
|
message.error("set: {} - {}".format(e.__class__.__name__, e))
|
||||||
|
|
||||||
|
def set(self, layer, section, option, value):
|
||||||
"""Set an option.
|
"""Set an option.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -296,11 +313,11 @@ class Config(QObject):
|
|||||||
value = self._interpolation.before_set(self, section, option,
|
value = self._interpolation.before_set(self, section, option,
|
||||||
value)
|
value)
|
||||||
try:
|
try:
|
||||||
sectdict = self.config[section]
|
sect = self.config[section]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise NoSectionError(section)
|
raise NoSectionError(section)
|
||||||
try:
|
try:
|
||||||
sectdict[self.optionxform(option)] = value
|
sect.setv(layer, option, value)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise NoOptionError(option, section)
|
raise NoOptionError(option, section)
|
||||||
else:
|
else:
|
||||||
@ -322,13 +339,16 @@ class Config(QObject):
|
|||||||
Return:
|
Return:
|
||||||
The changed config part as string.
|
The changed config part as string.
|
||||||
"""
|
"""
|
||||||
|
# FIXME adopt this for layering
|
||||||
lines = []
|
lines = []
|
||||||
for secname, section in self.config.items():
|
for secname, section in self.config.items():
|
||||||
changed_opts = []
|
changed_opts = []
|
||||||
for optname, option in section.items():
|
for optname, option in section.items():
|
||||||
if (option.rawvalue is not None and
|
if (option.values.temp is not None and
|
||||||
option.rawvalue != option.default):
|
option.values.temp != option.default or
|
||||||
keyval = '{} = {}'.format(optname, option)
|
option.values.conf is not None and
|
||||||
|
option.values.conf != option.default):
|
||||||
|
keyval = '{} = {}'.format(optname, option) # FIXME layer?
|
||||||
changed_opts.append(keyval)
|
changed_opts.append(keyval)
|
||||||
if changed_opts:
|
if changed_opts:
|
||||||
lines.append('[{}]'.format(secname))
|
lines.append('[{}]'.format(secname))
|
||||||
@ -409,7 +429,7 @@ class SectionProxy(MutableMapping):
|
|||||||
return self._conf.get(self._name, key)
|
return self._conf.get(self._name, key)
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
return self._conf.set(self._name, key, value)
|
return self._conf.set('conf', self._name, key, value)
|
||||||
|
|
||||||
def __delitem__(self, key):
|
def __delitem__(self, key):
|
||||||
if not (self._conf.has_option(self._name, key) and
|
if not (self._conf.has_option(self._name, key) and
|
||||||
|
@ -64,13 +64,13 @@ class KeyValue:
|
|||||||
return self.values[key]
|
return self.values[key]
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
"""Set the value for key.
|
"""Set the config value for key.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: The key to set the value for, as a string.
|
key: The key to set the value for, as a string.
|
||||||
value: The value to set, as a string
|
value: The value to set, as a string
|
||||||
"""
|
"""
|
||||||
self.values[key].value = value
|
self.setv('conf', key, value)
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
"""Iterate over all set values."""
|
"""Iterate over all set values."""
|
||||||
@ -85,15 +85,29 @@ class KeyValue:
|
|||||||
"""Return whether the section contains a given key."""
|
"""Return whether the section contains a given key."""
|
||||||
return key in self.values
|
return key in self.values
|
||||||
|
|
||||||
|
def setv(self, layer, key, value):
|
||||||
|
"""Set the value on a layer.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
layer: The layer to set the value on, an element name of the
|
||||||
|
ValueLayers dict.
|
||||||
|
key: The key of the element to set.
|
||||||
|
value: The value to set.
|
||||||
|
"""
|
||||||
|
self.values[key].setv(layer, value)
|
||||||
|
|
||||||
def items(self):
|
def items(self):
|
||||||
"""Get dict item tuples."""
|
"""Get dict item tuples."""
|
||||||
return self.values.items()
|
return self.values.items()
|
||||||
|
|
||||||
def from_cp(self, sect):
|
def from_cp(self, sect):
|
||||||
"""Initialize the values from a configparser section."""
|
"""Initialize the values from a configparser section.
|
||||||
|
|
||||||
|
We assume all keys already exist from the defaults.
|
||||||
|
"""
|
||||||
for k, v in sect.items():
|
for k, v in sect.items():
|
||||||
logging.debug("'{}' = '{}'".format(k, v))
|
logging.debug("'{}' = '{}'".format(k, v))
|
||||||
self.values[k].value = v
|
self.values[k].setv('conf', v)
|
||||||
|
|
||||||
|
|
||||||
class ValueList:
|
class ValueList:
|
||||||
@ -117,6 +131,9 @@ class ValueList:
|
|||||||
# KeyValue section.
|
# KeyValue section.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# FIXME use a ChainMap for this
|
||||||
|
# FIXME how to handle value layers here?
|
||||||
|
|
||||||
def __init__(self, keytype, valtype, *defaults):
|
def __init__(self, keytype, valtype, *defaults):
|
||||||
"""Wrap types over default values. Take care when overriding this."""
|
"""Wrap types over default values. Take care when overriding this."""
|
||||||
self.keytype = keytype
|
self.keytype = keytype
|
||||||
@ -149,14 +166,13 @@ class ValueList:
|
|||||||
return self.default[key]
|
return self.default[key]
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
"""Set the value for key.
|
"""Set the config value for key.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key: The key to set the value for, as a string.
|
key: The key to set the value for, as a string.
|
||||||
value: The value to set, as a string
|
value: The value to set, as a string
|
||||||
"""
|
"""
|
||||||
self.values[key] = SettingValue(self.valtype)
|
self.setv('conf', key, value)
|
||||||
self.values[key].value = value
|
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
"""Iterate over all set values."""
|
"""Iterate over all set values."""
|
||||||
@ -174,6 +190,22 @@ class ValueList:
|
|||||||
self.update_valdict()
|
self.update_valdict()
|
||||||
return key in self.valdict
|
return key in self.valdict
|
||||||
|
|
||||||
|
def setv(self, layer, key, value):
|
||||||
|
"""Set the value on a layer.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
layer: The layer to set the value on, an element name of the
|
||||||
|
ValueLayers dict.
|
||||||
|
key: The key of the element to set.
|
||||||
|
value: The value to set.
|
||||||
|
"""
|
||||||
|
if key in self.values:
|
||||||
|
self.values[key].setv(layer, value)
|
||||||
|
else:
|
||||||
|
val = SettingValue(self.valtype)
|
||||||
|
val.setv(layer, value)
|
||||||
|
self.values[key] = val
|
||||||
|
|
||||||
def items(self):
|
def items(self):
|
||||||
"""Get dict items."""
|
"""Get dict items."""
|
||||||
self.update_valdict()
|
self.update_valdict()
|
||||||
@ -186,4 +218,4 @@ class ValueList:
|
|||||||
for k, v in sect.items():
|
for k, v in sect.items():
|
||||||
keytype.validate(k)
|
keytype.validate(k)
|
||||||
valtype.validate(v)
|
valtype.validate(v)
|
||||||
self.values[k] = SettingValue(self.valtype, v)
|
self.setv('conf', k, v)
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
"""A single value (with multiple layers possibly) in the config."""
|
"""A single value (with multiple layers possibly) in the config."""
|
||||||
|
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
|
||||||
class SettingValue:
|
class SettingValue:
|
||||||
|
|
||||||
@ -26,9 +28,9 @@ class SettingValue:
|
|||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
typ: A BaseType subclass.
|
typ: A BaseType subclass.
|
||||||
default: Default value if the user has not overridden it, as a string.
|
value: (readonly property) The currently valid, most important value.
|
||||||
value: (property) The currently valid, most important value.
|
_values: An OrderedDict with the values on different layers, with the
|
||||||
rawvalue: The current value as a raw string.
|
most significant layer first.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, typ, default=None):
|
def __init__(self, typ, default=None):
|
||||||
@ -39,25 +41,62 @@ class SettingValue:
|
|||||||
default: Raw value to set.
|
default: Raw value to set.
|
||||||
"""
|
"""
|
||||||
self.typ = typ()
|
self.typ = typ()
|
||||||
self.rawvalue = None
|
self._values = OrderedDict.fromkeys(['temp', 'conf', 'default'])
|
||||||
self.default = default
|
self._values['default'] = default
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""Get raw string value."""
|
"""Get raw string value."""
|
||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
"""Get the currently valid value."""
|
||||||
|
return self.get_first_value()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def values(self):
|
||||||
|
"""Readonly property for _values."""
|
||||||
|
return self._values
|
||||||
|
|
||||||
|
def getlayers(self, startlayer):
|
||||||
|
"""Get a dict of values starting with startlayer.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
startlayer: The first layer to include.
|
||||||
|
"""
|
||||||
|
idx = list(self._values.keys()).index(startlayer)
|
||||||
|
d = OrderedDict(list(self._values.items())[idx:])
|
||||||
|
return d
|
||||||
|
|
||||||
|
def get_first_value(self, startlayer=None):
|
||||||
|
"""Get the first valid value starting from startlayer.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
startlayer: The first layer to include.
|
||||||
|
"""
|
||||||
|
# pylint: disable=useless-else-on-loop
|
||||||
|
if startlayer is None:
|
||||||
|
d = self._values
|
||||||
|
else:
|
||||||
|
d = self.getlayers(startlayer)
|
||||||
|
for val in d.values():
|
||||||
|
if val is not None:
|
||||||
|
return val
|
||||||
|
else:
|
||||||
|
raise ValueError("No valid config value found!")
|
||||||
|
|
||||||
def transformed(self):
|
def transformed(self):
|
||||||
"""Get the transformed value."""
|
"""Get the transformed value."""
|
||||||
v = self.value
|
v = self.value
|
||||||
return self.typ.transform(v)
|
return self.typ.transform(v)
|
||||||
|
|
||||||
@property
|
def setv(self, layer, value):
|
||||||
def value(self):
|
"""Set the value on a layer.
|
||||||
"""Get the currently valid value."""
|
|
||||||
return self.rawvalue if self.rawvalue is not None else self.default
|
|
||||||
|
|
||||||
@value.setter
|
Arguments:
|
||||||
def value(self, val):
|
layer: The layer to set the value on, an element name of the
|
||||||
"""Set the currently valid value."""
|
ValueLayers dict.
|
||||||
self.typ.validate(val)
|
value: The value to set.
|
||||||
self.rawvalue = val
|
"""
|
||||||
|
self.typ.validate(value)
|
||||||
|
self._values[layer] = value
|
||||||
|
Loading…
Reference in New Issue
Block a user