# coding: utf-8 from autopath import do_autopath do_autopath() from copy import copy from tiramisu.setting import groups from tiramisu import setting setting.expires_time = 1 from tiramisu.option import IPOption, OptionDescription, BoolOption, IntOption, StrOption from tiramisu.config import Config from tiramisu.error import PropertiesOptionError, RequirementError from py.test import raises def test_requires(): a = BoolOption('activate_service', '', True) b = IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) od = OptionDescription('service', '', [a, b]) c = Config(od) c.read_write() c.ip_address_service c.activate_service = False props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] c.activate_service = True c.ip_address_service def test_requires_with_requires(): a = BoolOption('activate_service', '', True) b = IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) od = OptionDescription('service', '', [a, b]) c = Config(od) c.read_write() c.cfgimpl_get_settings()[b].append('test') c.ip_address_service c.activate_service = False props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] c.activate_service = True c.ip_address_service def test_requires_invalid(): a = BoolOption('activate_service', '', True) a raises(ValueError, "IPOption('ip_address_service', '', requires='string')") raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'unknown': True}])") raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False}])") raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'action': 'disabled'}])") raises(ValueError, "IPOption('ip_address_service', '', requires=[{'expected': False, 'action': 'disabled'}])") raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'inverse': 'string'}])") raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'transitive': 'string'}])") raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'same_action': 'string'}])") raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': 'string', 'expected': False, 'action': 'disabled'}])") raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': 'string', 'action': 'disabled'}])") def test_requires_same_action(): a = BoolOption('activate_service', '', True) b = BoolOption('activate_service_web', '', True, requires=[{'option': a, 'expected': False, 'action': 'new'}]) d = IPOption('ip_address_service_web', '', requires=[{'option': b, 'expected': False, 'action': 'disabled', 'inverse': False, 'transitive': True, 'same_action': False}]) od = OptionDescription('service', '', [a, b, d]) c = Config(od) c.read_write() c.cfgimpl_get_settings().append('new') c.activate_service c.activate_service_web c.ip_address_service_web c.activate_service = False # props = [] try: c.activate_service_web except PropertiesOptionError as err: props = err.proptype assert props == ['new'] # props = [] try: c.ip_address_service_web except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] def test_multiple_requires(): a = StrOption('activate_service', '') b = IPOption('ip_address_service', '', requires=[{'option': a, 'expected': 'yes', 'action': 'disabled'}, {'option': a, 'expected': 'ok', 'action': 'disabled'}]) od = OptionDescription('service', '', [a, b]) c = Config(od) c.read_write() c.ip_address_service c.activate_service = 'yes' props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] c.activate_service = 'ok' props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] c.activate_service = 'no' c.ip_address_service def test_multiple_requires_cumulative(): a = StrOption('activate_service', '') b = IPOption('ip_address_service', '', requires=[{'option': a, 'expected': 'yes', 'action': 'disabled'}, {'option': a, 'expected': 'yes', 'action': 'hidden'}]) od = OptionDescription('service', '', [a, b]) c = Config(od) c.read_write() c.ip_address_service c.activate_service = 'yes' props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert set(props) == set(['hidden', 'disabled']) c.activate_service = 'ok' c.ip_address_service c.activate_service = 'no' c.ip_address_service def test_multiple_requires_cumulative_inverse(): a = StrOption('activate_service', '') b = IPOption('ip_address_service', '', requires=[{'option': a, 'expected': 'yes', 'action': 'disabled', 'inverse': True}, {'option': a, 'expected': 'yes', 'action': 'hidden', 'inverse': True}]) od = OptionDescription('service', '', [a, b]) c = Config(od) c.read_write() props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert set(props) == set(['hidden', 'disabled']) c.activate_service = 'yes' c.ip_address_service c.activate_service = 'ok' props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert set(props) == set(['hidden', 'disabled']) c.activate_service = 'no' props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert set(props) == set(['hidden', 'disabled']) def test_multiple_requires_inverse(): a = StrOption('activate_service', '') b = IPOption('ip_address_service', '', requires=[{'option': a, 'expected': 'yes', 'action': 'disabled', 'inverse': True}, {'option': a, 'expected': 'ok', 'action': 'disabled', 'inverse': True}]) od = OptionDescription('service', '', [a, b]) c = Config(od) c.read_write() props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] c.activate_service = 'yes' c.ip_address_service c.activate_service = 'ok' c.ip_address_service c.activate_service = 'no' props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] def test_requires_transitive(): a = BoolOption('activate_service', '', True) b = BoolOption('activate_service_web', '', True, requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) d = IPOption('ip_address_service_web', '', requires=[{'option': b, 'expected': False, 'action': 'disabled'}]) od = OptionDescription('service', '', [a, b, d]) c = Config(od) c.read_write() c.activate_service c.activate_service_web c.ip_address_service_web c.activate_service = False # props = [] try: c.activate_service_web except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] # props = [] try: c.ip_address_service_web except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] def test_requires_transitive_owner(): a = BoolOption('activate_service', '', True) b = BoolOption('activate_service_web', '', True, requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) d = IPOption('ip_address_service_web', '', requires=[{'option': b, 'expected': False, 'action': 'disabled'}]) od = OptionDescription('service', '', [a, b, d]) c = Config(od) c.read_write() c.activate_service c.activate_service_web c.ip_address_service_web #no more default value c.ip_address_service_web = '1.1.1.1' c.activate_service = False props = [] try: c.ip_address_service_web except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] def test_requires_transitive_bis(): a = BoolOption('activate_service', '', True) abis = BoolOption('activate_service_bis', '', True) b = BoolOption('activate_service_web', '', True, requires=[{'option': a, 'expected': True, 'action': 'disabled', 'inverse': True}]) d = IPOption('ip_address_service_web', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}]) od = OptionDescription('service', '', [a, abis, b, d]) c = Config(od) c.read_write() # c.activate_service_web c.ip_address_service_web c.activate_service = False # props = [] try: c.activate_service_web except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] # props = [] try: c.ip_address_service_web except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] def test_requires_transitive_hidden_disabled(): a = BoolOption('activate_service', '', True) b = BoolOption('activate_service_web', '', True, requires=[{'option': a, 'expected': False, 'action': 'hidden'}]) d = IPOption('ip_address_service_web', '', requires=[{'option': b, 'expected': False, 'action': 'disabled'}]) od = OptionDescription('service', '', [a, b, d]) c = Config(od) c.read_write() c.activate_service c.activate_service_web c.ip_address_service_web c.activate_service = False # props = [] try: c.activate_service_web except PropertiesOptionError as err: props = err.proptype assert props == ['hidden'] raises(RequirementError, 'c.ip_address_service_web') def test_requires_not_transitive(): a = BoolOption('activate_service', '', True) b = BoolOption('activate_service_web', '', True, requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) d = IPOption('ip_address_service_web', '', requires=[{'option': b, 'expected': False, 'action': 'disabled', 'transitive': False}]) od = OptionDescription('service', '', [a, b, d]) c = Config(od) c.read_write() c.activate_service c.activate_service_web c.ip_address_service_web c.activate_service = False # props = [] try: c.activate_service_web except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] # c.ip_address_service_web def test_requires_not_transitive_not_same_action(): a = BoolOption('activate_service', '', True) b = BoolOption('activate_service_web', '', True, requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) d = IPOption('ip_address_service_web', '', requires=[{'option': b, 'expected': False, 'action': 'hidden', 'transitive': False}]) od = OptionDescription('service', '', [a, b, d]) c = Config(od) c.read_write() c.activate_service c.activate_service_web c.ip_address_service_web c.activate_service = False # props = [] try: c.activate_service_web except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] # raises(RequirementError, "c.ip_address_service_web") def test_requires_None(): a = BoolOption('activate_service', '') b = IPOption('ip_address_service', '', requires=[{'option': a, 'expected': None, 'action': 'disabled'}]) od = OptionDescription('service', '', [a, b]) c = Config(od) c.read_write() props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] c.activate_service = False c.ip_address_service def test_requires_multi_disabled(): a = BoolOption('activate_service', '') b = IntOption('num_service', '') c = IPOption('ip_address_service', '', requires=[{'option': a, 'expected': True, 'action': 'disabled'}, {'option': b, 'expected': 1, 'action': 'disabled'}]) od = OptionDescription('service', '', [a, b, c]) c = Config(od) c.read_write() c.ip_address_service c.activate_service = True props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] c.activate_service = False c.ip_address_service c.num_service = 1 props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] c.activate_service = True props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] def test_requires_multi_disabled_new_format(): a = BoolOption('activate_service', '') b = IntOption('num_service', '') c = IPOption('ip_address_service', '', requires=[{'expected': [{'option': a, 'value': True}, {'option': b, 'value': 1}], 'action': 'disabled'}]) od = OptionDescription('service', '', [a, b, c]) c = Config(od) c.read_write() c.ip_address_service c.activate_service = True props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] c.activate_service = False c.ip_address_service c.num_service = 1 props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] c.activate_service = True props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] def test_requires_multi_disabled_new_format_and(): a = BoolOption('activate_service', '') b = IntOption('num_service', '') c = IPOption('ip_address_service', '', requires=[{'expected': [{'option': a, 'value': True}, {'option': b, 'value': 1}], 'action': 'disabled', 'operator': 'and'}]) od = OptionDescription('service', '', [a, b, c]) c = Config(od) c.read_write() c.ip_address_service c.activate_service = True props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == [] c.activate_service = False c.ip_address_service c.num_service = 1 props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == [] c.activate_service = True props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] def test_requires_multi_disabled_new_format_and_2(): a = BoolOption('activate_service', '') b = IntOption('num_service', '') c = IPOption('ip_address_service', '', requires=[{'expected': [{'option': a, 'value': True}, {'option': b, 'value': 1}], 'action': 'disabled', 'operator': 'and'}, {'expected': [{'option': a, 'value': False}, {'option': b, 'value': 1}], 'action': 'expert'}]) od = OptionDescription('service', '', [a, b, c]) c = Config(od) c.cfgimpl_get_settings().append('expert') c.read_write() c.ip_address_service c.activate_service = True props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == [] c.activate_service = False c.num_service = 1 props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['expert'] c.activate_service = True props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled', 'expert'] def test_requires_multi_disabled_inverse(): a = BoolOption('activate_service', '') b = IntOption('num_service', '') c = IPOption('ip_address_service', '', requires=[{'option': a, 'expected': True, 'action': 'disabled', 'inverse': True}, {'option': b, 'expected': 1, 'action': 'disabled', 'inverse': True}]) od = OptionDescription('service', '', [a, b, c]) c = Config(od) c.read_write() props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] c.activate_service = True props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] c.activate_service = False props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] c.num_service = 1 props = [] try: c.ip_address_service except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] c.activate_service = True c.ip_address_service def test_requires_multi_disabled_2(): a = BoolOption('a', '') b = BoolOption('b', '') c = BoolOption('c', '') d = BoolOption('d', '') e = BoolOption('e', '') f = BoolOption('f', '') g = BoolOption('g', '') h = BoolOption('h', '') i = BoolOption('i', '') j = BoolOption('j', '') k = BoolOption('k', '') l = BoolOption('l', '') m = BoolOption('m', '') list_bools = [a, b, c, d, e, f, g, h, i, j, k, l, m] requires = [] for boo in list_bools: requires.append({'option': boo, 'expected': True, 'action': 'disabled'}) z = IPOption('z', '', requires=requires) y = copy(list_bools) y.append(z) od = OptionDescription('service', '', y) cfg = Config(od) cfg.read_write() cfg.z for boo in list_bools: setattr(cfg, boo._name, True) props = [] try: cfg.z except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] for boo in list_bools: setattr(cfg, boo._name, False) if boo == m: cfg.z else: props = [] try: cfg.z except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] def test_requires_multi_disabled_inverse_2(): a = BoolOption('a', '') b = BoolOption('b', '') c = BoolOption('c', '') d = BoolOption('d', '') e = BoolOption('e', '') f = BoolOption('f', '') g = BoolOption('g', '') h = BoolOption('h', '') i = BoolOption('i', '') j = BoolOption('j', '') k = BoolOption('k', '') l = BoolOption('l', '') m = BoolOption('m', '') list_bools = [a, b, c, d, e, f, g, h, i, j, k, l, m] requires = [] for boo in list_bools: requires.append({'option': boo, 'expected': True, 'action': 'disabled', 'inverse': True}) z = IPOption('z', '', requires=requires) y = copy(list_bools) y.append(z) od = OptionDescription('service', '', y) cfg = Config(od) cfg.read_write() props = [] try: cfg.z except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] for boo in list_bools: setattr(cfg, boo._name, True) if boo == m: cfg.z else: props = [] try: cfg.z except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] for boo in list_bools: setattr(cfg, boo._name, False) props = [] try: cfg.z except PropertiesOptionError as err: props = err.proptype assert props == ['disabled'] def test_requires_requirement_append(): a = BoolOption('activate_service', '', True) b = IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) od = OptionDescription('service', '', [a, b]) c = Config(od) c.read_write() str(c.cfgimpl_get_settings()) str(c.cfgimpl_get_settings()[b]) raises(ValueError, 'c.cfgimpl_get_settings()[b].append("disabled")') c.activate_service = False # disabled is now set, test to remove disabled before store in storage c.cfgimpl_get_settings()[b].append("test") def test_requires_different_inverse(): a = BoolOption('activate_service', '', True) b = IPOption('ip_address_service', '', requires=[ {'option': a, 'expected': True, 'action': 'disabled', 'inverse': True}, {'option': a, 'expected': True, 'action': 'disabled', 'inverse': False}]) od = OptionDescription('service', '', [a, b]) c = Config(od) c.read_write() raises(PropertiesOptionError, 'c.ip_address_service') c.activate_service = False raises(PropertiesOptionError, 'c.ip_address_service') def test_requires_different_inverse_unicode(): a = BoolOption('activate_service', '', True) d = StrOption('activate_other_service', '', 'val2') b = IPOption('ip_address_service', '', requires=[ {'option': a, 'expected': True, 'action': 'disabled', 'inverse': True}, {'option': d, 'expected': 'val1', 'action': 'disabled', 'inverse': False}]) od = OptionDescription('service', '', [a, d, b]) c = Config(od) c.read_write() assert c.ip_address_service == None c.activate_service = False raises(PropertiesOptionError, 'c.ip_address_service') c.activate_service = True assert c.ip_address_service == None c.activate_other_service = 'val1' raises(PropertiesOptionError, 'c.ip_address_service') c.activate_service = False raises(PropertiesOptionError, 'c.ip_address_service') def test_requires_recursive_path(): a = BoolOption('activate_service', '', True) b = IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) od1 = OptionDescription('service', '', [a, b], requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) od = OptionDescription('base', '', [od1]) c = Config(od) c.read_write() raises(RequirementError, 'c.service.a') def test_get_properties_with_None_path(): a = BoolOption('activate_service', '', True) b = IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) od1 = OptionDescription('service', '', [a, b], requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) od = OptionDescription('base', '', [od1]) c = Config(od) c.read_write() raises(ValueError, "c.cfgimpl_get_settings()._getproperties(a)") def test_set_item(): a = BoolOption('activate_service', '', True) b = IPOption('ip_address_service', '') od1 = OptionDescription('service', '', [a, b]) od = OptionDescription('base', '', [od1]) c = Config(od) c.read_write() raises(ValueError, 'c.cfgimpl_get_settings()[a] = ("test",)') def test_optiondescription_requires(): a = BoolOption('activate_service', '', True) b = BoolOption('ip_address_service', '', multi=True) a, b OptionDescription('service', '', [b], requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) def test_optiondescription_requires_multi(): a = BoolOption('activate_service', '', True) b = IPOption('ip_address_service', '', multi=True) a, b raises(ValueError, "OptionDescription('service', '', [a], requires=[{'option': b, 'expected': False, 'action': 'disabled'}])") def test_properties_conflict(): a = BoolOption('activate_service', '', True) a raises(ValueError, "IPOption('ip_address_service', '', properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])") raises(ValueError, "od1 = OptionDescription('service', '', [a], properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])") def test_master_slave_requires(): 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, requires=[{'option': ip_admin_eth0, 'expected': '192.168.1.1', 'action': 'disabled'}]) interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) interface1.impl_set_group_type(groups.master) maconfig = OptionDescription('toto', '', [interface1]) cfg = Config(maconfig) cfg.read_write() assert cfg.ip_admin_eth0.netmask_admin_eth0 == [] assert cfg.ip_admin_eth0.ip_admin_eth0 == [] cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.2') assert cfg.ip_admin_eth0.netmask_admin_eth0 == [None] assert cfg.ip_admin_eth0.ip_admin_eth0 == ['192.168.1.2'] cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.1') assert cfg.ip_admin_eth0.netmask_admin_eth0[0] is None raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0[1]") cfg.ip_admin_eth0.ip_admin_eth0[1] = '192.168.1.2' assert cfg.ip_admin_eth0.netmask_admin_eth0[1] is None cfg.ip_admin_eth0.netmask_admin_eth0[1] = '255.255.255.255' assert cfg.ip_admin_eth0.netmask_admin_eth0[1] == '255.255.255.255' cfg.ip_admin_eth0.ip_admin_eth0[1] = '192.168.1.1' raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0[1]") def test_master_slave_requires_no_master(): activate = BoolOption('activate', "Activer l'accès au réseau", True) 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, requires=[{'option': activate, 'expected': False, 'action': 'disabled'}]) interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) interface1.impl_set_group_type(groups.master) maconfig = OptionDescription('toto', '', [activate, interface1]) cfg = Config(maconfig) cfg.read_write() assert cfg.ip_admin_eth0.netmask_admin_eth0 == [] assert cfg.ip_admin_eth0.ip_admin_eth0 == [] cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.2') assert cfg.ip_admin_eth0.netmask_admin_eth0 == [None] assert cfg.ip_admin_eth0.netmask_admin_eth0[0] is None assert cfg.ip_admin_eth0.ip_admin_eth0 == ['192.168.1.2'] cfg.activate = False cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.1') assert cfg.ip_admin_eth0.ip_admin_eth0 == ['192.168.1.2', '192.168.1.1'] raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0") raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0[0]") raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0[1]") cfg.activate = True assert cfg.ip_admin_eth0.netmask_admin_eth0 == [None, None] cfg.ip_admin_eth0.netmask_admin_eth0 = [None, '255.255.255.255'] assert cfg.ip_admin_eth0.netmask_admin_eth0[1] == '255.255.255.255' cfg.activate = False raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0") raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0[0]") raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0[1]")