add masters/slaves in the Values()
This commit is contained in:
parent
e6d5d349c8
commit
8f4efe6b00
|
@ -27,7 +27,8 @@ from tiramisu.error import (PropertiesOptionError, ConfigError, NotFoundError,
|
||||||
from tiramisu.option import (OptionDescription, Option, SymLinkOption,
|
from tiramisu.option import (OptionDescription, Option, SymLinkOption,
|
||||||
apply_requires)
|
apply_requires)
|
||||||
from tiramisu.setting import groups, owners, Setting
|
from tiramisu.setting import groups, owners, Setting
|
||||||
from tiramisu.value import OptionValues
|
from tiramisu.value import Values
|
||||||
|
|
||||||
|
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
class Config(object):
|
class Config(object):
|
||||||
|
@ -53,9 +54,9 @@ class Config(object):
|
||||||
self._cfgimpl_context = self
|
self._cfgimpl_context = self
|
||||||
else:
|
else:
|
||||||
self._cfgimpl_context = context
|
self._cfgimpl_context = context
|
||||||
if parent == None:
|
if parent is None:
|
||||||
self._cfgimpl_settings = Setting()
|
self._cfgimpl_settings = Setting()
|
||||||
self._cfgimpl_values = OptionValues(self._cfgimpl_context)
|
self._cfgimpl_values = Values(self._cfgimpl_context)
|
||||||
else:
|
else:
|
||||||
if context is None:
|
if context is None:
|
||||||
raise ConfigError("cannot find a value for this config")
|
raise ConfigError("cannot find a value for this config")
|
||||||
|
@ -95,7 +96,7 @@ class Config(object):
|
||||||
if self._cfgimpl_descr.group_type == groups.master:
|
if self._cfgimpl_descr.group_type == groups.master:
|
||||||
mastername = self._cfgimpl_descr._name
|
mastername = self._cfgimpl_descr._name
|
||||||
masteropt = getattr(self._cfgimpl_descr, mastername)
|
masteropt = getattr(self._cfgimpl_descr, mastername)
|
||||||
self._cfgimpl_values.master_groups[masteropt] = []
|
self._cfgimpl_values.masters[masteropt] = []
|
||||||
|
|
||||||
for child in self._cfgimpl_descr._children:
|
for child in self._cfgimpl_descr._children:
|
||||||
if isinstance(child, OptionDescription):
|
if isinstance(child, OptionDescription):
|
||||||
|
@ -104,11 +105,9 @@ class Config(object):
|
||||||
context=self._cfgimpl_context)
|
context=self._cfgimpl_context)
|
||||||
if (self._cfgimpl_descr.group_type == groups.master and
|
if (self._cfgimpl_descr.group_type == groups.master and
|
||||||
child != masteropt):
|
child != masteropt):
|
||||||
self._cfgimpl_values.master_groups[child] = []
|
self._cfgimpl_values.slaves[child] = masteropt
|
||||||
self._cfgimpl_values.master_groups[masteropt].append(child)
|
self._cfgimpl_values.masters[masteropt].append(child)
|
||||||
|
|
||||||
if self._cfgimpl_descr.group_type == groups.master:
|
|
||||||
print self._cfgimpl_values.master_groups
|
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
# attribute methods
|
# attribute methods
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
|
@ -241,7 +240,7 @@ class Config(object):
|
||||||
except MandatoryError:
|
except MandatoryError:
|
||||||
pass
|
pass
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
raise e # HiddenOptionError or DisabledOptionError
|
raise e # HiddenOptionError or DisabledOptionError
|
||||||
homeconfig.setoption(name, value)
|
homeconfig.setoption(name, value)
|
||||||
elif len(candidates) > 1:
|
elif len(candidates) > 1:
|
||||||
raise AmbigousOptionError(
|
raise AmbigousOptionError(
|
||||||
|
@ -249,7 +248,7 @@ class Config(object):
|
||||||
else:
|
else:
|
||||||
raise NoMatchingOptionFound(
|
raise NoMatchingOptionFound(
|
||||||
'there is no option that matches %s'
|
'there is no option that matches %s'
|
||||||
' or the option is hidden or disabled'% (key, ))
|
' or the option is hidden or disabled' % (key, ))
|
||||||
|
|
||||||
def get(self, name):
|
def get(self, name):
|
||||||
"""
|
"""
|
||||||
|
@ -379,7 +378,6 @@ class Config(object):
|
||||||
|
|
||||||
__repr__ = __str__
|
__repr__ = __str__
|
||||||
|
|
||||||
|
|
||||||
def getpaths(self, include_groups=False, allpaths=False, mandatory=False):
|
def getpaths(self, include_groups=False, allpaths=False, mandatory=False):
|
||||||
"""returns a list of all paths in self, recursively, taking care of
|
"""returns a list of all paths in self, recursively, taking care of
|
||||||
the context of properties (hidden/disabled)
|
the context of properties (hidden/disabled)
|
||||||
|
@ -438,7 +436,7 @@ class Config(object):
|
||||||
value = getattr(self, path)
|
value = getattr(self, path)
|
||||||
if value == byvalue:
|
if value == byvalue:
|
||||||
return True
|
return True
|
||||||
except: # a property restricts the access of the value
|
except: # a property restricts the access of the value
|
||||||
pass
|
pass
|
||||||
return False
|
return False
|
||||||
def _filter_by_type():
|
def _filter_by_type():
|
||||||
|
@ -497,6 +495,7 @@ class Config(object):
|
||||||
"""
|
"""
|
||||||
return self._find(bytype, byname, byvalue, byattrs, first=True)
|
return self._find(bytype, byname, byvalue, byattrs, first=True)
|
||||||
|
|
||||||
|
|
||||||
def make_dict(config, flatten=False):
|
def make_dict(config, flatten=False):
|
||||||
"""export the whole config into a `dict`
|
"""export the whole config into a `dict`
|
||||||
:returns: dict of Option's name (or path) and values"""
|
:returns: dict of Option's name (or path) and values"""
|
||||||
|
@ -511,10 +510,11 @@ def make_dict(config, flatten=False):
|
||||||
value = getattr(config, path)
|
value = getattr(config, path)
|
||||||
pathsvalues.append((pathname, value))
|
pathsvalues.append((pathname, value))
|
||||||
except:
|
except:
|
||||||
pass # this just a hidden or disabled option
|
pass # this just a hidden or disabled option
|
||||||
options = dict(pathsvalues)
|
options = dict(pathsvalues)
|
||||||
return options
|
return options
|
||||||
|
|
||||||
|
|
||||||
def mandatory_warnings(config):
|
def mandatory_warnings(config):
|
||||||
"""convenience function to trace Options that are mandatory and
|
"""convenience function to trace Options that are mandatory and
|
||||||
where no value has been set
|
where no value has been set
|
||||||
|
|
|
@ -25,3 +25,5 @@ class NoValueReturned(Exception):
|
||||||
pass
|
pass
|
||||||
class OptionValueError(Exception):
|
class OptionValueError(Exception):
|
||||||
pass
|
pass
|
||||||
|
class MultiTypeError(Exception):
|
||||||
|
pass
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
# the whole pypy projet is under MIT licence
|
# the whole pypy projet is under MIT licence
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
from tiramisu.error import NoValueReturned, MandatoryError
|
from tiramisu.error import NoValueReturned, MandatoryError
|
||||||
from tiramisu.setting import owners
|
from tiramisu.setting import owners, multitypes
|
||||||
|
|
||||||
class OptionValues(object):
|
class Values(object):
|
||||||
def __init__(self, context):
|
def __init__(self, context):
|
||||||
"""
|
"""
|
||||||
Initializes the values's dict.
|
Initializes the values's dict.
|
||||||
|
@ -34,17 +34,25 @@ class OptionValues(object):
|
||||||
"Config's root indeed is in charge of the `Option()`'s values"
|
"Config's root indeed is in charge of the `Option()`'s values"
|
||||||
self.values = {}
|
self.values = {}
|
||||||
self.previous_values = {}
|
self.previous_values = {}
|
||||||
self.master_groups = {}
|
self.masters = {}
|
||||||
|
self.slaves = {}
|
||||||
self.context = context
|
self.context = context
|
||||||
|
|
||||||
def _get_value(self, opt):
|
def _get_value(self, opt):
|
||||||
"special case for the multis: they never return None"
|
"special case for the multis: they never return None"
|
||||||
if opt.is_multi():
|
if opt not in self.values:
|
||||||
if opt not in self.values:
|
if opt.is_multi():
|
||||||
|
if opt in self.slaves:
|
||||||
|
# slave
|
||||||
|
multitype = multitypes.slave
|
||||||
|
elif opt in self.masters:
|
||||||
|
# master
|
||||||
|
multitype = multitypes.master
|
||||||
# FIXME : default value for a multi, we shall work on groups
|
# FIXME : default value for a multi, we shall work on groups
|
||||||
return Multi(opt.getdefault(), self.context, opt)
|
else:
|
||||||
else:
|
multitype = multitypes.default
|
||||||
if opt not in self.values:
|
return Multi(opt.getdefault(), self.context, opt, multitype)
|
||||||
|
else:
|
||||||
return opt.getdefault()
|
return opt.getdefault()
|
||||||
return self.values[opt]
|
return self.values[opt]
|
||||||
|
|
||||||
|
@ -128,6 +136,21 @@ class OptionValues(object):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def __setitem__(self, opt, value):
|
def __setitem__(self, opt, value):
|
||||||
|
if opt in self.masters:
|
||||||
|
masterlen = len(value)
|
||||||
|
for slave in masters[opt]:
|
||||||
|
if len(self._get_value(slave)) != masterlen:
|
||||||
|
raise MultiTypeError("invalid len for the slave: {0}"
|
||||||
|
"which has {1} as master".format(slave._name,
|
||||||
|
master._name))
|
||||||
|
elif opt in self.slaves:
|
||||||
|
if len(self._get_value(self.slaves[opt])) != len(value):
|
||||||
|
raise MultiTypeError("invalid len for the slave: {0}"
|
||||||
|
"which has {1} as master".format(slave._name,
|
||||||
|
master._name))
|
||||||
|
self.setitem(opt, value)
|
||||||
|
|
||||||
|
def setitem(self, opt, value):
|
||||||
self.set_previous_value(opt)
|
self.set_previous_value(opt)
|
||||||
self.values[opt] = value
|
self.values[opt] = value
|
||||||
self.setowner(opt, self.context._cfgimpl_settings.getowner())
|
self.setowner(opt, self.context._cfgimpl_settings.getowner())
|
||||||
|
@ -149,7 +172,7 @@ class OptionValues(object):
|
||||||
class Multi(list):
|
class Multi(list):
|
||||||
"""multi options values container
|
"""multi options values container
|
||||||
that support item notation for the values of multi options"""
|
that support item notation for the values of multi options"""
|
||||||
def __init__(self, lst, context, opt, multitype=settings.multitypes.default):
|
def __init__(self, lst, context, opt, multitype):
|
||||||
"""
|
"""
|
||||||
:param lst: the Multi wraps a list value
|
:param lst: the Multi wraps a list value
|
||||||
:param context: the home config that has the settings and the values
|
:param context: the home config that has the settings and the values
|
||||||
|
@ -160,40 +183,48 @@ class Multi(list):
|
||||||
self.values = context._cfgimpl_values
|
self.values = context._cfgimpl_values
|
||||||
self.multitype = multitype
|
self.multitype = multitype
|
||||||
super(Multi, self).__init__(lst)
|
super(Multi, self).__init__(lst)
|
||||||
|
if multitype == multitypes.master:
|
||||||
|
self.slaves = context._cfgimpl_values.masters[opt]
|
||||||
|
else:
|
||||||
|
self.slaves = None
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
self._setvalue(value, key, who=self.settings.getowner())
|
self._validate(value)
|
||||||
|
self.values[self.opt] = self
|
||||||
|
super(Multi, self).__setitem__(key, value)
|
||||||
|
|
||||||
def append(self, value):
|
def append(self, value, force=False):
|
||||||
"""the list value can be updated (appened)
|
"""the list value can be updated (appened)
|
||||||
only if the option is a master
|
only if the option is a master
|
||||||
"""
|
"""
|
||||||
self._setvalue(value, who=self.settings.getowner(self.opt))
|
if not force:
|
||||||
|
if self.multitype == multitypes.slave:
|
||||||
|
raise MultiTypeError("cannot append a value on a multi option {0}"
|
||||||
|
" wich is a slave".format(self.opt._name))
|
||||||
|
elif self.multitype == multitypes.master:
|
||||||
|
for slave in self.slaves:
|
||||||
|
self.values[slave].append(None, force=True)
|
||||||
|
self._validate(value)
|
||||||
|
self.values.setitem(self.opt, self)
|
||||||
|
super(Multi, self).append(value)
|
||||||
|
|
||||||
def _setvalue(self, value, key=None, who=None):
|
def _validate(self, value):
|
||||||
if value != None:
|
if value != None and not self.opt._validate(value):
|
||||||
if not self.opt._validate(value):
|
raise ConfigError("invalid value {0} "
|
||||||
raise ConfigError("invalid value {0} "
|
|
||||||
"for option {1}".format(str(value), self.opt._name))
|
"for option {1}".format(str(value), self.opt._name))
|
||||||
oldvalue = list(self)
|
|
||||||
if key is None:
|
|
||||||
super(Multi, self).append(value)
|
|
||||||
else:
|
|
||||||
super(Multi, self).__setitem__(key, value)
|
|
||||||
if who != None:
|
|
||||||
if not isinstance(who, owners.Owner):
|
|
||||||
raise TypeError("invalid owner {0} for the value {1}".format(
|
|
||||||
str(who), str(value)))
|
|
||||||
self.values.setowner(self.opt, getattr(owners, who))
|
|
||||||
self.values.previous_values[self.opt] = oldvalue
|
|
||||||
|
|
||||||
def pop(self, key):
|
def pop(self, key, force=False):
|
||||||
"""the list value can be updated (poped)
|
"""the list value can be updated (poped)
|
||||||
only if the option is a master
|
only if the option is a master
|
||||||
|
|
||||||
:param key: index of the element to pop
|
:param key: index of the element to pop
|
||||||
:return: the requested element
|
:return: the requested element
|
||||||
"""
|
"""
|
||||||
self.values.setowner(opt, self.settings.get_owner())
|
if not force:
|
||||||
self.values.previous_values[self.opt] = list(self)
|
if self.multitype == multitypes.slave:
|
||||||
|
raise MultiTypeError("cannot append a value on a multi option {0}"
|
||||||
|
" wich is a slave".format(self.opt._name))
|
||||||
|
elif self.multitype == multitypes.master:
|
||||||
|
for slave in self.slaves:
|
||||||
|
self.values[slave].pop(key, force=True)
|
||||||
|
self.values.setitem(self.opt, self)
|
||||||
return super(Multi, self).pop(key)
|
return super(Multi, self).pop(key)
|
||||||
|
|
Loading…
Reference in New Issue