From 72f06bc29d8daedad27c43ac32015b7860aabf70 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Thu, 6 Feb 2014 19:19:48 +0100 Subject: [PATCH 1/2] properties option in consistencies are now allowed --- test/test_option_consistency.py | 11 +++++++++++ tiramisu/option.py | 5 +++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/test/test_option_consistency.py b/test/test_option_consistency.py index 4db3410..a7ff41c 100644 --- a/test/test_option_consistency.py +++ b/test/test_option_consistency.py @@ -283,3 +283,14 @@ def test_consistency_not_all(): c.a = ['192.168.1.0'] c.b = ['255.255.255.0'] c.c = ['192.168.1.255'] + + +def test_consistency_permissive(): + a = IntOption('a', '', 1) + b = IntOption('b', '', 2, properties=('hidden',)) + od = OptionDescription('od', '', [a, b]) + a.impl_add_consistency('not_equal', b) + c = Config(od) + c.cfgimpl_get_settings().setpermissive(('hidden',)) + c.read_write() + c.a = 1 diff --git a/tiramisu/option.py b/tiramisu/option.py index 409d6eb..aafd43b 100644 --- a/tiramisu/option.py +++ b/tiramisu/option.py @@ -367,7 +367,8 @@ class Option(BaseOption): #if context, calculate value, otherwise get default value if context is not None: opt_value = context._getattr( - descr.impl_get_path_by_opt(opt), validate=False) + descr.impl_get_path_by_opt(opt), validate=False, + force_permissive=True) else: opt_value = opt.impl_getdefault() @@ -873,7 +874,7 @@ class PortOption(Option): if not self._min_value <= int(val) <= self._max_value: raise ValueError(_('invalid port, must be an between {0} ' 'and {1}').format(self._min_value, - self._max_value)) + self._max_value)) except ValueError: raise ValueError(_('invalid port')) From e7531e1fda5340b61b6766aaae900d588d05e25a Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Thu, 6 Feb 2014 22:17:20 +0100 Subject: [PATCH 2/2] more tests --- test/test_config_api.py | 32 ++++++++++++++++- test/test_config_domain.py | 12 +++++-- test/test_option_consistency.py | 28 +++++++++++++++ test/test_state.py | 8 ++++- tiramisu/option.py | 61 +++++++++------------------------ 5 files changed, 93 insertions(+), 48 deletions(-) diff --git a/test/test_config_api.py b/test/test_config_api.py index f5bc2c1..4be9e80 100644 --- a/test/test_config_api.py +++ b/test/test_config_api.py @@ -5,7 +5,9 @@ from py.test import raises from tiramisu.config import Config from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \ BoolOption, FilenameOption, UnicodeOption, SymLinkOption, IPOption, \ - PortOption, OptionDescription + PortOption, NetworkOption, NetmaskOption, BroadcastOption, \ + DomainnameOption, OptionDescription +from tiramisu.error import PropertiesOptionError def make_description(): @@ -212,6 +214,22 @@ def test_iter_all_prop(): assert list(config.iter_all()) == [('string2', 'string2')] +def test_impl_getpaths(): + s = StrOption("string", "", default="string", properties=('disabled',)) + s2 = StrOption("string2", "", default="string2") + s3 = StrOption("string3", "", default="string3") + s4 = StrOption("string4", "", default="string4", properties=('hidden',)) + od = OptionDescription('od', '', [s3, s4]) + descr = OptionDescription("options", "", [s, s2, od]) + config = Config(descr) + assert ['string', 'string2', 'od.string3', 'od.string4'] == config.cfgimpl_get_description().impl_getpaths() + assert ['string', 'string2', 'od', 'od.string3', 'od.string4'] == config.cfgimpl_get_description().impl_getpaths(include_groups=True) + config.read_write() + raises(PropertiesOptionError, "config.od.string4") + assert ['string', 'string2', 'od.string3', 'od.string4'] == config.cfgimpl_get_description().impl_getpaths() + assert ['string', 'string2', 'od', 'od.string3', 'od.string4'] == config.cfgimpl_get_description().impl_getpaths(include_groups=True) + + def test_invalid_option(): raises(TypeError, "ChoiceOption('a', '', [1, 2])") raises(TypeError, "ChoiceOption('a', '', 1)") @@ -225,3 +243,15 @@ def test_invalid_option(): raises(ValueError, "PortOption('a', '', 'string')") raises(ValueError, "PortOption('a', '', '11:12:13', allow_range=True)") raises(ValueError, "PortOption('a', '', 11111111111111111111)") + raises(ValueError, "PortOption('a', '', allow_zero=True, allow_wellknown=False, allow_registred=True, allow_private=False)") + raises(ValueError, "PortOption('a', '', allow_zero=True, allow_wellknown=True, allow_registred=False, allow_private=True)") + raises(ValueError, "PortOption('a', '', allow_zero=True, allow_wellknown=False, allow_registred=False, allow_private=True)") + raises(ValueError, "PortOption('a', '', allow_zero=True, allow_wellknown=False, allow_registred=True, allow_private=True)") + raises(ValueError, "PortOption('a', '', allow_zero=False, allow_wellknown=False, allow_registred=False, allow_private=False)") + raises(ValueError, "NetworkOption('a', '', 'string')") + raises(ValueError, "NetmaskOption('a', '', 'string')") + raises(ValueError, "BroadcastOption('a', '', 'string')") + raises(ValueError, "DomainnameOption('a', '', 'string')") + raises(ValueError, "DomainnameOption('a', '', type_='string')") + raises(ValueError, "DomainnameOption('a', '', allow_ip='string')") + raises(ValueError, "DomainnameOption('a', '', allow_without_dot='string')") diff --git a/test/test_config_domain.py b/test/test_config_domain.py index f4579a6..8fcf1f1 100644 --- a/test/test_config_domain.py +++ b/test/test_config_domain.py @@ -7,9 +7,9 @@ from tiramisu.option import DomainnameOption, EmailOption, URLOption, OptionDesc def test_domainname(): d = DomainnameOption('d', '') - e = DomainnameOption('e', '', "toto.com") f = DomainnameOption('f', '', allow_without_dot=True) - od = OptionDescription('a', '', [d, f]) + g = DomainnameOption('g', '', allow_ip=True) + od = OptionDescription('a', '', [d, f, g]) c = Config(od) c.read_write() c.d = 'toto.com' @@ -24,6 +24,12 @@ def test_domainname(): # c.f = 'toto.com' c.f = 'toto' + raises(ValueError, "c.f = 'domainnametoolongthathavemorethanmaximumsizeforatruedomainnameanditsnoteasytogeneratesolongdomainnamewithoutrepeatdomainnametoolongthathavemorethanmaximumsizeforatruedomainnameanditsnoteasytogeneratesolongdomainnamewithoutrepeatbutimnotabletodoitnowiendityeah'") + raises(ValueError, "c.f = 'd'") + # + c.g = 'toto.com' + c.g = '192.168.1.0' + c.g = '192.168.1.29' def test_domainname_netbios(): @@ -56,6 +62,7 @@ def test_email(): c.e = 'root@foo.com' raises(ValueError, "c.e = 'root'") raises(ValueError, "c.e = 'root@domain'") + raises(ValueError, "c.e = 'root[]@domain'") def test_url(): @@ -76,3 +83,4 @@ def test_url(): c.u = 'https://foo.com:8443' c.u = 'https://foo.com:8443/' c.u = 'https://foo.com:8443/index.html' + raises(ValueError, "c.u = 'https://foo.com:84438989'") diff --git a/test/test_option_consistency.py b/test/test_option_consistency.py index a7ff41c..1beb4bb 100644 --- a/test/test_option_consistency.py +++ b/test/test_option_consistency.py @@ -169,6 +169,18 @@ def test_consistency_network_netmask(): raises(ValueError, "c.a = '192.168.1.1'") +def test_consistency_ip_netmask_network_error(): + a = IPOption('a', '') + b = NetworkOption('b', '') + c = NetmaskOption('c', '') + od = OptionDescription('od', '', [a, b, c]) + c.impl_add_consistency('ip_netmask', a, b) + c = Config(od) + c.a = '192.168.1.1' + c.b = '192.168.1.0' + raises(ConfigError, "c.c = '255.255.255.0'") + + def test_consistency_ip_netmask_error_multi(): a = IPOption('a', '', multi=True) b = NetmaskOption('b', '') @@ -217,6 +229,8 @@ def test_consistency_ip_netmask_multi_master(): c.b = ['255.255.255.255'] c.b = ['255.255.255.0'] raises(ValueError, "c.a = ['192.168.1.0']") + c.a = ['192.168.1.128'] + raises(ValueError, "c.b = ['255.255.255.128']") c.a = ['192.168.1.2', '192.168.1.3'] @@ -260,6 +274,20 @@ def test_consistency_broadcast(): c.c[1] = '192.168.2.255' +def test_consistency_broadcast_error(): + a = NetworkOption('a', '', multi=True) + b = NetmaskOption('b', '', multi=True) + c = BroadcastOption('c', '', multi=True) + od = OptionDescription('a', '', [a, b, c]) + od.impl_set_group_type(groups.master) + b.impl_add_consistency('network_netmask', a) + c.impl_add_consistency('broadcast', a) + c = Config(od) + c.a = ['192.168.1.0'] + c.b = ['255.255.255.0'] + raises(ConfigError, "c.c = ['192.168.1.255']") + + def test_consistency_broadcast_default(): a = NetworkOption('a', '', '192.168.1.0') b = NetmaskOption('b', '', '255.255.255.128') diff --git a/test/test_state.py b/test/test_state.py index fd547ef..03be06e 100644 --- a/test/test_state.py +++ b/test/test_state.py @@ -1,3 +1,5 @@ +import autopath + from tiramisu.option import BoolOption, UnicodeOption, SymLinkOption, \ IntOption, OptionDescription from tiramisu.config import Config, GroupConfig, MetaConfig @@ -133,7 +135,6 @@ def _diff_conf(cfg1, cfg2): def test_diff_opt(): b = BoolOption('b', '') u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}]) - #u.impl_add_consistency('not_equal', b) s = SymLinkOption('s', u) o = OptionDescription('o', '', [b, u, s]) o1 = OptionDescription('o1', '', [o]) @@ -147,6 +148,11 @@ def test_diff_opt(): _diff_opt(o1.o.s, q.o.s) +def test_only_optiondescription(): + b = BoolOption('b', '') + raises(SystemError, "a = dumps(b)") + + def test_diff_opt_cache(): b = BoolOption('b', '') u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}]) diff --git a/tiramisu/option.py b/tiramisu/option.py index aafd43b..af7a67a 100644 --- a/tiramisu/option.py +++ b/tiramisu/option.py @@ -354,9 +354,6 @@ class Option(BaseOption): """ if context is not None: descr = context.cfgimpl_get_description() - #option is also in all_cons_opts - if option not in all_cons_opts: - raise ConfigError(_('option not in all_cons_opts')) all_cons_vals = [] for opt in all_cons_opts: @@ -587,31 +584,15 @@ class Option(BaseOption): consistencies = self._state_consistencies else: consistencies = self._consistencies - if isinstance(consistencies, list): - new_value = [] - for consistency in consistencies: - values = [] - for obj in consistency[1]: - if load: - values.append(descr.impl_get_opt_by_path(obj)) - else: - values.append(descr.impl_get_path_by_opt(obj)) - new_value.append((consistency[0], tuple(values))) - - else: - new_value = {} - for key, _consistencies in consistencies.items(): - new_value[key] = [] - for key_cons, _cons in _consistencies: - _list_cons = [] - for _con in _cons: - if load: - _list_cons.append( - descr.impl_get_opt_by_path(_con)) - else: - _list_cons.append( - descr.impl_get_path_by_opt(_con)) - new_value[key].append((key_cons, tuple(_list_cons))) + new_value = [] + for consistency in consistencies: + values = [] + for obj in consistency[1]: + if load: + values.append(descr.impl_get_opt_by_path(obj)) + else: + values.append(descr.impl_get_path_by_opt(obj)) + new_value.append((consistency[0], tuple(values))) if load: del(self._state_consistencies) self._consistencies = new_value @@ -932,19 +913,14 @@ class NetmaskOption(Option): IP('{0}/{1}'.format(val_ipnetwork, val_netmask), make_net=not make_net) except ValueError: - if not make_net: - msg = _("invalid network {0} ({1}) " - "with netmask {2}," - " this network is an IP") + pass else: if make_net: msg = _("invalid IP {0} ({1}) with netmask {2}," " this IP is a network") except ValueError: - if make_net: - msg = _('invalid IP {0} ({1}) with netmask {2}') - else: + if not make_net: msg = _('invalid network {0} ({1}) with netmask {2}') if msg is not None: raise ValueError(msg.format(val_ipnetwork, opts[1]._name, @@ -1035,8 +1011,8 @@ class DomainnameOption(Option): if self._type == 'domainname' and not self._allow_without_dot and \ '.' not in value: raise ValueError(_("invalid domainname, must have dot")) - if len(value) > 255: - raise ValueError(_("invalid domainname's length (max 255)")) + if len(value) > 255: + raise ValueError(_("invalid domainname's length (max 255)")) if len(value) < 2: raise ValueError(_("invalid domainname's length (min 2)")) if not self._domain_re.search(value): @@ -1313,13 +1289,10 @@ class OptionDescription(BaseOption): if consistencies is not None: for func, all_cons_opts in consistencies: #all_cons_opts[0] is the option where func is set - ret = all_cons_opts[0]._launch_consistency(func, option, - value, - context, index, - all_cons_opts) - if ret is False: - return False - return True + all_cons_opts[0]._launch_consistency(func, option, + value, + context, index, + all_cons_opts) def _impl_getstate(self, descr=None): """enables us to export into a dict