From 7b4f3b5d365bc26122e36dc61eefe97cb737024d Mon Sep 17 00:00:00 2001 From: gwen Date: Mon, 25 Feb 2013 11:33:20 +0100 Subject: [PATCH] option's name shall not have an api's method name --- test/test_option_with_special_name.py | 18 ++++++++++++++ test/test_parsing_group.py | 36 ++++++++++++++++++++++++++- tiramisu/config.py | 19 +++++++++++--- tiramisu/value.py | 12 ++++----- 4 files changed, 75 insertions(+), 10 deletions(-) diff --git a/test/test_option_with_special_name.py b/test/test_option_with_special_name.py index 9488149..9adaf33 100644 --- a/test/test_option_with_special_name.py +++ b/test/test_option_with_special_name.py @@ -43,3 +43,21 @@ def test_root_config_answers_ok(): settings.enable_property('hiddend') #cfgimpl_hide() assert cfg.dummy == False assert cfg.boolop == True + +def test_optname_shall_not_start_with_numbers(): + "if you hide the root config, the options in this namespace behave normally" + gcdummy = BoolOption('123dummy', 'dummy', default=False) + boolop = BoolOption('boolop', 'Test boolean option op', default=True) + descr = OptionDescription('tiramisu', '', [gcdummy, boolop]) + cfg = Config(descr) + # FIXME devrait lever une exception NameError + settings = cfg.cfgimpl_get_settings() + settings.enable_property('hiddend') #cfgimpl_hide() +# assert cfg.123dummy == False + assert cfg.boolop == True + +def test_option_has_an_api_name(): + gcdummy = BoolOption('cfgimpl_get_settings', 'dummy', default=False) + boolop = BoolOption('boolop', 'Test boolean option op', default=True) + descr = OptionDescription('tiramisu', '', [gcdummy, boolop]) + raises(NameError, "cfg = Config(descr)") diff --git a/test/test_parsing_group.py b/test/test_parsing_group.py index 84eb57d..9148194 100644 --- a/test/test_parsing_group.py +++ b/test/test_parsing_group.py @@ -2,7 +2,7 @@ import autopath from tiramisu.config import * from tiramisu.option import * -from tiramisu.setting import groups +from tiramisu.setting import groups, owners from py.test import raises @@ -121,3 +121,37 @@ def test_group_always_has_multis(): netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau") group = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) raises(ConfigError, "group.set_group_type(groups.master)") + +#____________________________________________________________ + +def test_values_with_master_and_slaves(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True) + interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + interface1.set_group_type(groups.master) + maconfig = OptionDescription('toto', '', [interface1]) + cfg = Config(maconfig) + opt = cfg.unwrap_from_path("ip_admin_eth0.ip_admin_eth0") + owner = cfg._cfgimpl_context._cfgimpl_settings.getowner() + assert interface1.get_group_type() == groups.master + assert opt.getowner(cfg) == owners.default + cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145") + assert cfg.ip_admin_eth0.ip_admin_eth0 == ["192.168.230.145"] + assert opt.getowner(cfg) == owner + +def test_reset_values_with_master_and_slaves(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True) + interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + interface1.set_group_type(groups.master) + maconfig = OptionDescription('toto', '', [interface1]) + cfg = Config(maconfig) + opt = cfg.unwrap_from_path("ip_admin_eth0.ip_admin_eth0") + owner = cfg._cfgimpl_context._cfgimpl_settings.getowner() + assert interface1.get_group_type() == groups.master + assert opt.getowner(cfg) == owners.default + cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145") + assert opt.getowner(cfg) == owner + cfg._cfgimpl_context._cfgimpl_values.reset(opt) + assert opt.getowner(cfg) == owners.default + assert cfg.ip_admin_eth0.ip_admin_eth0 == [] diff --git a/tiramisu/config.py b/tiramisu/config.py index 961d5dc..ab2b04d 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -21,6 +21,7 @@ # the whole pypy projet is under MIT licence # ____________________________________________________________ from copy import copy +from inspect import getmembers, ismethod from tiramisu.error import (PropertiesOptionError, ConfigError, NotFoundError, AmbigousOptionError, ConflictConfigError, NoMatchingOptionFound, MandatoryError, MethodCallError, NoValueReturned) @@ -65,6 +66,10 @@ class Config(object): "warnings are a great idea, let's make up a better use of it" self._cfgimpl_warnings = [] self._cfgimpl_toplevel = self._cfgimpl_get_toplevel() + # some api members shall not be used as option's names ! + methods = getmembers(self, ismethod) + self._cfgimpl_slots = [key for key, value in methods \ + if not key.startswith("_")] self._cfgimpl_build() def cfgimpl_get_settings(self): @@ -96,17 +101,22 @@ 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.masters[masteropt] = [] + self._cfgimpl_context._cfgimpl_values.masters[masteropt] = [] for child in self._cfgimpl_descr._children: if isinstance(child, OptionDescription): self._validate_duplicates(child._children) self._cfgimpl_subconfigs[child] = Config(child, parent=self, context=self._cfgimpl_context) + else: + if child._name in self._cfgimpl_slots: + raise NameError("invalid name for the option:" + " {0}".format(child._name)) + if (self._cfgimpl_descr.group_type == groups.master and child != masteropt): - self._cfgimpl_values.slaves[child] = masteropt - self._cfgimpl_values.masters[masteropt].append(child) + self._cfgimpl_context._cfgimpl_values.slaves[child] = masteropt + self._cfgimpl_context._cfgimpl_values.masters[masteropt].append(child) # ____________________________________________________________ # attribute methods @@ -120,6 +130,9 @@ class Config(object): return setattr(homeconfig, name, value) if type(getattr(self._cfgimpl_descr, name)) != SymLinkOption: self._validate(name, getattr(self._cfgimpl_descr, name)) + if name in self._cfgimpl_slots: + raise NameError("invalid name for the option:" + " {0}".format(name)) self.setoption(name, value) def _validate(self, name, opt_or_descr, permissive=False): diff --git a/tiramisu/value.py b/tiramisu/value.py index 07236d5..74adc5b 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -20,7 +20,7 @@ # the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/ # the whole pypy projet is under MIT licence # ____________________________________________________________ -from tiramisu.error import NoValueReturned, MandatoryError +from tiramisu.error import NoValueReturned, MandatoryError, MultiTypeError from tiramisu.setting import owners, multitypes class Values(object): @@ -138,16 +138,16 @@ class Values(object): def __setitem__(self, opt, value): if opt in self.masters: masterlen = len(value) - for slave in masters[opt]: + for slave in self.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)) + " which has {1} as master".format(slave._name, + opt._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)) + " which has {1} as master".format(opt._name, + self.slaves[opt]._name)) self.setitem(opt, value) def setitem(self, opt, value):