from .autopath import do_autopath do_autopath() from .config import config_type, get_config import warnings from py.test import raises from tiramisu import BoolOption, StrOption, OptionDescription, Leadership, Config, Params, ParamValue, ParamOption, ParamContext from tiramisu.setting import groups from tiramisu.error import ValueWarning, ConfigError from tiramisu.i18n import _ from tiramisu.storage import list_sessions def teardown_function(function): assert list_sessions() == [], 'session list is not empty when leaving "{}"'.format(function.__name__) msg_err = _('attention, "{0}" could be an invalid {1} for "{2}"') def return_true(value, param=None): if value == 'val' and param in [None, 'yes']: return True raise ValueError('test error') def return_false(value, param=None): if value == 'val' and param in [None, 'yes']: raise ValueError('test error return_false') def return_val(value, param=None): return 'val' def return_if_val(value): if value != 'val': raise ValueError('test error') def is_context(value, context): cfg = Config(context) cfg.property.pop('validator') if not isinstance(cfg, Config): raise ValueError('not context') def value_values(value, values): if not (value == 'val' and values == ['val'] or value == 'val1' and values == ['val'] or value == 'val2' and values == ['val'] or value == 'val1' and values == ['val1'] or value == 'val1' and values == ['val1', 'val2'] or value == 'val2' and values == ['val1', 'val2'] or value == 'val1' and values == ['val1', None]): raise ValueError('error') def value_values_index(value, values, index): value_values(value, values) if not (index == 0 or (value == 'val2' and index == 1)): raise ValueError('error 2') def value_values_auto(value, values, auto=False): if auto != False: raise ValueError('auto should be False') if not (value == 'val' and values == ['val'] or value == 'val1' and values == ['val1'] or value == 'val2' and values == ['val1', 'val2'] or value == 'val1' and values == ['val1', None]): raise ValueError('error') def value_values_auto2(value, values, auto=False): if auto != False: raise ValueError('auto should be False') if not (value == 'val1' and values == 'val' or value == 'val2' and values == 'val'): raise ValueError('error') def value_values_index2(value, values, index, auto=False): if auto != False: raise ValueError('auto should be False') if not (value == 'val1' and values == ['val1'] and index == 'val' or value == 'val1' and values == ['val1', None] and index == 'val' or value == 'val2' and values == ['val1', 'val2'] and index == 'val'): raise ValueError('error') def value_empty(value, empty, values): if not value == 'val' or empty is not False and not values == ['val']: raise ValueError('error') def valid_from_config(value, config): cfg = Config(config) if cfg.option('opt1').value.get() != u'yes': raise ValueError("c'est une erreur") def test_validator(config_type): opt1 = StrOption('opt1', '', validator=return_true, default='val') raises(ValueError, "StrOption('opt2', '', validator=return_false, default='val')") opt2 = StrOption('opt2', '', validator=return_false) root = OptionDescription('root', '', [opt1, opt2]) cfg_ori = Config(root) cfg = get_config(cfg_ori, config_type) assert cfg.option('opt1').value.get() == 'val' raises(ValueError, "cfg.option('opt2').value.set('val')") try: cfg.option('opt2').value.set('val') except ValueError as err: msg = _('"{0}" is an invalid {1} for "{2}"').format('val', _('string'), 'opt2') + ', ' + _('test error return_false') assert str(err) == msg if config_type == 'tiramisu-api': msg = _('"{0}" is an invalid {1} for "{2}"').format('val', 'string', 'opt2') + ', ' + _('test error return_false') if config_type == 'tiramisu-api': cfg.send() cfg_ori.property.add('demoting_error_warning') cfg = get_config(cfg_ori, config_type) warnings.simplefilter("always", ValueWarning) with warnings.catch_warnings(record=True) as w: cfg.option('opt2').value.set('val') assert len(w) == 1 assert str(w[0].message) == msg def test_validator_params(config_type): opt1 = StrOption('opt1', '', validator=return_true, validator_params=Params(ParamValue('yes')), default='val') raises(ValueError, "StrOption('opt2', '', validator=return_false, validator_params=Params(ParamValue('yes')), default='val')") opt2 = StrOption('opt2', '', validator=return_false, validator_params=Params(ParamValue('yes'))) root = OptionDescription('root', '', [opt1, opt2]) cfg_ori = Config(root) cfg = get_config(cfg_ori, config_type) assert cfg.option('opt1').value.get() == 'val' raises(ValueError, "cfg.option('opt2').value.set('val')") if config_type == 'tiramisu-api': cfg.send() cfg_ori.property.add('demoting_error_warning') cfg = get_config(cfg_ori, config_type) warnings.simplefilter("always", ValueWarning) with warnings.catch_warnings(record=True) as w: cfg.option('opt2').value.set('val') assert len(w) == 1 def test_validator_params_value_values(config_type): opt1 = StrOption('opt1', '', validator=value_values, default=['val'], multi=True) root = OptionDescription('root', '', [opt1]) cfg = Config(root) cfg = get_config(cfg, config_type) assert cfg.option('opt1').value.get() == ['val'] cfg.option('opt1').value.set(['val1', 'val2']) def test_validator_params_value_values_index(config_type): opt1 = StrOption('opt1', '', validator=value_values_index, default=['val'], multi=True) root = OptionDescription('root', '', [opt1]) cfg = Config(root) cfg = get_config(cfg, config_type) assert cfg.option('opt1').value.get() == ['val'] cfg.option('opt1').value.set(['val1', 'val2']) def test_validator_params_value_values_leader(config_type): ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, validator=value_values) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True) interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) root = OptionDescription('root', '', [interface1]) cfg = Config(root) cfg = get_config(cfg, config_type) assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val2']) def test_validator_params_value_values_index_leader(config_type): ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, validator=value_values_index) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True) interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) root = OptionDescription('root', '', [interface1]) cfg = Config(root) cfg = get_config(cfg, config_type) assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val2']) def test_validator_params_value_values_follower(config_type): ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True, validator=value_values) interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) root = OptionDescription('root', '', [interface1]) cfg = Config(root) cfg = get_config(cfg, config_type) assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val']) cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('val1') cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val', 'val']) cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('val2') def test_validator_params_value_values_index_follower(config_type): ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True, validator=value_values_index) interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) root = OptionDescription('root', '', [interface1]) cfg = Config(root) cfg = get_config(cfg, config_type) assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val']) cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('val1') cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val', 'val']) cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('val2') def test_validator_params_value_values_notmulti(): raises(ConfigError, "opt1 = StrOption('opt1', '', validator=value_values, default='val')") def test_validator_params_value_values_kwargs_empty(config_type): v = BoolOption('v', '', default=False) ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, default=["ip"]) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True, validator=value_empty, validator_params=Params(ParamOption(v))) interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) root = OptionDescription('root', '', [v, interface1]) cfg = Config(root) cfg = get_config(cfg, config_type) assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['ip'] cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['ip', 'val']) #cfg.ip_admin_eth0.ip_admin_eth0.append('val') #cfg.ip_admin_eth0.netmask_admin_eth0[1] = 'val2' def test_validator_params_value_values_kwargs(config_type): v = BoolOption('v', '', default=False) ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, default=["ip"]) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True, validator=value_values_auto, validator_params=Params(kwargs={'auto': ParamOption(v)})) interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) root = OptionDescription('root', '', [v, interface1]) cfg = Config(root) cfg = get_config(cfg, config_type) assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['ip'] cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('val1') cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['ip', 'val']) cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('val2') def test_validator_params_value_values_kwargs_values(config_type): ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True, validator=value_values_auto2, validator_params=Params(kwargs={'values': ParamOption(ip_admin_eth0)})) interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) root = OptionDescription('root', '', [interface1]) cfg = Config(root) cfg = get_config(cfg, config_type) assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val']) cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('val1') cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val', 'val']) cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('val2') def test_validator_params_value_values_kwargs2(config_type): ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True, validator=value_values_index2, validator_params=Params(ParamValue(['val1']), {'index': ParamOption(ip_admin_eth0)})) interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) root = OptionDescription('root', '', [interface1]) cfg = Config(root) cfg = get_config(cfg, config_type) assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val']) cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('val1') cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val', 'val']) def test_validator_params_value_values_kwargs_index(config_type): ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True, validator=value_values_index2, validator_params=Params(kwargs={'index': ParamOption(ip_admin_eth0)})) interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) root = OptionDescription('root', '', [interface1]) cfg = Config(root) cfg = get_config(cfg, config_type) assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val']) cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('val1') cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val', 'val']) cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('val2') def test_validator_params_context(): opt1 = StrOption('opt1', '', validator=is_context, validator_params=Params(ParamContext()), default='val') root = OptionDescription('root', '', [opt1]) cfg = Config(root) # cfg = get_config(cfg, config_type) # ParamContext not supported assert 'validator' in cfg.property.get() assert cfg.option('opt1').value.get() == 'val' assert 'validator' in cfg.property.get() def test_validator_params_context_value(): opt1 = StrOption('opt1', '', 'yes') opt2 = StrOption('opt2', '', validator=valid_from_config, validator_params=Params(ParamContext()), default='val') root = OptionDescription('root', '', [opt1, opt2]) cfg = Config(root) # cfg = get_config(cfg_ori, config_type) # ParamContext not supported assert cfg.option('opt1').value.get() == 'yes' assert cfg.option('opt2').value.get() == 'val' cfg.option('opt1').value.set('no') raises(ValueError, "assert cfg.option('opt2').value.get()") if config_type == 'tiramisu-api': cfg.send() cfg.property.add('demoting_error_warning') warnings.simplefilter("always", ValueWarning) with warnings.catch_warnings(record=True) as w: cfg.option('opt2').value.get() assert len(w) == 1 def test_validator_params_key(config_type): opt1 = StrOption('opt1', '', validator=return_true, validator_params=Params(kwargs={'param': ParamValue('yes')}), default='val') raises(ConfigError, "StrOption('opt2', '', validator=return_true, validator_params=Params(kwargs={'param_unknown': ParamValue('yes')}), default='val')") root = OptionDescription('root', '', [opt1]) cfg = Config(root) cfg = get_config(cfg, config_type) assert cfg.option('opt1').value.get() == 'val' def test_validator_params_option(config_type): opt0 = StrOption('opt0', '', default='yes') opt1 = StrOption('opt1', '', validator=return_true, validator_params=Params(ParamOption(opt0)), default='val') r = OptionDescription('root', '', [opt0, opt1]) cfg_ori = Config(r) cfg = get_config(cfg_ori, config_type) assert cfg.option('opt1').value.get() == 'val' cfg.option('opt0').value.set('val') raises(ValueError, "cfg.option('opt1').value.get()") if config_type == 'tiramisu-api': cfg.send() cfg_ori.property.add('demoting_error_warning') cfg = get_config(cfg_ori, config_type) warnings.simplefilter("always", ValueWarning) with warnings.catch_warnings(record=True) as w: cfg.option('opt1').value.get() assert len(w) == 1 def test_validator_multi(config_type): opt1 = StrOption('opt1', '', validator=return_if_val, multi=True) root = OptionDescription('root', '', [opt1]) cfg_ori = Config(root) cfg = get_config(cfg_ori, config_type) assert cfg.option('opt1').value.get() == [] cfg.option('opt1').value.set(['val']) assert cfg.option('opt1').value.get() == ['val'] raises(ValueError, "cfg.option('opt1').value.set(['val', 'val1'])") if config_type == 'tiramisu-api': cfg.send() cfg_ori.property.add('demoting_error_warning') cfg = get_config(cfg_ori, config_type) warnings.simplefilter("always", ValueWarning) with warnings.catch_warnings(record=True) as w: cfg.option('opt1').value.set(['val', 'val1']) assert len(w) == 1 def test_validator_warning(config_type): opt1 = StrOption('opt1', '', validator=return_true, default='val', warnings_only=True) opt2 = StrOption('opt2', '', validator=return_false, warnings_only=True) opt3 = StrOption('opt3', '', validator=return_if_val, multi=True, warnings_only=True) root = OptionDescription('root', '', [opt1, opt2, opt3]) cfg = Config(root) cfg = get_config(cfg, config_type) assert cfg.option('opt1').value.get() == 'val' warnings.simplefilter("always", ValueWarning) with warnings.catch_warnings(record=True) as w: cfg.option('opt1').value.set('val') assert w == [] # with warnings.catch_warnings(record=True) as w: cfg.option('opt2').value.set('val') assert len(w) == 1 if config_type != 'tiramisu-api': assert w[0].message.opt() == opt2 assert str(w[0].message) == msg_err.format('val', opt2._display_name, 'opt2') + ', ' + 'test error return_false' # with warnings.catch_warnings(record=True) as w: cfg.option('opt3').value.set(['val']) assert w == [] # with warnings.catch_warnings(record=True) as w: cfg.option('opt3').value.set(['val', 'val1']) assert len(w) == 1 if config_type != 'tiramisu-api': assert w[0].message.opt() == opt3 assert str(w[0].message) == msg_err.format('val1', opt3._display_name, 'opt3') + ', ' + 'test error' # with warnings.catch_warnings(record=True) as w: raises(ValueError, "cfg.option('opt2').value.set(1)") assert len(w) == 0 # with warnings.catch_warnings(record=True) as w: cfg.option('opt2').value.set('val') cfg.option('opt3').value.set(['val', 'val1', 'val']) assert len(w) == 2 if config_type != 'tiramisu-api': assert w[0].message.opt() == opt2 assert str(w[0].message) == msg_err.format('val', opt2._display_name, 'opt2') + ', ' + 'test error return_false' assert w[1].message.opt() == opt3 assert str(w[1].message) == msg_err.format('val1', opt3._display_name, 'opt3') + ', ' + 'test error' def test_validator_warning_disabled(config_type): opt1 = StrOption('opt1', '', validator=return_true, default='val', warnings_only=True) opt2 = StrOption('opt2', '', validator=return_false, warnings_only=True) opt3 = StrOption('opt3', '', validator=return_if_val, multi=True, warnings_only=True) root = OptionDescription('root', '', [opt1, opt2, opt3]) cfg_ori = Config(root) cfg_ori.property.pop('warnings') cfg = get_config(cfg_ori, config_type) assert cfg.option('opt1').value.get() == 'val' warnings.simplefilter("always", ValueWarning) with warnings.catch_warnings(record=True) as w: cfg.option('opt1').value.set('val') assert w == [] # with warnings.catch_warnings(record=True) as w: cfg.option('opt2').value.set('val') assert w == [] # with warnings.catch_warnings(record=True) as w: cfg.option('opt3').value.set(['val']) assert w == [] # with warnings.catch_warnings(record=True) as w: cfg.option('opt3').value.set(['val', 'val1']) assert w == [] raises(ValueError, "cfg.option('opt2').value.set(1)") # with warnings.catch_warnings(record=True) as w: cfg.option('opt2').value.set('val') cfg.option('opt3').value.set(['val', 'val1', 'val']) assert w == [] # if config_type == 'tiramisu-api': cfg.send() cfg_ori.property.add('demoting_error_warning') cfg = get_config(cfg_ori, config_type) if config_type != 'tiramisu-api': warnings.simplefilter("always", ValueWarning) with warnings.catch_warnings(record=True) as w: cfg.option('opt2').value.set(1) assert len(w) == 1 def test_validator_warning_leadership(config_type): display_name_ip = "ip reseau autorise" display_name_netmask = "masque du sous-reseau" ip_admin_eth0 = StrOption('ip_admin_eth0', display_name_ip, multi=True, validator=return_false, warnings_only=True) netmask_admin_eth0 = StrOption('netmask_admin_eth0', display_name_netmask, multi=True, validator=return_if_val, warnings_only=True) interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) assert interface1.impl_get_group_type() == groups.leadership root = OptionDescription('root', '', [interface1]) cfg = Config(root) cfg = get_config(cfg, config_type) warnings.simplefilter("always", ValueWarning) with warnings.catch_warnings(record=True) as w: cfg.option('ip_admin_eth0.ip_admin_eth0').value.set([None]) assert w == [] # with warnings.catch_warnings(record=True) as w: cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('val1') assert len(w) == 1 if config_type != 'tiramisu-api': assert w[0].message.opt() == netmask_admin_eth0 assert str(w[0].message) == msg_err.format('val1', netmask_admin_eth0._display_name, display_name_netmask) + ', test error' # with warnings.catch_warnings(record=True) as w: cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val']) if config_type != 'tiramisu-api': assert w[0].message.opt() == ip_admin_eth0 assert str(w[0].message) == msg_err.format('val', ip_admin_eth0._display_name, display_name_ip) + ', test error return_false' else: assert len(w) == 2 # with warnings.catch_warnings(record=True) as w: cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val', 'val1', 'val1']) if config_type != 'tiramisu-api': assert w[0].message.opt() == ip_admin_eth0 assert str(w[0].message) == msg_err.format('val', ip_admin_eth0._display_name, display_name_ip) + ', test error return_false' else: assert len(w) == 3 # with warnings.catch_warnings(record=True) as w: cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val', 'val1']) if config_type != 'tiramisu-api': assert w[0].message.opt() == ip_admin_eth0 assert str(w[0].message) == msg_err.format('val', ip_admin_eth0._display_name, display_name_ip) + ', test error return_false' else: assert len(w) == 3 # warnings.resetwarnings() with warnings.catch_warnings(record=True) as w: cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val1', 'val']) if config_type != 'tiramisu-api': assert w[0].message.opt() == ip_admin_eth0 assert str(w[0].message) == msg_err.format('val', ip_admin_eth0._display_name, display_name_ip) + ', test error return_false' else: assert len(w) == 3 def test_validator_follower_param(config_type): ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True, validator=return_true, validator_params=Params(kwargs={'param': ParamOption(ip_admin_eth0)})) interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) root = OptionDescription('root', '', [interface1]) cfg = Config(root) cfg = get_config(cfg, config_type) assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['yes']) cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('val') cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['yes', 'yes']) cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('val') def test_validator_dependencies(): ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise") netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", validator=return_true, validator_params=Params(kwargs={'param': ParamOption(ip_admin_eth0)})) opt2 = StrOption('opt2', '', validator=return_false) root = OptionDescription('root', '', [ip_admin_eth0, netmask_admin_eth0, opt2]) cfg = Config(root) assert cfg.option('ip_admin_eth0').option.has_dependency() is False assert cfg.option('netmask_admin_eth0').option.has_dependency() is True assert cfg.option('opt2').option.has_dependency() is False # assert cfg.option('ip_admin_eth0').option.has_dependency(False) is True assert cfg.option('netmask_admin_eth0').option.has_dependency(False) is False assert cfg.option('opt2').option.has_dependency(False) is False