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