add masters/slaves in the Values()

This commit is contained in:
gwen 2013-02-22 11:09:17 +01:00
parent e6d5d349c8
commit 8f4efe6b00
3 changed files with 77 additions and 44 deletions

View File

@ -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

View File

@ -25,3 +25,5 @@ class NoValueReturned(Exception):
pass
class OptionValueError(Exception):
pass
class MultiTypeError(Exception):
pass

View File

@ -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)