From 9b876f64637d1cd6aa2d6670b7c56988d7afe568 Mon Sep 17 00:00:00 2001 From: gwen Date: Mon, 23 Jul 2012 14:30:06 +0200 Subject: [PATCH] multies are working now --- src/config.py | 50 +++++++++++++++--------------- src/option.py | 86 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 75 insertions(+), 61 deletions(-) diff --git a/src/config.py b/src/config.py index f4fabdd..851ac77 100644 --- a/src/config.py +++ b/src/config.py @@ -27,6 +27,7 @@ from error import (HiddenOptionError, ConfigError, NotFoundError, from option import (OptionDescription, Option, SymLinkOption, group_types, Multi, apply_requires, modes) from autolib import special_owners, special_owner_factory +from copy import copy # ______________________________________________________________________ # generic owner. 'default' is the general config owner after init time default_owner = 'user' @@ -68,10 +69,10 @@ class Config(object): for child in self._cfgimpl_descr._children: if isinstance(child, Option): if child.is_multi(): - childdef = Multi(child.getdefault(), config=self, + childdef = Multi(copy(child.getdefault()), config=self, child=child) self._cfgimpl_values[child._name] = childdef - self._cfgimpl_previous_values[child._name] = childdef + self._cfgimpl_previous_values[child._name] = list(childdef) else: childdef = child.getdefault() self._cfgimpl_values[child._name] = childdef @@ -100,9 +101,14 @@ class Config(object): for child in self._cfgimpl_descr._children: if isinstance(child, Option): if child._name not in self._cfgimpl_values: - self._cfgimpl_values[child._name] = child.getdefault() - # FIXME and ['default', ...] if is_multi() ? - self._cfgimpl_value_owners[child._name] = 'default' + if child.is_multi(): + self._cfgimpl_values[child._name] = Multi( + copy(child.getdefault()), config=self, child=child) + self._cfgimpl_value_owners[child._name] = ['default' \ + for i in range(len(child.getdefault() ))] + else: + self._cfgimpl_values[child._name] = copy(child.getdefault()) + self._cfgimpl_value_owners[child._name] = 'default' elif isinstance(child, OptionDescription): if child._name not in self._cfgimpl_values: self._cfgimpl_values[child._name] = Config(child, parent=self) @@ -223,7 +229,7 @@ class Config(object): config=self._cfgimpl_get_toplevel()) # this result **shall not** be a list # for example, [1, 2, 3, None] -> [1, 2, 3, result] - if type(result) == list: + if isinstance(result, list): raise ConfigError('invalid calculated value returned' ' for option {0} : shall not be a list'.format(name)) if result != None and not opt_or_descr._validate(result): @@ -231,9 +237,9 @@ class Config(object): ' for option {0}'.format(name)) if opt_or_descr.is_multi(): if value == []: - _result = [result] + _result = Multi([result], value.config, value.child) else: - _result = [] + _result = Multi([], value.config, value.child) for val in value: if val == None: val = result @@ -250,19 +256,8 @@ class Config(object): and opt_or_descr.getdefault() == None: raise MandatoryError("option: {0} is mandatory " "and shall have a value".format(name)) - # for multi types with None in the value (ex: ["egg", None, "spam"]) - # None is replaced by default_multi - if not isinstance(opt_or_descr, OptionDescription): - if opt_or_descr.is_multi() and None in self._cfgimpl_values[name]: - newvalue = [] - for val in self._cfgimpl_values[name]: - if val is None: - newvalue.append(opt_or_descr.default_multi) - else: - newvalue.append(val) - return newvalue return self._cfgimpl_values[name] - + def __dir__(self): #from_type = dir(type(self)) from_dict = list(self.__dict__) @@ -301,6 +296,7 @@ class Config(object): def setoption(self, name, value, who=None): #who is **not necessarily** a owner, because it cannot be a list + #FIXME : sortir le setoption pour les multi, ca ne devrait pas être la child = getattr(self._cfgimpl_descr, name) if who == None: if child.is_multi(): @@ -310,8 +306,11 @@ class Config(object): else: if type(child) != SymLinkOption: if child.is_multi(): - if type(value) != list: - raise ConfigError("invalid value for option:" + if type(value) != Multi: + if type(value) == list: + value = Multi(value, self, child) + else: + raise ConfigError("invalid value for option:" " {0} that is set to multi".format(name)) newowner = [who for i in range(len(value))] else: @@ -336,10 +335,11 @@ class Config(object): child.hide() if (value is None and who != 'default' and not child.is_multi()): child.setowner(self, 'default') - self._cfgimpl_values[name] = child.getdefault() + self._cfgimpl_values[name] = copy(child.getdefault()) elif (value == [] and who != 'default' and child.is_multi()): child.setowner(self, ['default' for i in range(len(child.getdefault()))]) - self._cfgimpl_values[name] = child.getdefault() + self._cfgimpl_values[name] = Multi(copy(child.getdefault()), + config=self, child=child) else: child.setowner(self, newowner) else: @@ -444,7 +444,7 @@ class Config(object): self.cfgimpl_unfreeze() rootconfig = self._cfgimpl_get_toplevel() rootconfig._cfgimpl_hidden = True - rootconfig._cfgimpl_disabled = False + rootconfig._cfgimpl_disabled = True rootconfig._cfgimpl_mandatory = False # ____________________________________________________________ def getkey(self): diff --git a/src/option.py b/src/option.py index ce06324..d6de739 100644 --- a/src/option.py +++ b/src/option.py @@ -31,49 +31,53 @@ reverse_actions = {'hide': 'show', 'show': 'hide', # OptionDescription authorized group_type values group_types = ['default', 'family', 'group', 'master'] # multi types + class Multi(list): "container that support items for the values of list (multi) options" - def __init__(self, lst, config=None, child=None): + def __init__(self, lst, config, child): self.config = config self.child = child super(Multi, self).__init__(lst) - def __getitem__(self, key): - value = super(Multi, self).__getitem__(key) - if value is None: - return self.child.default_multi - else: - return value - def __setitem__(self, key, value): - if value is None: - owner = 'default' - else: - owner = self.config._cfgimpl_owner - oldowner = self.child.getowner(self.config) - oldowner[key] = owner - self.child.setowner(self.config, oldowner) - if value != None and not self.child._validate(value): - raise ConfigError("invalid value {0} " - "for option {1}".format(str(value), self.child._name)) - return super(Multi, self).__setitem__(key, value) + return self.setoption(value, key) def append(self, value): - if value is None: - owner = 'default' + self.setoption(value) + + def setoption(self, value, key=None): + owners = self.child.getowner(self.config) + # None is replaced by default_multi + if value == None: + defval = self.child.getdefault() + if key is not None and len(defval) > key: + value = defval[key] + else: + value = self.child.default_multi + who = 'default' else: - owner = self.config._cfgimpl_owner + who = self.config._cfgimpl_owner + if not self.child._validate(value): + raise ConfigError("invalid value {0} " + "for option {1}".format(str(value), self.child._name)) + oldvalue = list(self) oldowner = self.child.getowner(self.config) - oldowner.append(owner) + if key is None: + ret = super(Multi, self).append(value) + oldvalue.append(None) + oldowner.append(who) + else: + ret = super(Multi, self).__setitem__(key, value) + oldowner[key] = who + self.config._cfgimpl_previous_values[self.child._name] = oldvalue self.child.setowner(self.config, oldowner) - # changer dans la config la valeur par défaut et le owner - if value != None and not self.child._validate(value): - raise ConfigError("invalid value {0} " - "for option {1}".format(str(value), self.child._name)) - super(Multi, self).append(value) - -# def pop(self): -# pass + return ret + + def pop(self, key): + oldowner = self.child.getowner(self.config) + oldowner.pop(key) + self.child.setowner(self.config, oldowner) + super(Multi, self).pop(key) # ____________________________________________________________ # class Option(HiddenBaseType, DisabledBaseType, ModeBaseType): @@ -202,7 +206,10 @@ class Option(HiddenBaseType, DisabledBaseType, ModeBaseType): # raise ConflictConfigError("an option with requires " # "has not the same length of the others " # "in the group : {0}".format(reqname)) - config._cfgimpl_previous_values[name] = config._cfgimpl_values[name] + if type(config._cfgimpl_values[name]) == Multi: + config._cfgimpl_previous_values[name] = list(config._cfgimpl_values[name]) + else: + config._cfgimpl_previous_values[name] = config._cfgimpl_values[name] config._cfgimpl_values[name] = value def getkey(self, value): @@ -224,10 +231,14 @@ class Option(HiddenBaseType, DisabledBaseType, ModeBaseType): class ChoiceOption(Option): opt_type = 'string' - def __init__(self, name, doc, values, default=None, requires=None, - callback=None, callback_params=None, multi=False, - mandatory=False): + def __init__(self, name, doc, values, open_values=False, default=None, + requires=None, callback=None, callback_params=None, + multi=False, mandatory=False): self.values = values + if open_values not in [True, False]: + raise ConfigError('Open_values must be a boolean for ' + '{0}'.format(name)) + self.open_values = open_values super(ChoiceOption, self).__init__(name, doc, default=default, callback=callback, callback_params=callback_params, requires=requires, multi=multi, mandatory=mandatory) @@ -237,7 +248,10 @@ class ChoiceOption(Option): super(ChoiceOption, self).setoption(config, value, who) def _validate(self, value): - return value is None or value in self.values + if not self.open_values: + return value is None or value in self.values + else: + return True class BoolOption(Option): opt_type = 'bool'