From b5f785d62c2ea6b2cffe8d167ce29f13d61e56ee Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Wed, 13 Dec 2017 22:15:34 +0100 Subject: [PATCH] convert tests --- test/api/test_owner.py | 2 +- test/new_api/__init__.py | 0 test/new_api/autopath.py | 14 + test/new_api/test_cache.py | 790 +++++++++++ test/new_api/test_choice_option.py | 199 +++ test/new_api/test_config.py | 403 ++++++ test/new_api/test_config_api.py | 387 ++++++ test/new_api/test_config_domain.py | 178 +++ test/new_api/test_config_ip.py | 254 ++++ test/new_api/test_dyn_optiondescription.py | 1368 ++++++++++++++++++++ test/new_api/test_freeze.py | 221 ++++ test/new_api/test_mandatory.py | 575 ++++++++ tiramisu/api.py | 408 ++++-- tiramisu/autolib.py | 2 +- tiramisu/config.py | 66 +- tiramisu/error.py | 13 +- tiramisu/option/baseoption.py | 19 +- tiramisu/option/booloption.py | 8 +- tiramisu/option/broadcastoption.py | 30 +- tiramisu/option/choiceoption.py | 61 +- tiramisu/option/dateoption.py | 12 +- tiramisu/option/domainnameoption.py | 63 +- tiramisu/option/floatoption.py | 8 +- tiramisu/option/intoption.py | 8 +- tiramisu/option/ipoption.py | 69 +- tiramisu/option/masterslave.py | 2 +- tiramisu/option/netmaskoption.py | 58 +- tiramisu/option/networkoption.py | 22 +- tiramisu/option/option.py | 52 +- tiramisu/option/optiondescription.py | 37 +- tiramisu/option/passwordoption.py | 10 +- tiramisu/option/portoption.py | 58 +- tiramisu/option/stroption.py | 27 +- tiramisu/option/symlinkoption.py | 69 +- tiramisu/option/syndynoptiondescription.py | 19 +- tiramisu/option/urloption.py | 27 +- tiramisu/setting.py | 24 +- tiramisu/value.py | 237 ++-- 38 files changed, 5234 insertions(+), 566 deletions(-) create mode 100644 test/new_api/__init__.py create mode 100644 test/new_api/autopath.py create mode 100644 test/new_api/test_cache.py create mode 100644 test/new_api/test_choice_option.py create mode 100644 test/new_api/test_config.py create mode 100644 test/new_api/test_config_api.py create mode 100644 test/new_api/test_config_domain.py create mode 100644 test/new_api/test_config_ip.py create mode 100644 test/new_api/test_dyn_optiondescription.py create mode 100644 test/new_api/test_freeze.py create mode 100644 test/new_api/test_mandatory.py diff --git a/test/api/test_owner.py b/test/api/test_owner.py index e4d6425..84bb084 100644 --- a/test/api/test_owner.py +++ b/test/api/test_owner.py @@ -1408,7 +1408,7 @@ def check_all(cfg, paths, path, meta, multi, default, default_multi, require, co do('val2', 'val1') #FIXME devrait etre dans la config ca ... - api.read_write() + api.property.read_write() if req: name = 'extraoptrequire' if symlink: diff --git a/test/new_api/__init__.py b/test/new_api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/new_api/autopath.py b/test/new_api/autopath.py new file mode 100644 index 0000000..8820560 --- /dev/null +++ b/test/new_api/autopath.py @@ -0,0 +1,14 @@ +"""automatically sets the PYTHONPATH before running the unit tests + +This is supposed to be used in development mode (i.e. testing from a fresh +checkout) +""" + +from os.path import dirname, abspath, join, normpath +import sys + +def do_autopath(): + HERE = dirname(abspath(__file__)) + PATH = normpath(join(HERE, '..', 'tiramisu')) + if PATH not in sys.path: + sys.path.insert(1, PATH) diff --git a/test/new_api/test_cache.py b/test/new_api/test_cache.py new file mode 100644 index 0000000..6a9a8c0 --- /dev/null +++ b/test/new_api/test_cache.py @@ -0,0 +1,790 @@ +# coding: utf-8 +from .autopath import do_autopath +do_autopath() + +from tiramisu import setting, value +setting.expires_time = 1 +value.expires_time = 1 +from tiramisu.option import BoolOption, IPOption, IntOption, StrOption, OptionDescription, MasterSlaves +from tiramisu.config import Config +from tiramisu.error import ConfigError, PropertiesOptionError +from tiramisu.setting import groups +from tiramisu import getapi, undefined +from tiramisu.api import TIRAMISU_VERSION + + +from time import sleep, time +from py.test import raises + + +global incr +incr = 0 +def return_incr(): + global incr + incr += 1 + return incr + + +def return_value(val): + return val + + +def make_description(): + u1 = IntOption('u1', '', multi=True) + u2 = IntOption('u2', '') + u3 = IntOption('u3', '', multi=True) + return OptionDescription('od1', '', [u1, u2, u3]) + + +def test_cache_config(): + od1 = make_description() + assert od1.impl_already_build_caches() is False + c = Config(od1) + assert od1.impl_already_build_caches() is True + c + + +def test_cache(): + od1 = make_description() + c = Config(od1) + api = getapi(c) + values = c.cfgimpl_get_values() + settings = c.cfgimpl_get_settings() + api.option('u1').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + api.option('u2').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u2' in values._p_.get_cached() + assert 'u2' in settings._p_.get_cached() + + +#def test_get_cache(): +# # force a value in cache, try if reget corrupted value +# od1 = make_description() +# c = Config(od1) +# api = getapi(c) +# values = c.cfgimpl_get_values() +# settings = c.cfgimpl_get_settings() +# ntime = time() + 1 +# settings._p_.setcache('u1', set(['inject']), ntime, None) +# assert 'inject' in settings[od1.u1] +# values._p_.setcache('u1', 100, ntime, None) +# assert api.option('u1').value.get() == [100] + + +#def test_get_cache_no_expire(): +# # force a value in cache, try if reget corrupted value +# od1 = make_description() +# c = Config(od1) +# api = getapi(c) +# values = c.cfgimpl_get_values() +# settings = c.cfgimpl_get_settings() +# settings._p_.setcache('u1', set(['inject2']), None, None) +# assert 'inject2' in settings[od1.u1] +# values._p_.setcache('u1', 200, None, None) +# assert api.option('u1').value.get() == [200] + + +def test_cache_reset(): + od1 = make_description() + c = Config(od1) + api = getapi(c) + values = c.cfgimpl_get_values() + settings = c.cfgimpl_get_settings() + #when change a value + api.option('u1').value.get() + api.option('u2').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u2' in values._p_.get_cached() + assert 'u2' in settings._p_.get_cached() + assert 'u1' in values._p_.get_cached() + api.option('u2').value.set(1) + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u2' not in values._p_.get_cached() + assert 'u2' not in settings._p_.get_cached() + #when remove a value + api.option('u1').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + api.option('u2').value.reset() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u2' not in values._p_.get_cached() + assert 'u2' not in settings._p_.get_cached() + #when add/del property + api.option('u1').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + api.option('u2').property.add('test') + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u2' not in values._p_.get_cached() + assert 'u2' not in settings._p_.get_cached() + api.option('u1').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + api.option('u2').property.pop('test') + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u2' not in values._p_.get_cached() + assert 'u2' not in settings._p_.get_cached() + #when enable/disabled property + api.option('u1').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + api.property.add('test') + assert 'u1' not in values._p_.get_cached() + assert 'u1' not in settings._p_.get_cached() + api.option('u1').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + api.property.pop('test') + assert 'u1' not in values._p_.get_cached() + assert 'u1' not in settings._p_.get_cached() + + +def test_cache_reset_multi(): + od1 = make_description() + c = Config(od1) + api = getapi(c) + values = c.cfgimpl_get_values() + settings = c.cfgimpl_get_settings() + api.option('u1').value.get() + api.option('u3').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u3' in values._p_.get_cached() + assert 'u3' in settings._p_.get_cached() + #when change a value + api.option('u3').value.set([1]) + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u3' not in values._p_.get_cached() + assert 'u3' not in settings._p_.get_cached() + #when append value + api.option('u1').value.get() + api.option('u3').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u3' in values._p_.get_cached() + assert 'u3' in settings._p_.get_cached() + api.option('u3').value.set([1, 1]) + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u3' not in values._p_.get_cached() + assert 'u3' not in settings._p_.get_cached() + #when pop value + api.option('u1').value.get() + api.option('u3').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u3' in values._p_.get_cached() + assert 'u3' in settings._p_.get_cached() + api.option('u3').value.set([1]) + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u3' not in values._p_.get_cached() + assert 'u3' not in settings._p_.get_cached() + #when remove a value + api.option('u1').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + api.option('u3').value.reset() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u3' not in values._p_.get_cached() + assert 'u3' not in settings._p_.get_cached() + + +def test_reset_cache(): + od1 = make_description() + c = Config(od1) + api = getapi(c) + values = c.cfgimpl_get_values() + settings = c.cfgimpl_get_settings() + api.option('u1').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + c.cfgimpl_reset_cache() + assert 'u1' not in values._p_.get_cached() + assert 'u1' not in settings._p_.get_cached() + api.option('u1').value.get() + sleep(1) + api.option('u1').value.get() + sleep(1) + api.option('u2').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u2' in values._p_.get_cached() + assert 'u2' in settings._p_.get_cached() + c.cfgimpl_reset_cache() + assert 'u1' not in values._p_.get_cached() + assert 'u1' not in settings._p_.get_cached() + assert 'u2' not in values._p_.get_cached() + assert 'u2' not in settings._p_.get_cached() + + +#def test_reset_cache_subconfig(): +# od1 = make_description() +# od2 = OptionDescription('od2', '', [od1]) +# c = Config(od2) +# api = getapi(c) +# values = c.cfgimpl_get_values() +# api.option('od1.u1').value.get() +# assert 'od1.u1' in values._p_.get_cached() +# c.od1.cfgimpl_reset_cache() +# assert 'od1.u1' not in values._p_.get_cached() + + +def test_reset_cache_only_expired(): + od1 = make_description() + c = Config(od1) + api = getapi(c) + values = c.cfgimpl_get_values() + settings = c.cfgimpl_get_settings() + api.option('u1').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + c.cfgimpl_reset_cache(True) + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + sleep(1) + api.option('u1').value.get() + sleep(1) + api.option('u2').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u2' in values._p_.get_cached() + assert 'u2' in settings._p_.get_cached() + c.cfgimpl_reset_cache(True) + assert 'u1' not in values._p_.get_cached() + assert 'u1' not in settings._p_.get_cached() + assert 'u2' in values._p_.get_cached() + assert 'u2' in settings._p_.get_cached() + + +def test_cache_not_expire(): + od1 = make_description() + c = Config(od1) + api = getapi(c) + values = c.cfgimpl_get_values() + settings = c.cfgimpl_get_settings() + api.property.pop('expire') + api.option('u1').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + c.cfgimpl_reset_cache(True) + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + sleep(1) + api.option('u2').value.get() + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u2' in values._p_.get_cached() + assert 'u2' in settings._p_.get_cached() + c.cfgimpl_reset_cache(True) + assert 'u1' in values._p_.get_cached() + assert 'u1' in settings._p_.get_cached() + assert 'u2' in values._p_.get_cached() + assert 'u2' in settings._p_.get_cached() + + +def test_cache_not_cache(): + od1 = make_description() + c = Config(od1) + api = getapi(c) + values = c.cfgimpl_get_values() + settings = c.cfgimpl_get_settings() + api.property.pop('cache') + api.option('u1').value.get() + assert 'u1' not in values._p_.get_cached() + assert 'u1' not in settings._p_.get_cached() + + +#def test_reset_cache_only(): +# od1 = make_description() +# c = Config(od1) +# api = getapi(c) +# values = c.cfgimpl_get_values() +# settings = c.cfgimpl_get_settings() +# api.option('u1').value.get() +# assert 'u1' in values._p_.get_cached() +# assert 'u1' in settings._p_.get_cached() +# c.cfgimpl_reset_cache(only=('values',)) +# assert 'u1' not in values._p_.get_cached() +# assert 'u1' in settings._p_.get_cached() +# api.option('u1').value.get() +# assert 'u1' in values._p_.get_cached() +# assert 'u1' in settings._p_.get_cached() +# c.cfgimpl_reset_cache(only=('settings',)) +# assert 'u1' in values._p_.get_cached() +# assert 'u1' not in settings._p_.get_cached() + + +#def test_force_cache(): +# u1 = IntOption('u1', '', multi=True) +# u2 = IntOption('u2', '') +# u3 = IntOption('u3', '', multi=True) +# u4 = IntOption('u4', '', properties=('disabled',)) +# od = OptionDescription('od1', '', [u1, u2, u3, u4]) +# c = Config(od) +# api = getapi(c) +# api.property.read_write() +# api.property.pop('expire') +# api.property.pop('disabled') +# +# c.cfgimpl_get_values().force_cache() +# assert c.cfgimpl_get_values()._p_.get_cached() == {'u1': {None: ([], None)}, +# 'u2': {None: (None, None)}, +# 'u3': {None: ([], None)}, +# 'u4': {None: (None, None)}} +# assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings']), None)}, +# 'u1': {None: (set(['empty']), None)}, +# 'u2': {None: (set([]), None)}, +# 'u3': {None: (set(['empty']), None)}, +# 'u4': {None: (set(['disabled']), None)}} +# api.property.read_only() +# +# c.cfgimpl_get_values().force_cache() +# assert c.cfgimpl_get_values()._p_.get_cached() == {'u1': {None: ([], None)}, +# 'u2': {None: (None, None)}, +# 'u3': {None: ([], None)}} +# assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'empty', 'everything_frozen', 'frozen', 'mandatory', 'validator', 'warnings']), None)}, +# 'u1': {None: (set(['empty']), None)}, +# 'u2': {None: (set([]), None)}, +# 'u3': {None: (set(['empty']), None)}, +# 'u4': {None: (set(['disabled']), None)}} +# +# c.cfgimpl_get_settings().remove('cache') +# raises(ConfigError, "c.cfgimpl_get_values().force_cache()") + + +def test_cache_master_slave(): + 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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('toto', '', [interface1]) + cfg = Config(maconfig) + api = getapi(cfg) + api.property.read_write() + assert cfg.cfgimpl_get_values()._p_.get_cached() == {} + assert cfg.cfgimpl_get_settings()._p_.get_cached() == {} + # + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2']) + api.option('ip_admin_eth0.ip_admin_eth0').value.get() + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() + cache = cfg.cfgimpl_get_values()._p_.get_cached() + if TIRAMISU_VERSION == 2: + assert set(cache.keys()) == set(['ip_admin_eth0.ip_admin_eth0']) + else: + assert set(cache.keys()) == set(['ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0']) + assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None]) + assert cache['ip_admin_eth0.ip_admin_eth0'][None][0] == ['192.168.1.2'] + #assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None]) + #assert cache['ip_admin_eth0.netmask_admin_eth0'][None][0] == [None] + #assert cache['ip_admin_eth0.netmask_admin_eth0'][0][0] is None + cache = cfg.cfgimpl_get_settings()._p_.get_cached() + assert set(cache.keys()) == set([None, 'ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0']) + assert set(cache['ip_admin_eth0'].keys()) == set([None]) + assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None]) + if TIRAMISU_VERSION == 2: + assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None, 0]) + else: + assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([0]) + # + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2', '192.168.1.1']) + api.option('ip_admin_eth0.ip_admin_eth0').value.get() + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() + api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() + cache = cfg.cfgimpl_get_values()._p_.get_cached() + if TIRAMISU_VERSION == 2: + assert set(cache.keys()) == set(['ip_admin_eth0.ip_admin_eth0']) + else: + assert set(cache.keys()) == set(['ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0']) + assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None]) + assert cache['ip_admin_eth0.ip_admin_eth0'][None][0] == ['192.168.1.2', '192.168.1.1'] + #assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None]) + #assert cache['ip_admin_eth0.netmask_admin_eth0'][None][0] == [None, None] + #assert cache['ip_admin_eth0.netmask_admin_eth0'][0][0] is None + #assert cache['ip_admin_eth0.netmask_admin_eth0'][1][0] is None + cache = cfg.cfgimpl_get_settings()._p_.get_cached() + assert set(cache.keys()) == set([None, 'ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0']) + assert set(cache['ip_admin_eth0'].keys()) == set([None]) + assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None]) + if TIRAMISU_VERSION == 2: + assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None, 0, 1]) + else: + assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([0, 1]) + #DEL, insert, ... + + +def return_value(value=None): + return value + + +def test_cache_callback(): + val1 = StrOption('val1', "", 'val') + val2 = StrOption('val2', "", callback=return_value, callback_params={'': ((val1, False),)}, properties=('mandatory',)) + val3 = StrOption('val3', "", callback=return_value, callback_params={'': ('yes',)}) + val4 = StrOption('val4', "", callback=return_value, callback_params={'value': ((val1, False),)}) + val5 = StrOption('val5', "", callback=return_value, callback_params={'value': ('yes',)}, multi=True) + maconfig = OptionDescription('rootconfig', '', [val1, val2, val3, val4, val5]) + cfg = Config(maconfig) + api = getapi(cfg) + api.property.read_write() + api.property.pop('expire') + api.option.make_dict() + #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + # 'val1': {None: (set([]), None)}} + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('val', None)}, + 'val2': {None: ('val', None)}, + 'val3': {None: ('yes', None)}, + 'val4': {None: ('val', None)}, + 'val5': {None: (['yes'], None)}} + api.option('val1').value.set('new') + #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + # 'val1': {None: (set([]), None)}} + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val3': {None: ('yes', None)}, + 'val5': {None: (['yes'], None)}} + api.option.make_dict() + #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + # 'val1': {None: (set([]), None)}} + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('new', None)}, + 'val2': {None: ('new', None)}, + 'val3': {None: ('yes', None)}, + 'val4': {None: ('new', None)}, + 'val5': {None: (['yes'], None)}} + api.option('val3').value.set('new2') + #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + # 'val1': {None: (set([]), None)}, + # 'val3': {None: (set([]), None)}} + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('new', None)}, + 'val2': {None: ('new', None)}, + 'val4': {None: ('new', None)}, + 'val5': {None: (['yes'], None)}} + api.option.make_dict() + #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + # 'val1': {None: (set([]), None)}, + # 'val3': {None: (set([]), None)}} + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('new', None)}, + 'val2': {None: ('new', None)}, + 'val3': {None: ('new2', None)}, + 'val4': {None: ('new', None)}, + 'val5': {None: (['yes'], None)}} + api.option('val4').value.set('new3') + #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + # 'val1': {None: (set([]), None)}, + # 'val3': {None: (set([]), None)}, + # 'val4': {None: (set([]), None)}} + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('new', None)}, + 'val2': {None: ('new', None)}, + 'val3': {None: ('new2', None)}, + 'val5': {None: (['yes'], None)}} + api.option.make_dict() + #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + # 'val1': {None: (set([]), None)}, + # 'val3': {None: (set([]), None)}, + # 'val4': {None: (set([]), None)}} + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('new', None)}, + 'val2': {None: ('new', None)}, + 'val3': {None: ('new2', None)}, + 'val4': {None: ('new3', None)}, + 'val5': {None: (['yes'], None)}} + api.option('val5').value.set([undefined, 'new4']) + #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + # 'val1': {None: (set([]), None)}, + # 'val3': {None: (set([]), None)}, + # 'val4': {None: (set([]), None)}, + # 'val5': {None: (set(['empty']), None)}} + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('new', None)}, + 'val2': {None: ('new', None)}, + 'val3': {None: ('new2', None)}, + 'val4': {None: ('new3', None)}} + api.option.make_dict() + #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + # 'val1': {None: (set([]), None)}, + # 'val3': {None: (set([]), None)}, + # 'val4': {None: (set([]), None)}, + # 'val5': {None: (set(['empty']), None)}} + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1': {None: ('new', None)}, + 'val2': {None: ('new', None)}, + 'val3': {None: ('new2', None)}, + 'val4': {None: ('new3', None)}, + 'val5': {None: (['yes', 'new4'], None)}} + + +def test_cache_master_and_slaves_master(): + val1 = StrOption('val1', "", multi=True) + val2 = StrOption('val2', "", multi=True) + interface1 = MasterSlaves('val1', '', [val1, val2]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('rootconfig', '', [interface1]) + cfg = Config(maconfig) + api = getapi(cfg) + api.property.read_write() + api.property.pop('expire') + api.option.make_dict() + global_props = ['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings'] + val1_props = [] + val1_val1_props = ['empty'] + val1_val2_props = [] + if TIRAMISU_VERSION == 2: + global_props = set(global_props) + val1_props = set(val1_props) + val1_val1_props = set(val1_val1_props) + val1_val2_props = set(val1_val2_props) + else: + global_props = frozenset(global_props) + val1_props = frozenset(val1_props) + val1_val1_props = frozenset(val1_val1_props) + val1_val2_props = frozenset(val1_val2_props) + #None because no value + idx_val2 = None + assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (global_props, None)}, + 'val1': {None: (val1_props, None)}, + 'val1.val1': {None: (val1_val1_props, None)}, + 'val1.val2': {idx_val2: (val1_val2_props, None)}} + if TIRAMISU_VERSION == 2: + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([], None)}, 'val1.val2': {None: ([], None)}} + else: + # len is 0 so don't get any value + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([], None)}} + # + api.option('val1.val1').value.set([undefined]) + assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}} + assert cfg.cfgimpl_get_values()._p_.get_cached() == {} + api.option.make_dict() + if TIRAMISU_VERSION == 2: + val_val2 = [None] + val_val2_props = {None: (set(), None), 0: (set(), None)} + else: + #has value + idx_val2 = 0 + val_val2 = None + val_val2_props = {idx_val2: (val1_val2_props, None)} + assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (global_props, None)}, + 'val1': {None: (val1_props, None)}, + 'val1.val1': {None: (val1_val1_props, None)}, + 'val1.val2': val_val2_props} + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([None], None)}, + 'val1.val2': {idx_val2: (val_val2, None)}} + api.option('val1.val1').value.set([undefined, undefined]) + api.option.make_dict() + api.option('val1.val2', 1).value.set('oui') + assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}} + assert cfg.cfgimpl_get_values()._p_.get_cached() == {} + api.option.make_dict() + if TIRAMISU_VERSION == 2: + val1_val2_props = {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)} + else: + val1_val2_props = {0: (frozenset([]), None), 1: (frozenset([]), None)} + assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (global_props, None)}, + 'val1': {None: (val1_props, None)}, + 'val1.val1': {None: (val1_val1_props, None)}, + 'val1.val2': val1_val2_props} + if TIRAMISU_VERSION == 2: + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([None, None], None)}, + 'val1.val2': {None: ([None, 'oui'], None)}} + else: + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([None, None], None)}, + 'val1.val2': {0: (None, None), 1: ('oui', None)}} + + +def test_cache_master_callback(): + val1 = StrOption('val1', "", multi=True) + val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'value': ((val1, False),)}) + interface1 = MasterSlaves('val1', '', [val1, val2]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('rootconfig', '', [interface1]) + cfg = Config(maconfig) + api = getapi(cfg) + api.property.read_write() + api.property.pop('expire') + api.option.make_dict() + global_props = ['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings'] + val1_props = [] + val1_val1_props = ['empty'] + val1_val2_props = [] + if TIRAMISU_VERSION == 2: + global_props = set(global_props) + val1_props = set(val1_props) + val1_val1_props = set(val1_val1_props) + val1_val2_props = set(val1_val2_props) + else: + global_props = frozenset(global_props) + val1_props = frozenset(val1_props) + val1_val1_props = frozenset(val1_val1_props) + val1_val2_props = frozenset(val1_val2_props) + assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (global_props, None)}, + 'val1': {None: (val1_props, None)}, + 'val1.val1': {None: (val1_val1_props, None)}, + 'val1.val2': {None: (val1_val2_props, None)}} + if TIRAMISU_VERSION == 2: + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([], None)}, 'val1.val2': {None: ([], None)}} + else: + assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([], None)}} + api.option('val1.val1').value.set([undefined]) + assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}} + + assert cfg.cfgimpl_get_values()._p_.get_cached() == {} + api.option.make_dict() + #FIXMEassert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + # 'val1': {None: (set([]), None)}} + #FIXMEassert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([None], None)}, + # 'val1.val2': {None: ([None], None)} + # } + + +#def test_cache_master_slave_different(): +# b = IntOption('int', 'Test int option', default=[0], multi=True) +# c = StrOption('str', 'Test string option', multi=True) +# d = StrOption('str1', 'Test string option', requires=[{'option': c, 'expected': None, 'action': 'hidden', 'inverse': True}], multi=True) +# descr = MasterSlaves("int", "", [b, c, d]) +# #descr.impl_set_group_type(groups.master) +# cfg = Config(descr) +# api = getapi(cfg) +# api.property.read_write() +# api.property.pop('expire') +# api.option.make_dict() +# assert cfg.cfgimpl_get_values()._p_.get_cached() == {'int': {None: ([0], None)}, +# 'str': {None: ([None], None)}, +# 'str1': {None: ([None], None)}} +# assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, +# 'int': {None: (set(['empty']), None)}, +# 'str': {None: (set([]), None), 0: (set([]), None)}, +# 'str1': {None: (set([]), None), 0: (set([]), None)}} +# api.option('int').value.set([0, 1]) +# api.option.make_dict() +# assert cfg.cfgimpl_get_values()._p_.get_cached() == {'int': {None: ([0, 1], None)}, +# 'str': {None: ([None, None], None)}, +# 'str1': {None: ([None, None], None)}} +# assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, +# 'int': {None: (set(['empty']), None)}, +# 'str': {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)}, +# 'str1': {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)}} +# +# api.option('str', 1).value.set('1') +# api.option.make_dict() +# assert set(cfg.cfgimpl_get_values()._p_.get_cached().keys()) == set(['int', 'str', 'str1']) +# assert cfg.cfgimpl_get_values()._p_.get_cached()['int'] == {None: ([0, 1], None)} +# assert cfg.cfgimpl_get_values()._p_.get_cached()['str'] == {None: ([None, '1'], None)} +# assert cfg.cfgimpl_get_values()._p_.get_cached()['str1'][None][0][0] == None +# raises(PropertiesOptionError, "cfg.cfgimpl_get_values()._p_.get_cached()['str1'][None][0][1]") +# assert cfg.cfgimpl_get_values()._p_.get_cached()['str1'][None][1] == None +# assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, +# 'int': {None: (set(['empty']), None)}, +# 'str': {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)}, +# 'str1': {None: (set([]), None), 0: (set([]), None), 1: (set(['hidden']), None)}} +# api.property.read_only() +# assert cfg.cfgimpl_get_values()._p_.get_cached() == {} +# assert cfg.cfgimpl_get_settings()._p_.get_cached() == {} +# api.option.make_dict() +# assert cfg.cfgimpl_get_values()._p_.get_cached() == {'int': {None: ([0, 1], None)}, +# 'str': {None: ([None, '1'], None)}, +# 'str1': {None: ([None, None], None)}} +# assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'everything_frozen', 'validator', 'warnings', 'empty', 'mandatory', ]), None)}, +# 'int': {None: (set(['empty']), None)}, +# 'str': {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)}, +# 'str1': {None: (set([]), None), 0: (set([]), None), 1: (set(['hidden']), None)}} + + + +def test_cache_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) + api = getapi(c) + api.property.read_write() + api.property.pop('expire') + assert c.cfgimpl_get_settings()._p_.get_cached() == {} + assert c.cfgimpl_get_values()._p_.get_cached() == {} + assert api.option('ip_address_service').value.get() == None + assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'activate_service': {None: (set([]), None)}, + 'ip_address_service': {None: (set([]), None)}} + + assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: (None, None)}} + api.option.make_dict() + assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'activate_service': {None: (set([]), None)}, + 'ip_address_service': {None: (set([]), None)}} + + assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: (None, None)}, + 'activate_service': {None: (True, None)}} + api.option('ip_address_service').value.set('1.1.1.1') + assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'activate_service': {None: (set([]), None)}} + + assert c.cfgimpl_get_values()._p_.get_cached() == {'activate_service': {None: (True, None)}} + api.option.make_dict() + assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'activate_service': {None: (set([]), None)}, + 'ip_address_service': {None: (set([]), None)}} + + assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: ('1.1.1.1', None)}, + 'activate_service': {None: (True, None)}} + api.option('activate_service').value.set(False) + assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}} + + assert c.cfgimpl_get_values()._p_.get_cached() == {} + api.option.make_dict() + assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'activate_service': {None: (set([]), None)}, + 'ip_address_service': {None: (set(['disabled']), None)}} + + assert c.cfgimpl_get_values()._p_.get_cached() == {'activate_service': {None: (False, None)}} + + +def test_cache_global_properties(): + 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) + api = getapi(c) + api.property.read_write() + api.property.pop('expire') + assert c.cfgimpl_get_settings()._p_.get_cached() == {} + assert c.cfgimpl_get_values()._p_.get_cached() == {} + assert api.option('ip_address_service').value.get() == None + assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'activate_service': {None: (set([]), None)}, + 'ip_address_service': {None: (set([]), None)}} + + assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: (None, None)}} + api.property.pop('disabled') + assert api.option('ip_address_service').value.get() == None + assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'activate_service': {None: (set([]), None)}, + 'ip_address_service': {None: (set([]), None)}} + api.property.add('test') + assert api.option('ip_address_service').value.get() == None + assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings', 'test']), None)}, + 'activate_service': {None: (set([]), None)}, + 'ip_address_service': {None: (set([]), None)}} + + +def test_callback_value_incr(): + val1 = IntOption('val1', "", callback=return_incr) + val2 = IntOption('val2', "", callback=return_value, callback_params={'value': ((val1, False),)}) + maconfig = OptionDescription('rootconfig', '', [val1, val2]) + cfg = Config(maconfig) + api = getapi(cfg) + api.property.read_write() + assert api.option('val1').value.get() == 1 + sleep(1) + assert api.option('val2').value.get() == 1 + sleep(1) + assert api.option('val1').value.get() == 2 + assert api.option('val2').value.get() == 2 diff --git a/test/new_api/test_choice_option.py b/test/new_api/test_choice_option.py new file mode 100644 index 0000000..02e253e --- /dev/null +++ b/test/new_api/test_choice_option.py @@ -0,0 +1,199 @@ +# coding: utf-8 +from py.test import raises + +from .autopath import do_autopath +do_autopath() + +from tiramisu.setting import owners +from tiramisu.option import ChoiceOption, StrOption, OptionDescription +from tiramisu.config import Config +from tiramisu.error import ConfigError +from tiramisu import getapi, undefined + + +def return_val(val): + return val + + +def return_list(): + return ['val1', 'val2'] + + +def return_calc_list(val): + return [val] + + +def return_error(): + raise Exception('test') + + +def test_choiceoption(): + choice = ChoiceOption('choice', '', values=('val1', 'val2')) + odesc = OptionDescription('od', '', [choice]) + cfg = Config(odesc) + api = getapi(cfg) + api.property.read_write() + owner = api.owner.get() + assert api.option('choice').owner.get() == owners.default + assert api.option('choice').owner.isdefault() + # + api.option('choice').value.set('val1') + assert api.option('choice').owner.get() == owner + assert not api.option('choice').owner.isdefault() + # + api.option('choice').value.reset() + assert api.option('choice').owner.get() == owners.default + assert api.option('choice').owner.isdefault() + # + raises(ValueError, "api.option('choice').value.set('no')") + assert api.option('choice').owner.get() == owners.default + assert api.option('choice').owner.isdefault() + # + assert api.option('choice').value.list() == ('val1', 'val2') + + +def test_choiceoption_function(): + choice = ChoiceOption('choice', '', values=return_list) + odesc = OptionDescription('od', '', [choice]) + cfg = Config(odesc) + api = getapi(cfg) + api.property.read_write() + owner = api.owner.get() + assert api.option('choice').owner.isdefault() + # + api.option('choice').value.set('val1') + assert api.option('choice').owner.get() == owner + # + api.option('choice').value.reset() + assert api.option('choice').owner.isdefault() + # + raises(ValueError, "api.option('choice').value.set('no')") + assert api.option('choice').owner.isdefault() + # + assert api.option('choice').value.list() == ['val1', 'val2'] + + +def test_choiceoption_function_error(): + choice = ChoiceOption('choice', '', values=return_error) + odesc = OptionDescription('od', '', [choice]) + cfg = Config(odesc) + api = getapi(cfg) + api.property.read_write() + raises(ConfigError, "api.option('choice').value.set('val1')") + + +def test_choiceoption_calc_function(): + choice = ChoiceOption('choice', "", values=return_calc_list, values_params={'': ('val1',)}) + odesc = OptionDescription('od', '', [choice]) + cfg = Config(odesc) + api = getapi(cfg) + api.property.read_write() + owner = api.owner.get() + assert api.option('choice').owner.isdefault() + # + api.option('choice').value.set('val1') + assert api.option('choice').owner.get() == owner + # + api.option('choice').value.reset() + assert api.option('choice').owner.isdefault() + # + raises(ValueError, "api.option('choice').value.set('no')") + assert api.option('choice').owner.isdefault() + + +def test_choiceoption_calc_opt_function(): + str_ = StrOption('str', '', 'val1') + choice = ChoiceOption('choice', + "", + values=return_calc_list, + values_params={'': ((str_, False),)}) + odesc = OptionDescription('od', '', [str_, choice]) + cfg = Config(odesc) + api = getapi(cfg) + api.property.read_write() + owner = api.owner.get() + assert api.option('choice').owner.isdefault() + # + api.option('choice').value.set('val1') + assert api.option('choice').owner.get() == owner + # + api.option('choice').value.reset() + assert api.option('choice').owner.isdefault() + # + raises(ValueError, "api.option('choice').value.set('no')") + assert api.option('choice').owner.isdefault() + + +def test_choiceoption_calc_opt_function_propertyerror(): + str_ = StrOption('str', '', 'val1', properties=('disabled',)) + choice = ChoiceOption('choice', + "", + values=return_calc_list, + values_params={'': ((str_, False),)}) + odesc = OptionDescription('od', '', [str_, choice]) + cfg = Config(odesc) + api = getapi(cfg) + api.property.read_write() + raises(ConfigError, "api.option('choice').value.set('no')") + + +def test_choiceoption_calc_opt_multi_function(): + str_ = StrOption('str', '', ['val1'], multi=True) + choice = ChoiceOption('choice', + "", + default_multi='val2', + values=return_val, + values_params={'': ((str_, False),)}, + multi=True) + ch2 = ChoiceOption('ch2', + "", + default=['val2'], + values=return_val, + values_params={'': ((str_, False),)}, + multi=True) + odesc = OptionDescription('od', '', [str_, choice, ch2]) + cfg = Config(odesc) + api = getapi(cfg) + api.property.read_write() + owner = api.owner.get() + assert api.option('choice').owner.isdefault() + assert api.option('choice').value.get() == [] + # + api.option('choice').value.set(['val1']) + assert api.option('choice').owner.get() == owner + # + raises(ValueError, "api.option('choice').value.set([undefined])") + # + api.option('choice').value.set(['val1']) + assert api.option('choice').owner.get() == owner + # + api.option('choice').value.reset() + assert api.option('choice').owner.isdefault() + # + raises(ValueError, "api.option('choice').value.set('no')") + assert api.option('choice').owner.isdefault() + # + raises(ValueError, "api.option('ch2').value.get()") + + +def test_choiceoption_calc_invalid(): + str_ = StrOption('str', '', ['val1'], multi=True) + str_ + raises(ValueError, + "choice = ChoiceOption('choice', '', default_multi='val2', values=[1, 2, 3], \ + values_params={'': ((str_, False),)}, multi=True)") + + +def test_choiceoption_calc_not_list(): + str_ = StrOption('str', '', 'val1') + choice = ChoiceOption('choice', + "", + default_multi='val2', + values=return_val, + values_params={'': ((str_, False),)}, + multi=True) + odesc = OptionDescription('od', '', [str_, choice]) + cfg = Config(odesc) + api = getapi(cfg) + api.property.read_write() + raises(ConfigError, "api.option('choice').value.set(['val1'])") diff --git a/test/new_api/test_config.py b/test/new_api/test_config.py new file mode 100644 index 0000000..c067eb1 --- /dev/null +++ b/test/new_api/test_config.py @@ -0,0 +1,403 @@ +# -*- coding: utf-8 -*- + +"""theses tests are much more to test that config, option description, vs... +**it's there** and answers via attribute access""" +from py.test import raises +import weakref + +from .autopath import do_autopath +do_autopath() + +from tiramisu.config import Config, SubConfig +from tiramisu.i18n import _ +from tiramisu import Config, IntOption, FloatOption, StrOption, ChoiceOption, \ + BoolOption, UnicodeOption, OptionDescription, getapi, undefined +from tiramisu.error import ConflictError, ConfigError, PropertiesOptionError, APIError + + +def make_description(): + gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref') + gcdummy = BoolOption('dummy', 'dummy', default=False) + objspaceoption = ChoiceOption('objspace', 'Object space', + ('std', 'thunk'), 'std') + booloption = BoolOption('bool', 'Test boolean option', default=True) + intoption = IntOption('int', 'Test int option', default=0) + floatoption = FloatOption('float', 'Test float option', default=2.3) + stroption = StrOption('str', 'Test string option', default="abc", properties=('mandatory', )) + boolop = BoolOption('boolop', 'Test boolean option op', default=True, properties=('hidden',)) + wantref_option = BoolOption('wantref', 'Test requires', default=False) + wantframework_option = BoolOption('wantframework', 'Test requires', + default=False) + + gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption]) + descr = OptionDescription('tiram', '', [gcgroup, booloption, objspaceoption, + wantref_option, stroption, + wantframework_option, + intoption, boolop]) + return descr + + +def test_base_config(): + """making a :class:`tiramisu.config.Config()` object + and a :class:`tiramisu.option.OptionDescription()` object + """ + gcdummy = BoolOption('dummy', 'dummy', default=False) + descr = OptionDescription('tiramisu', '', [gcdummy]) + cfg = Config(descr) + api = getapi(cfg) + assert api.option('dummy').value.get() is False + dmo = cfg.unwrap_from_path('dummy') + assert dmo.impl_getname() == 'dummy' + + +def test_base_config_name(): + gcdummy = BoolOption('dummy', 'dummy', default=False) + descr = OptionDescription('tiramisu', '', [gcdummy]) + cfg = Config(descr, session_id='cfg') + cfg.impl_getname() == 'cfg' + raises(ValueError, "Config(descr, session_id='unvalid name')") + + +def test_not_config(): + assert raises(TypeError, "Config('str')") + + +def test_base_path(): + gcdummy = BoolOption('dummy', 'dummy', default=False) + descr = OptionDescription('tiramisu', '', [gcdummy]) + cfg = Config(descr) + assert cfg._impl_path is None + base = OptionDescription('config', '', [descr]) + cfg = Config(base) + assert cfg._impl_path is None + assert cfg.getattr('tiramisu', None, validate_properties=False)._impl_path == 'tiramisu' + nbase = OptionDescription('baseconfig', '', [base]) + cfg = Config(nbase) + assert cfg._impl_path is None + assert cfg.getattr('config', None, validate_properties=False)._impl_path == 'config' + assert cfg.getattr('config.tiramisu', None, validate_properties=False)._impl_path == 'config.tiramisu' + + +def test_base_config_force_permissive(): + descr = make_description() + config = Config(descr) + api = getapi(config) + api.property.read_write() + api.permissive.set(('hidden',)) + raises(PropertiesOptionError, "api.option('boolop').value.get()") + assert api.forcepermissive.option('boolop').value.get() is True + + +def test_base_config_in_a_tree(): + "how options are organized into a tree, see :ref:`tree`" + descr = make_description() + config = Config(descr) + api = getapi(config) + # + api.option('bool').value.set(False) + # + assert api.option('gc.name').value.get() == 'ref' + api.option('gc.name').value.set('framework') + assert api.option('gc.name').value.get() == 'framework' + # + assert api.option('objspace').value.get() == 'std' + api.option('objspace').value.set('thunk') + assert api.option('objspace').value.get() == 'thunk' + # + assert api.option('gc.float').value.get() == 2.3 + api.option('gc.float').value.set(3.4) + assert api.option('gc.float').value.get() == 3.4 + # + assert api.option('int').value.get() == 0 + api.option('int').value.set(123) + assert api.option('int').value.get() == 123 + # + assert api.option('wantref').value.get() is False + api.option('wantref').value.set(True) + assert api.option('wantref').value.get() is True + # + assert api.option('str').value.get() == 'abc' + api.option('str').value.set('def') + assert api.option('str').value.get() == 'def' + # + raises(AttributeError, "api.option('gc.foo').value.get()") + ## + config = Config(descr) + api = getapi(config) + assert api.option('bool').value.get() is True + assert api.option('gc.name').value.get() == 'ref' + assert api.option('wantframework').value.get() is False + + +def test_cfgimpl_get_home_by_path(): + " :meth:`tiramisu.config.SubConfig.cfgimpl_get_home_by_path()` to retrieve a path" + descr = make_description() + config = Config(descr) + api = getapi(config) + api.option('bool').value.set(False) + assert config.cfgimpl_get_home_by_path('gc.dummy', None)[1] == 'dummy' + assert config.cfgimpl_get_home_by_path('dummy', None)[1] == 'dummy' + + +def test_not_valid_properties(): + raises(TypeError, "stroption = StrOption('str', 'Test string option', default='abc', properties=['mandatory',])") + + +def test_information_config(): + descr = make_description() + config = Config(descr) + api = getapi(config) + string = 'some informations' + # + api.information.set('info', string) + assert api.information.get('info') == string + # + raises(ValueError, "api.information.get('noinfo')") + assert api.information.get('noinfo', 'default') == 'default' + api.information.reset('info') + raises(ValueError, "api.information.get('info')") + raises(ValueError, "api.information.reset('noinfo')") + + +def test_config_impl_get_path_by_opt(): + descr = make_description() + config = Config(descr) + api = getapi(config) + dummy = api.option.get('gc.dummy') + boo = api.option.get('bool') + unknown = IntOption('test', '') + unknown + assert config.cfgimpl_get_description().impl_get_path_by_opt(boo) == 'bool' + assert config.cfgimpl_get_description().impl_get_path_by_opt(dummy) == 'gc.dummy' + raises(AttributeError, "config.cfgimpl_get_description().impl_get_path_by_opt(unknown)") + + +def test_config_impl_get_path_by_opt_od(): + descr = make_description() + config = Config(descr) + api = getapi(config) + dummy = api.option.get('gc.dummy') + dummy + raises(ConfigError, "config.getattr('gc', None).cfgimpl_get_description().impl_get_path_by_opt(dummy)") + + +def test_config_impl_get_opt_by_path(): + descr = make_description() + config = Config(descr) + api = getapi(config) + dummy = api.option.get('gc.dummy') + boo = api.option.get('bool') + assert config.cfgimpl_get_description().impl_get_opt_by_path('bool') == boo + assert config.cfgimpl_get_description().impl_get_opt_by_path('gc.dummy') == dummy + raises(AttributeError, "config.cfgimpl_get_description().impl_get_opt_by_path('gc.unknown')") + raises(ConfigError, "config.getattr('gc', None).cfgimpl_get_description().impl_get_opt_by_path('gc.unknown')") + + +#def test_information_display(): +# g1 = IntOption('g1', '', 1) +# g2 = StrOption('g2', '', 'héhé') +# g3 = UnicodeOption('g3', '', u'héhé') +# g4 = BoolOption('g4', '', True) +# g5 = StrOption('g5', '') +# d1 = OptionDescription('od', '', [g1, g2, g3, g4, g5]) +# root = OptionDescription('root', '', [d1]) +# config = Config(root) +# assert str(config.od) == """g1 = 1 +#g2 = héhé +#g3 = héhé +#g4 = True +#g5 = None""" +# assert str(config) == '[od]' + + +def test_get_modified_values(): + g1 = IntOption('g1', '', 1) + g2 = StrOption('g2', '', 'héhé') + g3 = UnicodeOption('g3', '', u'héhé') + g4 = BoolOption('g4', '', True) + g5 = StrOption('g5', '') + g6 = StrOption('g6', '', multi=True) + d1 = OptionDescription('od', '', [g1, g2, g3, g4, g5, g6]) + root = OptionDescription('root', '', [d1]) + config = Config(root) + api = getapi(config) + assert config.cfgimpl_get_values().get_modified_values() == {} + api.option('od.g5').value.set('yes') + assert config.cfgimpl_get_values().get_modified_values() == {'od.g5': ('user', 'yes')} + api.option('od.g4').value.set(True) + assert config.cfgimpl_get_values().get_modified_values() == {'od.g5': ('user', 'yes'), 'od.g4': ('user', True)} + api.option('od.g4').value.reset() + assert config.cfgimpl_get_values().get_modified_values() == {'od.g5': ('user', 'yes')} + api.option('od.g6').value.set([undefined]) + assert config.cfgimpl_get_values().get_modified_values() == {'od.g5': ('user', 'yes'), 'od.g6': ('user', (None,))} + api.option('od.g6').value.set([]) + assert config.cfgimpl_get_values().get_modified_values() == {'od.g5': ('user', 'yes'), 'od.g6': ('user', tuple())} + api.option('od.g6').value.set(['3']) + assert config.cfgimpl_get_values().get_modified_values() == {'od.g5': ('user', 'yes'), 'od.g6': ('user', ('3',))} + api.option('od.g6').value.set([]) + assert config.cfgimpl_get_values().get_modified_values() == {'od.g5': ('user', 'yes'), 'od.g6': ('user', tuple())} + + +#def test_has_value(): +# g1 = IntOption('g1', '', 1) +# g2 = StrOption('g2', '', 'héhé') +# g3 = UnicodeOption('g3', '', u'héhé') +# g4 = BoolOption('g4', '', True) +# g5 = StrOption('g5', '') +# d1 = OptionDescription('od', '', [g1, g2, g3, g4, g5]) +# root = OptionDescription('root', '', [d1]) +# config = Config(root) +# api = getapi(config) +# assert not g5 in config.cfgimpl_get_values() +# api.option('od.g5').value.set('yes') +# assert g5 in config.cfgimpl_get_values() + + +#def test_values_not_setitem(): +# g1 = IntOption('g1', '', 1) +# g2 = StrOption('g2', '', 'héhé') +# g3 = UnicodeOption('g3', '', u'héhé') +# g4 = BoolOption('g4', '', True) +# g5 = StrOption('g5', '') +# d1 = OptionDescription('od', '', [g1, g2, g3, g4, g5]) +# root = OptionDescription('root', '', [d1]) +# config = Config(root) +# config +# raises(ConfigError, "config.cfgimpl_get_values()[g1] = 2") + + +def test_duplicated_option(): + g1 = IntOption('g1', '', 1) + g1 + #in same OptionDescription + raises(ConflictError, "d1 = OptionDescription('od', '', [g1, g1])") + + +def test_duplicated_option_diff_od(): + g1 = IntOption('g1', '', 1) + d1 = OptionDescription('od1', '', [g1]) + #in different OptionDescription + d2 = OptionDescription('od2', '', [g1, d1]) + d2 + raises(ConflictError, 'Config(d2)') + + +def test_cannot_assign_value_to_option_description(): + descr = make_description() + cfg = Config(descr) + api = getapi(cfg) + api + raises(APIError, "api.option('gc').value.set(3)") + + +def test_config_multi(): + i1 = IntOption('test1', '', multi=True) + i2 = IntOption('test2', '', multi=True, default_multi=1) + i3 = IntOption('test3', '', default=[2], multi=True, default_multi=1) + od = OptionDescription('test', '', [i1, i2, i3]) + config = Config(od) + api = getapi(config) + assert api.option('test1').value.get() == [] + assert api.option('test2').value.get() == [] + api.option('test2').value.set([undefined]) + assert api.option('test2').value.get() == [1] + assert api.option('test3').value.get() == [2] + api.option('test3').value.set([undefined, undefined]) + assert api.option('test3').value.get() == [2, 1] + + +def test_no_validation(): + i1 = IntOption('test1', '') + od = OptionDescription('test', '', [i1]) + cfg = Config(od) + api = getapi(cfg) + api.property.read_write() + api.option('test1').value.set(1) + raises(ValueError, "api.option('test1').value.set('yes')") + assert api.option('test1').value.get() == 1 + api.property.pop('validator') + api.option('test1').value.set('yes') + assert api.option('test1').value.get() == 'yes' + api.property.add('validator') + raises(ValueError, "api.option('test1').value.get()") + api.option('test1').value.reset() + assert api.option('test1').value.get() is None + + +#def test_delete_config_with_subconfig(): +# test = IntOption('test', '') +# multi = IntOption('multi', '', multi=True) +# od = OptionDescription('od', '', [test, multi]) +# odroot = OptionDescription('odroot', '', [od]) +# cfg = Config(odroot) +# api = getapi(cfg) +# sub = cfg.od +# val = cfg.cfgimpl_get_values() +# setting = cfg.cfgimpl_get_settings() +# assert api.option('od.test').value.get() is None +# assert api.option('od.multi').value.get() == [] +# api.config.make_dict() +# del(api) +# del(cfg) +# raises(ConfigError, 'val[test]') +# raises(ConfigError, 'val[multi]') +# raises(ConfigError, 'setting[test]') +# raises(ConfigError, 'sub.make_dict()') + + +def test_subconfig(): + i = IntOption('i', '') + o = OptionDescription('val', '', [i]) + o2 = OptionDescription('val', '', [o]) + c = Config(o2) + c + raises(TypeError, "SubConfig(i, weakref.ref(c))") + + +#def test_config_weakref(): +# o = OptionDescription('val', '', []) +# o2 = OptionDescription('val', '', [o]) +# c = Config(o2) +# SubConfig(o, weakref.ref(c)) +# raises(ValueError, "SubConfig(o, c)") +# s = SubConfig(o, weakref.ref(c)) +# assert s._cfgimpl_get_context() == c +# del(c) +# raises(ConfigError, "s._cfgimpl_get_context()") + + +#def test_config_str(): +# gcdummy = BoolOption('dummy', 'dummy', default=False) +# gcdummy1 = BoolOption('dummy1', 'dummy', default=False, properties=('disabled',)) +# o = OptionDescription('o', '', [gcdummy, gcdummy1]) +# descr = OptionDescription('tiramisu', '', [o]) +# cfg = Config(descr) +# api = getapi(cfg) +# api.property.read_only() +# str(cfg) +# str(cfg.o) + + +#def test_config_od_function(): +# gcdummy = BoolOption('dummy', 'dummy', default=False) +# gcdummy1 = BoolOption('dummy1', 'dummy', default=False, properties=('disabled',)) +# o = OptionDescription('o', '', [gcdummy, gcdummy1]) +# descr = OptionDescription('tiramisu', '', [o]) +# cfg = Config(descr) +# try: +# print(cfg.impl_get_opt_by_path()) +# except AttributeError as err: +# assert str(err) == _('unknown Option {0} in OptionDescription {1}' +# '').format('impl_get_opt_by_path', descr.impl_getname()) + + +def test_config_subconfig(): + i1 = IntOption('i1', '') + i2 = IntOption('i2', '', default=1) + i3 = IntOption('i3', '') + i4 = IntOption('i4', '', default=2) + od1 = OptionDescription('od1', '', [i1, i2, i3, i4]) + od2 = OptionDescription('od2', '', [od1]) + conf1 = Config(od2, session_id='conf1') + api = getapi(conf1) + raises(ConfigError, "conf2 = Config(od1, session_id='conf2')") diff --git a/test/new_api/test_config_api.py b/test/new_api/test_config_api.py new file mode 100644 index 0000000..1ffa915 --- /dev/null +++ b/test/new_api/test_config_api.py @@ -0,0 +1,387 @@ +"configuration objects global API" +from py.test import raises + +from .autopath import do_autopath +do_autopath() + +from tiramisu import Config, IntOption, FloatOption, StrOption, ChoiceOption, \ + BoolOption, FilenameOption, UnicodeOption, SymLinkOption, IPOption, \ + PortOption, NetworkOption, NetmaskOption, BroadcastOption, \ + DomainnameOption, OptionDescription, getapi +from tiramisu.error import PropertiesOptionError + + +def make_description(): + gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref') + gcdummy = BoolOption('dummy', 'dummy', default=False) + prop = BoolOption('prop', '', properties=('disabled',)) + prop2 = BoolOption('prop', '', properties=('hidden',)) + objspaceoption = ChoiceOption('objspace', 'Object space', + ('std', 'thunk'), 'std') + booloption = BoolOption('bool', 'Test boolean option', default=True) + booloption2 = BoolOption('bool', 'Test boolean option', default=False) + intoption = IntOption('int', 'Test int option', default=0) + floatoption2 = FloatOption('float', 'Test float option', default=2.3) + floatoption = FloatOption('float', 'Test float option', default=2.3) + stroption = StrOption('str', 'Test string option', default="abc") + boolop = BoolOption('boolop', 'Test boolean option op', default=True) + wantref_option = BoolOption('wantref', 'Tests', default=False) + wantframework_option = BoolOption('wantframework', 'Test', default=False) + gcgroup2 = OptionDescription('gc2', '', [booloption2, prop]) + gcgroup = OptionDescription('gc', '', [gcgroup2, gcoption, gcdummy, floatoption, prop2]) + descr = OptionDescription('tiramisu', '', [gcgroup, booloption, objspaceoption, + wantref_option, stroption, + wantframework_option, + intoption, boolop, floatoption2]) + return descr + + +def _is_same_opt(opt1, opt2): + if "id" in dir(opt1): + assert opt1.id == opt2.id + else: + assert opt1 == opt2 + + +#def test_iter_config(): +# "iteration on config object" +# s = StrOption("string", "", default="string") +# s2 = StrOption("string2", "", default="string2") +# descr = OptionDescription("options", "", [s, s2]) +# config = Config(descr) +# assert [(name, value) for name, value in config] == \ +# [('string', 'string'), ('string2', 'string2')] +# +# +#def test_iter_config_property(): +# "iteration on config object" +# s = StrOption("string", "", default="string", properties=('disabled',)) +# s2 = StrOption("string2", "", default="string2") +# descr = OptionDescription("options", "", [s, s2]) +# config = Config(descr) +# config.read_only() +# assert [(name, value) for name, value in config] == \ +# [('string2', 'string2')] +# +# +#def test_iter_subconfig(): +# "iteration on config sub object" +# descr = make_description() +# conf = Config(descr) +# for (name, value), (gname, gvalue) in \ +# zip(conf.gc, [("name", "ref"), ("dummy", False)]): +# assert name == gname +# assert value == gvalue + + +def test_str(): + descr = make_description() + c = Config(descr) + c # does not crash + + +def test_make_dict(): + "serialization of the whole config to a dict" + descr = OptionDescription("opt", "", [ + OptionDescription("s1", "", [ + BoolOption("a", "", default=False), + BoolOption("b", "", default=False, properties=('hidden',))]), + IntOption("int", "", default=42)]) + config = Config(descr) + api = getapi(config) + api.property.read_write() + api.permissive.set(('hidden',)) + d = api.option.make_dict() + assert d == {"s1.a": False, "int": 42} + api.option('int').value.set(43) + api.option('s1.a').value.set(True) + d = api.option.make_dict() + assert d == {"s1.a": True, "int": 43} + d2 = api.option.make_dict(flatten=True) + assert d2 == {'a': True, 'int': 43} + raises(ValueError, 'd2 = api.option.make_dict(withvalue="3")') + d = api.forcepermissive.option.make_dict() + assert d == {"s1.a": True, "s1.b": False, "int": 43} + + +def test_make_dict_with_disabled(): + descr = OptionDescription("opt", "", [ + OptionDescription("s1", "", [ + BoolOption("a", "", default=False), + BoolOption("b", "", default=False, properties=('disabled',))]), + OptionDescription("s2", "", [ + BoolOption("a", "", default=False), + BoolOption("b", "", default=False)], properties=('disabled',)), + IntOption("int", "", default=42)]) + config = Config(descr) + api = getapi(config) + api.property.read_only() + d = api.option.make_dict() + assert d == {"s1.a": False, "int": 42} + + +def test_make_dict_with_disabled_in_callback(): + descr = OptionDescription("opt", "", [ + OptionDescription("s1", "", [ + BoolOption("a", "", default=False), + BoolOption("b", "", default=False, properties=('disabled',))]), + OptionDescription("s2", "", [ + BoolOption("a", "", default=False), + BoolOption("b", "", default=False)], properties=('disabled',)), + IntOption("int", "", default=42)]) + config = Config(descr) + api = getapi(config) + api.property.read_only() + d = api.option.make_dict() + assert d == {"s1.a": False, "int": 42} + + +def test_make_dict_fullpath(): + descr = OptionDescription("root", "", [ + OptionDescription("opt", "", [ + OptionDescription("s1", "", [ + BoolOption("a", "", default=False), + BoolOption("b", "", default=False, properties=('disabled',))]), + OptionDescription("s2", "", [ + BoolOption("a", "", default=False), + BoolOption("b", "", default=False)], properties=('disabled',)), + IntOption("int", "", default=42)]), + IntOption("introot", "", default=42)]) + config = Config(descr) + api = getapi(config) + api.property.read_only() + assert api.option.make_dict() == {"opt.s1.a": False, "opt.int": 42, "introot": 42} + assert api.option('opt').make_dict() == {"s1.a": False, "int": 42} + assert api.option.make_dict(fullpath=True) == {"opt.s1.a": False, "opt.int": 42, "introot": 42} + assert api.option('opt').make_dict(fullpath=True) == {"opt.s1.a": False, "opt.int": 42} + + +def test_find_in_config(): + "finds option in config" + descr = make_description() + conf = Config(descr) + api = getapi(conf) + api.property.read_only() + api.permissive.set(('hidden',)) + ret = api.option.find('dummy') + assert len(ret) == 1 + _is_same_opt(ret[0], api.option.get('gc.dummy')) + # + ret = api.option.find_first('dummy') + _is_same_opt(ret, api.option.get('gc.dummy')) + # + ret = api.option.find('float') + assert len(ret) == 2 + _is_same_opt(ret[0], api.option.get('gc.float')) + _is_same_opt(ret[1], api.option.get('float')) + # + _is_same_opt(api.option.find_first('bool'), api.option.get('gc.gc2.bool')) + #_is_same_opt(conf.find_first(byname='bool', byvalue=True), conf.unwrap_from_path('bool')) + #_is_same_opt(conf.find_first(byname='dummy'), conf.unwrap_from_path('gc.dummy')) + #_is_same_opt(conf.find_first(byname='float'), conf.unwrap_from_path('gc.float')) + #ret = conf.find(bytype=ChoiceOption) + #assert len(ret) == 2 + #_is_same_opt(ret[0], conf.unwrap_from_path('gc.name')) + #_is_same_opt(ret[1], conf.unwrap_from_path('objspace')) + #_is_same_opt(conf.find_first(bytype=ChoiceOption), conf.unwrap_from_path('gc.name')) + #ret = conf.find(byvalue='ref') + #assert len(ret) == 1 + #_is_same_opt(ret[0], conf.unwrap_from_path('gc.name')) + #_is_same_opt(conf.find_first(byvalue='ref'), conf.unwrap_from_path('gc.name')) + #ret = conf.find(byname='prop') + #assert len(ret) == 1 + #_is_same_opt(ret[0], conf.unwrap_from_path('gc.prop')) + #conf.read_write() + #raises(AttributeError, "assert conf.find(byname='prop')") + #ret = conf.find(byname='prop', check_properties=False) + #assert len(ret) == 2 + #_is_same_opt(ret[0], conf.cfgimpl_get_description().impl_get_opt_by_path('gc.gc2.prop')) + #_is_same_opt(ret[1], conf.unwrap_from_path('gc.prop', force_permissive=True)) + #ret = conf.find(byname='prop', force_permissive=True) + #assert len(ret) == 1 + #_is_same_opt(ret[0], conf.unwrap_from_path('gc.prop', force_permissive=True)) + #_is_same_opt(conf.find_first(byname='prop', force_permissive=True), conf.unwrap_from_path('gc.prop', force_permissive=True)) + ##assert conf.find_first(byname='prop') == conf.unwrap_from_path('gc.prop') + ## combinaison of filters + #ret = conf.find(bytype=BoolOption, byname='dummy') + #assert len(ret) == 1 + #_is_same_opt(ret[0], conf.unwrap_from_path('gc.dummy')) + #_is_same_opt(conf.find_first(bytype=BoolOption, byname='dummy'), conf.unwrap_from_path('gc.dummy')) + #ret = conf.find(byvalue=False, byname='dummy') + #assert len(ret) == 1 + #_is_same_opt(ret[0], conf.unwrap_from_path('gc.dummy')) + #_is_same_opt(conf.find_first(byvalue=False, byname='dummy'), conf.unwrap_from_path('gc.dummy')) + ##subconfig + #ret = conf.gc.find(byname='dummy') + #assert len(ret) == 1 + #_is_same_opt(ret[0], conf.unwrap_from_path('gc.dummy')) + #ret = conf.gc.find(byname='float') + #assert len(ret) == 1 + #_is_same_opt(ret[0], conf.unwrap_from_path('gc.float')) + #ret = conf.gc.find(byname='bool') + #assert len(ret) == 1 + #_is_same_opt(ret[0], conf.unwrap_from_path('gc.gc2.bool')) + #_is_same_opt(conf.gc.find_first(byname='bool', byvalue=False), conf.unwrap_from_path('gc.gc2.bool')) + #raises(AttributeError, "assert conf.gc.find_first(byname='bool', byvalue=True)") + #raises(AttributeError, "conf.gc.find(byname='wantref').first()") + #ret = conf.gc.find(byname='prop', check_properties=False) + #assert len(ret) == 2 + #_is_same_opt(ret[0], conf.cfgimpl_get_description().impl_get_opt_by_path('gc.gc2.prop')) + #_is_same_opt(ret[1], conf.unwrap_from_path('gc.prop', force_permissive=True)) + #conf.read_only() + #ret = conf.gc.find(byname='prop') + #assert len(ret) == 1 + #_is_same_opt(ret[0], conf.unwrap_from_path('gc.prop')) + ## not OptionDescription + #raises(AttributeError, "conf.find_first(byname='gc')") + #raises(AttributeError, "conf.gc.find_first(byname='gc2')") + #raises(ValueError, "conf.find(byname='bool', type_='unknown')") + + +#def test_find_multi(): +# b = BoolOption('bool', '', multi=True) +# o = OptionDescription('od', '', [b]) +# conf = Config(o) +# raises(AttributeError, "conf.find(byvalue=True)") +# raises(AttributeError, "conf.find_first(byvalue=True)") +# conf.bool.append(False) +# raises(AttributeError, "conf.find(byvalue=True)") +# raises(AttributeError, "conf.find_first(byvalue=True)") +# conf.bool.append(False) +# raises(AttributeError, "conf.find(byvalue=True)") +# raises(AttributeError, "conf.find_first(byvalue=True)") +# conf.bool.append(True) +# ret = conf.find(byvalue=True) +# assert len(ret) == 1 +# _is_same_opt(ret[0], b) +# _is_same_opt(conf.find_first(byvalue=True), b) + + +def test_does_not_find_in_config(): + descr = make_description() + conf = Config(descr) + api = getapi(conf) + api + raises(AttributeError, "api.option.find('IDontExist')") + + +def test_filename(): + a = FilenameOption('a', '') + o = OptionDescription('o', '', [a]) + cfg = Config(o) + api = getapi(cfg) + api.option('a').value.set('/') + api.option('a').value.set('/tmp') + api.option('a').value.set('/tmp/') + api.option('a').value.set('/tmp/text.txt') + api.option('a').value.set('tmp') + api.option('a').value.set('tmp/') + api.option('a').value.set('tmp/text.txt') + raises(ValueError, "api.option('a').value.set('/tmp/with space.txt')") + raises(ValueError, "api.option('a').value.set('/tmp/with$.txt')") + + +#def test_iter_all(): +# s = StrOption("string", "", default="string") +# s2 = StrOption("string2", "", default="string2") +# descr = OptionDescription("options", "", [s, s2]) +# config = Config(descr) +# assert list(config.iter_all()) == [('string', 'string'), ('string2', 'string2')] +# for i in config.iter_all(): +# #test StopIteration +# break +# +# +#def test_iter_all_force_permissive(): +# s = StrOption("string", "", default="string") +# s2 = StrOption("string2", "", default="string2") +# s3 = StrOption("string3", "", default="string3", properties=('hidden',)) +# descr = OptionDescription("options", "", [s, s2, s3]) +# config = Config(descr) +# api = getapi(config) +# api.property.read_write() +# api.permissive.set(('hidden',)) +# assert list(config.iter_all()) == [('string', 'string'), ('string2', 'string2')] +# assert list(config.iter_all(force_permissive=True)) == [('string', 'string'), +# ('string2', 'string2'), +# ('string3', 'string3')] +# +# +#def test_iter_all_prop(): +# s = StrOption("string", "", default="string", properties=('disabled',)) +# s2 = StrOption("string2", "", default="string2") +# descr = OptionDescription("options", "", [s, s2]) +# config = Config(descr) +# api = getapi(config) +# api.property.read_only() +# 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(): + ChoiceOption('a', '', ('1', '2')) + raises(TypeError, "ChoiceOption('a', '', [1, 2])") + raises(TypeError, "ChoiceOption('a', '', 1)") + raises(ValueError, "ChoiceOption('a', '', (1,), 3)") + FloatOption('a', '') + raises(ValueError, "FloatOption('a', '', 'string')") + UnicodeOption('a', '') + raises(ValueError, "UnicodeOption('a', '', 1)") + u = UnicodeOption('a', '') + SymLinkOption('a', u) + raises(ValueError, "SymLinkOption('a', 'string')") + IPOption('a', '') + raises(ValueError, "IPOption('a', '', 1)") + raises(ValueError, "IPOption('a', '', 'string')") + PortOption('a', '') + 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)") + NetworkOption('a', '') + raises(ValueError, "NetworkOption('a', '', 'string')") + NetmaskOption('a', '') + raises(ValueError, "NetmaskOption('a', '', 'string')") + BroadcastOption('a', '') + raises(ValueError, "BroadcastOption('a', '', 'string')") + DomainnameOption('a', '') + 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')") + raises(ValueError, "DomainnameOption('a', '', 1)") + # + ChoiceOption('a', '', (1,), multi=True, default_multi=1) + raises(ValueError, "ChoiceOption('a', '', (1,), default_multi=1)") + raises(ValueError, "ChoiceOption('a', '', (1,), multi=True, default=[1,], default_multi=2)") + raises(ValueError, "FloatOption('a', '', multi=True, default_multi='string')") + raises(ValueError, "UnicodeOption('a', '', multi=True, default_multi=1)") + raises(ValueError, "IPOption('a', '', multi=True, default_multi=1)") + raises(ValueError, "IPOption('a', '', multi=True, default_multi='string')") + raises(ValueError, "PortOption('a', '', multi=True, default_multi='string')") + raises(ValueError, "PortOption('a', '', multi=True, default_multi='11:12:13', allow_range=True)") + raises(ValueError, "PortOption('a', '', multi=True, default_multi=11111111111111111111)") + raises(ValueError, "NetworkOption('a', '', multi=True, default_multi='string')") + raises(ValueError, "NetmaskOption('a', '', multi=True, default_multi='string')") + raises(ValueError, "BroadcastOption('a', '', multi=True, default_multi='string')") + raises(ValueError, "DomainnameOption('a', '', multi=True, default_multi='string')") + raises(ValueError, "DomainnameOption('a', '', multi=True, default_multi=1)") diff --git a/test/new_api/test_config_domain.py b/test/new_api/test_config_domain.py new file mode 100644 index 0000000..4408858 --- /dev/null +++ b/test/new_api/test_config_domain.py @@ -0,0 +1,178 @@ +from .autopath import do_autopath +do_autopath() + +import warnings, sys +from py.test import raises + +from tiramisu.config import Config +from tiramisu.option import DomainnameOption, EmailOption, URLOption, OptionDescription +from tiramisu.error import ValueWarning +from tiramisu.i18n import _ +from tiramisu import getapi + + +def test_domainname(): + d = DomainnameOption('d', '') + f = DomainnameOption('f', '', allow_without_dot=True) + g = DomainnameOption('g', '', allow_ip=True) + od = OptionDescription('a', '', [d, f, g]) + c = Config(od) + api = getapi(c) + api.property.read_write() + api.option('d').value.set('toto.com') + raises(ValueError, "api.option('d').value.set('toto')") + api.option('d').value.set('toto3.com') + raises(ValueError, "api.option('d').value.set('toto_super.com')") + api.option('d').value.set('toto-.com') + raises(ValueError, "api.option('d').value.set('toto..com')") + # + api.option('f').value.set('toto.com') + api.option('f').value.set('toto') + api.option('f').value.set('domainnametoolongthathavemorethanmaximumsizeforatruedomainnamea') + raises(ValueError, "api.option('f').value.set('domainnametoolongthathavemorethanmaximumsizeforatruedomainnamean')") + api.option('f').value.set('domainnametoolongthathavemorethanmaximumsizeforatruedomainnamea.nd') + api.option('f').value.set('domainnametoolongthathavemorethanmaximumsizeforatruedomainnamea.nditsnoteasytogeneratesolongdomainnamewithoutrepeatdomainnameto.olongthathavemorethanmaximumsizeforatruedomainnameanditsnoteas.ytogeneratesolongdomainnamewithoutrepeatbutimnotabletodoitnowie') + raises(ValueError, "api.option('d').value.set('domainnametoolongthathavemorethanmaximumsizeforatruedomainnamea.nditsnoteasytogeneratesolongdomainnamewithoutrepeatdomainnameto.olongthathavemorethanmaximumsizeforatruedomainnameanditsnoteas.ytogeneratesolongdomainnamewithoutrepeatbutimnotabletodoitnowien')") + api.option('f').value.set('d') + api.option('f').value.set('d.t') + # + raises(ValueError, "api.option('f').value.set('192.168.1.1')") + api.option('g').value.set('toto.com') + api.option('g').value.set('192.168.1.0') + api.option('g').value.set('192.168.1.29') + + +def test_domainname_upper(): + d = DomainnameOption('d', '') + od = OptionDescription('a', '', [d]) + c = Config(od) + api = getapi(c) + api.property.read_write() + api.option('d').value.set('toto.com') + msg = _('some characters are uppercase') + has_error = False + try: + api.option('d').value.set('TOTO.COM') + except ValueError as err: + assert msg in str(err) + has_error = True + assert has_error is True + has_error = False + try: + api.option('d').value.set('toTo.com') + except ValueError as err: + assert msg in str(err) + has_error = True + assert has_error is True + + +def test_domainname_warning(): + d = DomainnameOption('d', '', warnings_only=True) + f = DomainnameOption('f', '', allow_without_dot=True, warnings_only=True) + g = DomainnameOption('g', '', allow_ip=True, warnings_only=True) + od = OptionDescription('a', '', [d, f, g]) + warnings.simplefilter("always", ValueWarning) + c = Config(od) + api = getapi(c) + api.property.read_write() + api.option('d').value.set('toto.com') + raises(ValueError, "api.option('d').value.set('toto')") + api.option('d').value.set('toto3.com') + with warnings.catch_warnings(record=True) as w: + api.option('d').value.set('toto_super.com') + assert len(w) == 1 + api.option('d').value.set('toto-.com') + raises(ValueError, "api.option('d').value.set('toto..com')") + # + api.option('f').value.set('toto.com') + api.option('f').value.set('toto') + api.option('f').value.set('domainnametoolongthathavemorethanmaximumsizeforatruedomainnamea') + raises(ValueError, "api.option('f').value.set('domainnametoolongthathavemorethanmaximumsizeforatruedomainnamean')") + api.option('f').value.set('domainnametoolongthathavemorethanmaximumsizeforatruedomainnamea.nd') + api.option('f').value.set('domainnametoolongthathavemorethanmaximumsizeforatruedomainnamea.nditsnoteasytogeneratesolongdomainnamewithoutrepeatdomainnameto.olongthathavemorethanmaximumsizeforatruedomainnameanditsnoteas.ytogeneratesolongdomainnamewithoutrepeatbutimnotabletodoitnowie') + raises(ValueError, "api.option('f').value.set('domainnametoolongthathavemorethanmaximumsizeforatruedomainname.nditsnoteasytogeneratesolongdomainnamewithoutrepeatdomainnamet.olongthathavemorethanmaximumsizeforatruedomainnameanditsnotea.ytogeneratesolongdomainnamewithoutrepeatbutimnotabletodoitnowie.xxxx')") + api.option('f').value.set('d') + api.option('f').value.set('d.t') + # + raises(ValueError, "api.option('f').value.set('192.168.1.1')") + api.option('g').value.set('toto.com') + api.option('g').value.set('192.168.1.0') + api.option('g').value.set('192.168.1.29') + + +def test_special_domain_name(): + """domain name option that starts with a number or not + """ + d = DomainnameOption('d', '') + e = DomainnameOption('e', '', type_='netbios') + od = OptionDescription('a', '', [d, e]) + c = Config(od) + api = getapi(c) + api.property.read_write() + api.option('d').value.set('1toto.com') + api.option('d').value.set('123toto.com') + api.option('e').value.set('toto') + api.option('e').value.set('1toto') + + +def test_domainname_netbios(): + d = DomainnameOption('d', '', type_='netbios') + e = DomainnameOption('e', '', "toto", type_='netbios') + od = OptionDescription('a', '', [d, e]) + c = Config(od) + api = getapi(c) + api.property.read_write() + raises(ValueError, "api.option('d').value.set('toto.com')") + api.option('d').value.set('toto') + raises(ValueError, "api.option('d').value.set('domainnametoolong')") + + +def test_domainname_hostname(): + d = DomainnameOption('d', '', type_='hostname') + e = DomainnameOption('e', '', "toto", type_='hostname') + od = OptionDescription('a', '', [d, e]) + c = Config(od) + api = getapi(c) + api.property.read_write() + raises(ValueError, "api.option('d').value.set('toto.com')") + api.option('d').value.set('toto') + api.option('d').value.set('domainnametoolong') + + +def test_email(): + e = EmailOption('e', '') + od = OptionDescription('a', '', [e]) + c = Config(od) + api = getapi(c) + api.property.read_write() + api.option('e').value.set('foo-bar.baz@example.com') + api.option('e').value.set('root@foo.com') + api.option('e').value.set('root@domain') + raises(ValueError, "api.option('e').value.set(1)") + raises(ValueError, "api.option('e').value.set('root')") + raises(ValueError, "api.option('e').value.set('root[]@domain')") + + +def test_url(): + u = URLOption('u', '') + od = OptionDescription('a', '', [u]) + c = Config(od) + api = getapi(c) + api.property.read_write() + api.option('u').value.set('http://foo.com') + api.option('u').value.set('https://foo.com') + api.option('u').value.set('https://foo.com/') + raises(ValueError, "api.option('u').value.set(1)") + raises(ValueError, "api.option('u').value.set('ftp://foo.com')") + raises(ValueError, "api.option('u').value.set('foo.com')") + raises(ValueError, "api.option('u').value.set(':/foo.com')") + raises(ValueError, "api.option('u').value.set('foo.com/http://')") + api.option('u').value.set('https://foo.com/index.html') + api.option('u').value.set('https://foo.com/index.html?var=value&var2=val2') + raises(ValueError, "api.option('u').value.set('https://foo.com/index\\n.html')") + api.option('u').value.set('https://foo.com:8443') + api.option('u').value.set('https://foo.com:8443/') + api.option('u').value.set('https://foo.com:8443/index.html') + raises(ValueError, "api.option('u').value.set('https://foo.com:84438989')") + api.option('u').value.set('https://foo.com:8443/INDEX') + raises(ValueError, "api.option('u').value.set('https://FOO.COM:8443')") diff --git a/test/new_api/test_config_ip.py b/test/new_api/test_config_ip.py new file mode 100644 index 0000000..6259d54 --- /dev/null +++ b/test/new_api/test_config_ip.py @@ -0,0 +1,254 @@ +from .autopath import do_autopath +do_autopath() + +import warnings +from py.test import raises +from tiramisu import Config ,IPOption, NetworkOption, NetmaskOption, \ + PortOption, BroadcastOption, OptionDescription, getapi +from tiramisu.error import ValueWarning + + +def test_ip(): + a = IPOption('a', '') + b = IPOption('b', '', private_only=True) + d = IPOption('d', '', warnings_only=True, private_only=True) + warnings.simplefilter("always", ValueWarning) + od = OptionDescription('od', '', [a, b, d]) + c = Config(od) + api = getapi(c) + api.option('a').value.set('192.168.1.1') + api.option('a').value.set('192.168.1.0') + api.option('a').value.set('88.88.88.88') + api.option('a').value.set('0.0.0.0') + raises(ValueError, "api.option('a').value.set('255.255.255.0')") + api.option('b').value.set('192.168.1.1') + api.option('b').value.set('192.168.1.0') + raises(ValueError, "api.option('b').value.set('88.88.88.88')") + api.option('b').value.set('0.0.0.0') + raises(ValueError, "api.option('b').value.set('255.255.255.0')") + raises(ValueError, "api.option('a').value.set('333.0.1.20')") + + raises(ValueError, "IPOption('a', 'ip', default='192.000.023.01')") + with warnings.catch_warnings(record=True) as w: + api.option('d').value.set('88.88.88.88') + assert len(w) == 1 + + +def test_ip_default(): + a = IPOption('a', '', '88.88.88.88') + od = OptionDescription('od', '', [a]) + c = Config(od) + api = getapi(c) + api.option('a').value.get() == '88.88.88.88' + + +def test_ip_reserved(): + a = IPOption('a', '') + b = IPOption('b', '', allow_reserved=True) + c = IPOption('c', '', warnings_only=True) + od = OptionDescription('od', '', [a, b, c]) + warnings.simplefilter("always", ValueWarning) + cfg = Config(od) + api = getapi(cfg) + raises(ValueError, "api.option('a').value.set('226.94.1.1')") + api.option('b').value.set('226.94.1.1') + with warnings.catch_warnings(record=True) as w: + api.option('c').value.set('226.94.1.1') + assert len(w) == 1 + + +def test_network(): + a = NetworkOption('a', '') + b = NetworkOption('b', '', warnings_only=True) + od = OptionDescription('od', '', [a, b]) + warnings.simplefilter("always", ValueWarning) + c = Config(od) + api = getapi(c) + api.option('a').value.set('192.168.1.1') + api.option('a').value.set('192.168.1.0') + api.option('a').value.set('88.88.88.88') + api.option('a').value.set('0.0.0.0') + raises(ValueError, "api.option('a').value.set(1)") + raises(ValueError, "api.option('a').value.set('1.1.1.1.1')") + raises(ValueError, "api.option('a').value.set('255.255.255.0')") + raises(ValueError, "api.option('a').value.set('192.168.001.0')") + raises(ValueError, "api.option('a').value.set('333.168.1.1')") + with warnings.catch_warnings(record=True) as w: + api.option('b').value.set('255.255.255.0') + assert len(w) == 1 + + +def test_network_invalid(): + raises(ValueError, "NetworkOption('a', '', default='toto')") + + +def test_netmask(): + a = NetmaskOption('a', '') + od = OptionDescription('od', '', [a]) + c = Config(od) + api = getapi(c) + raises(ValueError, "api.option('a').value.set('192.168.1.1.1')") + raises(ValueError, "api.option('a').value.set('192.168.1.1')") + raises(ValueError, "api.option('a').value.set('192.168.1.0')") + raises(ValueError, "api.option('a').value.set('88.88.88.88')") + raises(ValueError, "api.option('a').value.set('255.255.255.000')") + raises(ValueError, "api.option('a').value.set(2)") + api.option('a').value.set('0.0.0.0') + api.option('a').value.set('255.255.255.0') + + +def test_broadcast(): + a = BroadcastOption('a', '') + od = OptionDescription('od', '', [a]) + c = Config(od) + api = getapi(c) + raises(ValueError, "api.option('a').value.set('192.168.1.255.1')") + raises(ValueError, "api.option('a').value.set('192.168.001.255')") + raises(ValueError, "api.option('a').value.set('192.168.0.300')") + raises(ValueError, "api.option('a').value.set(1)") + raises(ValueError, "api.option('a').value.set(2)") + api.option('a').value.set('0.0.0.0') + api.option('a').value.set('255.255.255.0') + + +def test_port(): + a = PortOption('a', '') + b = PortOption('b', '', allow_zero=True) + c = PortOption('c', '', allow_zero=True, allow_registred=False) + d = PortOption('d', '', allow_zero=True, allow_wellknown=False, allow_registred=False) + e = PortOption('e', '', allow_zero=True, allow_private=True) + f = PortOption('f', '', allow_private=True) + od = OptionDescription('od', '', [a, b, c, d, e, f]) + c = Config(od) + api = getapi(c) + raises(ValueError, "api.option('a').value.set(0)") + api.option('a').value.set(1) + api.option('a').value.set(1023) + api.option('a').value.set(1024) + api.option('a').value.set(49151) + raises(ValueError, "api.option('a').value.set(49152)") + raises(ValueError, "api.option('a').value.set(65535)") + raises(ValueError, "api.option('a').value.set(65536)") + + api.option('b').value.set(0) + api.option('b').value.set(1) + api.option('b').value.set(1023) + api.option('b').value.set(1024) + api.option('b').value.set(49151) + raises(ValueError, "api.option('b').value.set(49152)") + raises(ValueError, "api.option('b').value.set(65535)") + raises(ValueError, "api.option('b').value.set(65536)") + + api.option('c').value.set(0) + api.option('c').value.set(1) + api.option('c').value.set(1023) + raises(ValueError, "api.option('c').value.set(1024)") + raises(ValueError, "api.option('c').value.set(49151)") + raises(ValueError, "api.option('c').value.set(49152)") + raises(ValueError, "api.option('c').value.set(65535)") + raises(ValueError, "api.option('c').value.set(65536)") + + api.option('d').value.set(0) + raises(ValueError, "api.option('d').value.set(1)") + raises(ValueError, "api.option('d').value.set(1023)") + raises(ValueError, "api.option('d').value.set(1024)") + raises(ValueError, "api.option('d').value.set(49151)") + raises(ValueError, "api.option('d').value.set(49152)") + raises(ValueError, "api.option('d').value.set(65535)") + raises(ValueError, "api.option('d').value.set(65536)") + + api.option('e').value.set(0) + api.option('e').value.set(1) + api.option('e').value.set(1023) + api.option('e').value.set(1024) + api.option('e').value.set(49151) + api.option('e').value.set(49152) + api.option('e').value.set(65535) + + raises(ValueError, "api.option('f').value.set(0)") + api.option('f').value.set(1) + api.option('f').value.set(1023) + api.option('f').value.set(1024) + api.option('f').value.set(49151) + api.option('f').value.set(49152) + api.option('f').value.set(65535) + raises(ValueError, "api.option('f').value.set(65536)") + + +def test_port_range(): + a = PortOption('a', '', allow_range=True) + b = PortOption('b', '', allow_range=True, allow_zero=True) + c = PortOption('c', '', allow_range=True, allow_zero=True, allow_registred=False) + d = PortOption('d', '', allow_range=True, allow_zero=True, allow_wellknown=False, allow_registred=False) + e = PortOption('e', '', allow_range=True, allow_zero=True, allow_private=True) + f = PortOption('f', '', allow_range=True, allow_private=True) + od = OptionDescription('od', '', [a, b, c, d, e, f]) + c = Config(od) + api = getapi(c) + raises(ValueError, "api.option('a').value.set(0)") + api.option('a').value.set(1) + api.option('a').value.set(1023) + api.option('a').value.set(1024) + api.option('a').value.set(49151) + raises(ValueError, "api.option('a').value.set(49152)") + raises(ValueError, "api.option('a').value.set(65535)") + raises(ValueError, "api.option('a').value.set(65536)") + api.option('a').value.set('1:49151') + raises(ValueError, "api.option('a').value.set('0:49151')") + raises(ValueError, "api.option('a').value.set('1:49152')") + + api.option('b').value.set(0) + api.option('b').value.set(1) + api.option('b').value.set(1023) + api.option('b').value.set(1024) + api.option('b').value.set(49151) + raises(ValueError, "api.option('b').value.set(49152)") + raises(ValueError, "api.option('b').value.set(65535)") + raises(ValueError, "api.option('b').value.set(65536)") + api.option('b').value.set('0:49151') + raises(ValueError, "api.option('b').value.set('0:49152')") + + api.option('c').value.set(0) + api.option('c').value.set(1) + api.option('c').value.set(1023) + raises(ValueError, "api.option('c').value.set(1024)") + raises(ValueError, "api.option('c').value.set(49151)") + raises(ValueError, "api.option('c').value.set(49152)") + raises(ValueError, "api.option('c').value.set(65535)") + raises(ValueError, "api.option('c').value.set(65536)") + api.option('c').value.set('0:1023') + raises(ValueError, "api.option('c').value.set('0:1024')") + + api.option('d').value.set(0) + raises(ValueError, "api.option('d').value.set(1)") + raises(ValueError, "api.option('d').value.set(1023)") + raises(ValueError, "api.option('d').value.set(1024)") + raises(ValueError, "api.option('d').value.set(49151)") + raises(ValueError, "api.option('d').value.set(49152)") + raises(ValueError, "api.option('d').value.set(65535)") + raises(ValueError, "api.option('d').value.set(65536)") + raises(ValueError, "api.option('d').value.set('0:0')") + raises(ValueError, "api.option('d').value.set('0:1')") + + api.option('e').value.set(0) + api.option('e').value.set(1) + api.option('e').value.set(1023) + api.option('e').value.set(1024) + api.option('e').value.set(49151) + api.option('e').value.set(49152) + api.option('e').value.set(65535) + api.option('e').value.set('0:65535') + raises(ValueError, "api.option('e').value.set('0:65536')") + + raises(ValueError, "api.option('f').value.set(0)") + api.option('f').value.set(1) + api.option('f').value.set(1023) + api.option('f').value.set(1024) + api.option('f').value.set(49151) + api.option('f').value.set(49152) + api.option('f').value.set(65535) + raises(ValueError, "api.option('f').value.set(65536)") + api.option('f').value.set('1:65535') + api.option('f').value.set('3:4') + raises(ValueError, "api.option('f').value.set('0:65535')") + raises(ValueError, "api.option('f').value.set('4:3')") diff --git a/test/new_api/test_dyn_optiondescription.py b/test/new_api/test_dyn_optiondescription.py new file mode 100644 index 0000000..948c7f5 --- /dev/null +++ b/test/new_api/test_dyn_optiondescription.py @@ -0,0 +1,1368 @@ +# coding: utf-8 +from .autopath import do_autopath +do_autopath() + +from tiramisu.setting import groups, owners +from tiramisu import BoolOption, StrOption, ChoiceOption, IPOption, \ + NetworkOption, NetmaskOption, IntOption, FloatOption, \ + UnicodeOption, PortOption, BroadcastOption, DomainnameOption, \ + EmailOption, URLOption, UsernameOption, FilenameOption, SymLinkOption, \ + OptionDescription, DynOptionDescription, DynSymLinkOption, submulti, MasterSlaves, \ + Config, getapi +from tiramisu.error import PropertiesOptionError, ConfigError, ConflictError +from tiramisu.storage import delete_session +#from .test_state import _diff_opts, _diff_conf + +from py.test import raises + + +def return_true(value, param=None, suffix=None): + if value == 'val' and param in [None, 'yes']: + return + raise ValueError('no value') + + +def return_dynval(value='val', suffix=None): + return value + + +def return_list2(suffix): + return [str(suffix), 'val2'] + + +def return_list(val=None, suffix=None): + if val: + return val + else: + return ['val1', 'val2'] + + +def return_same_list(): + return ['val1', 'val1'] + + +def return_wrong_list(): + return ['---', ' '] + + +def return_raise(): + raise Exception('error') + + +#def test_build_dyndescription(): +# st = StrOption('st', '') +# dod = DynOptionDescription('dod', '', [st], callback=return_list) +# od = OptionDescription('od', '', [dod]) +# cfg = Config(od) +# assert str(cfg) == """[dodval1] +#[dodval2]""" +# assert str(cfg.dodval1) == "stval1 = None" +# assert str(cfg.dodval2) == "stval2 = None" + + +#def test_build_dyndescription_raise(): +# st = StrOption('st', '') +# dod = DynOptionDescription('dod', '', [st], callback=return_raise) +# od = OptionDescription('od', '', [dod]) +# cfg = Config(od) +# raises(ConfigError, "str(cfg)") + + +#def test_subpath_dyndescription(): +# st = StrOption('st', '') +# dod = DynOptionDescription('dod', '', [st], callback=return_list) +# od = OptionDescription('od', '', [dod]) +# od2 = OptionDescription('od', '', [od]) +# api = getapi(Config(od2)) +# assert str(cfg) == "[od]" +# assert str(cfg.od) == """[dodval1] +#[dodval2]""" +# assert str(cfg.od.dodval1) == "stval1 = None" +# assert str(cfg.od.dodval2) == "stval2 = None" + + +def test_list_dyndescription(): + st = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st], callback=return_list) + od = OptionDescription('od', '', [dod]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + assert api.option('od.dodval1.stval1').value.get() is None + assert api.option('od.dodval2.stval2').value.get() is None + + +def test_unknown_dyndescription(): + st = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st], callback=return_list) + od = OptionDescription('od', '', [dod]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + raises(AttributeError, "api.option('od.dodval3').value.get()") + raises(AttributeError, "api.option('od.dodval1.novalue').value.get()") + + +#def test_getdoc_dyndescription(): +# st = StrOption('st', 'doc1') +# dod = DynOptionDescription('dod', 'doc2', [st], callback=return_list) +# od = OptionDescription('od', '', [dod]) +# od2 = OptionDescription('od', '', [od]) +# api = getapi(Config(od2)) +# stval1 = cfg.unwrap_from_path('od.dodval1.stval1') +# stval2 = cfg.unwrap_from_path('od.dodval2.stval2') +# dodval1 = cfg.unwrap_from_path('od.dodval1') +# dodval2 = cfg.unwrap_from_path('od.dodval2') +# assert stval1.impl_getname() == 'stval1' +# assert stval2.impl_getname() == 'stval2' +# assert dodval1.impl_getname() == 'dodval1' +# assert dodval2.impl_getname() == 'dodval2' +# assert stval1.impl_getdoc() == 'doc1' +# assert stval2.impl_getdoc() == 'doc1' +# assert dodval1.impl_getdoc() == 'doc2' +# assert dodval2.impl_getdoc() == 'doc2' + + +#def test_getpaths_dyndescription(): +# st = StrOption('st', '') +# dod = DynOptionDescription('dod', '', [st], callback=return_list) +# od = OptionDescription('od', '', [dod]) +# od2 = OptionDescription('od', '', [od]) +# api = getapi(Config(od2)) +# assert cfg.cfgimpl_get_description().impl_getpaths() == ['od.dodval1.stval1', 'od.dodval2.stval2'] +# assert cfg.cfgimpl_get_description().impl_getpaths(include_groups=True) == ['od', 'od.dodval1', 'od.dodval1.stval1', 'od.dodval2', 'od.dodval2.stval2'] + + +def test_mod_dyndescription(): + st = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st], callback=return_list) + od = OptionDescription('od', '', [dod]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + owner = api.owner.get() + # + assert api.option('od.dodval1.stval1').value.get() is None + assert api.option('od.dodval2.stval2').value.get() is None + assert api.option('od.dodval1.stval1').owner.isdefault() + assert api.option('od.dodval2.stval2').owner.isdefault() + # + api.option('od.dodval1.stval1').value.set('yes') + assert api.option('od.dodval1.stval1').value.get() == 'yes' + assert api.option('od.dodval2.stval2').value.get() is None + assert api.option('od.dodval1.stval1').owner.get() == owner + assert api.option('od.dodval2.stval2').owner.isdefault() + # + api.option('od.dodval2.stval2').value.set('no') + assert api.option('od.dodval1.stval1').value.get() == 'yes' + assert api.option('od.dodval2.stval2').value.get() == 'no' + assert api.option('od.dodval1.stval1').owner.get() == owner + assert api.option('od.dodval2.stval2').owner.get() == owner + + +def test_del_dyndescription(): + st = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st], callback=return_list) + od = OptionDescription('od', '', [dod]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + owner = api.owner.get() + assert api.option('od.dodval1.stval1').value.get() is None + assert api.option('od.dodval2.stval2').value.get() is None + api.option('od.dodval1.stval1').value.set('yes') + assert api.option('od.dodval1.stval1').owner.get() == owner + api.option('od.dodval1.stval1').value.reset() + assert api.option('od.dodval1.stval1').owner.isdefault() + + +def test_multi_dyndescription(): + st = StrOption('st', '', multi=True) + dod = DynOptionDescription('dod', '', [st], callback=return_list) + od = OptionDescription('od', '', [dod]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + owner = api.owner.get() + assert api.option('od.dodval1.stval1').value.get() == [] + assert api.option('od.dodval2.stval2').value.get() == [] + assert api.option('od.dodval1.stval1').owner.isdefault() + assert api.option('od.dodval2.stval2').owner.isdefault() + api.option('od.dodval1.stval1').value.set(['yes']) + assert api.option('od.dodval1.stval1').value.get() == ['yes'] + assert api.option('od.dodval2.stval2').value.get() == [] + assert api.option('od.dodval1.stval1').owner.get() == owner + assert api.option('od.dodval2.stval2').owner.isdefault() + api.option('od.dodval2.stval2').value.set(['no']) + assert api.option('od.dodval1.stval1').value.get() == ['yes'] + assert api.option('od.dodval2.stval2').value.get() == ['no'] + #assert cfg.getowner(st) == owners.default + assert api.option('od.dodval1.stval1').owner.get() == owner + assert api.option('od.dodval2.stval2').owner.get() == owner + api.option('od.dodval1.stval1').value.set(['yes', 'yes']) + assert api.option('od.dodval1.stval1').value.get() == ['yes', 'yes'] + api.option('od.dodval1.stval1').value.set(['yes']) + assert api.option('od.dodval1.stval1').value.get() == ['yes'] + + +def test_prop_dyndescription(): + st = StrOption('st', '', properties=('test',)) + dod = DynOptionDescription('dod', '', [st], callback=return_list) + od = OptionDescription('od', '', [dod]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + assert set(api.option('od.dodval1.stval1').property.get()) == set(['test']) + assert set(api.option('od.dodval2.stval2').property.get()) == set(['test']) + api.option('od.dodval2.stval2').property.add('test2') + assert set(api.option('od.dodval1.stval1').property.get()) == set(['test']) + assert set(api.option('od.dodval2.stval2').property.get()) == set(['test', 'test2']) + api.option('od.dodval1.stval1').property.pop('test') + assert set(api.option('od.dodval1.stval1').property.get()) == set([]) + # + assert set(api.option('od.dodval1').property.get()) == set([]) + assert set(api.option('od.dodval2').property.get()) == set([]) + api.option('od.dodval1').property.add('test1') + assert set(api.option('od.dodval1').property.get()) == set(['test1']) + assert set(api.option('od.dodval2').property.get()) == set([]) + api.option('od.dodval1').property.pop('test1') + assert set(api.option('od.dodval1').property.get()) == set([]) + assert set(api.option('od.dodval2').property.get()) == set([]) + + +def test_prop_dyndescription_force_store_value(): + st = StrOption('st', '', properties=('force_store_value',)) + dod = DynOptionDescription('dod', '', [st], callback=return_list) + od = OptionDescription('od', '', [dod]) + od2 = OptionDescription('od', '', [od]) + raises(ConfigError, "Config(od2)") + + +def test_callback_dyndescription(): + st = StrOption('st', '', callback=return_dynval) + dod = DynOptionDescription('dod', '', [st], callback=return_list) + od = OptionDescription('od', '', [dod]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + owner = api.owner.get() + assert api.option('od.dodval1.stval1').value.get() == 'val' + assert api.option('od.dodval2.stval2').value.get() == 'val' + assert api.option('od.dodval1.stval1').owner.isdefault() + assert api.option('od.dodval2.stval2').owner.isdefault() + api.option('od.dodval1.stval1').value.set('val2') + assert api.option('od.dodval1.stval1').value.get() == 'val2' + assert api.option('od.dodval2.stval2').value.get() == 'val' + assert api.option('od.dodval1.stval1').owner.get() == owner + assert api.option('od.dodval2.stval2').owner.isdefault() + api.option('od.dodval1.stval1').value.reset() + assert api.option('od.dodval1.stval1').value.get() == 'val' + assert api.option('od.dodval2.stval2').value.get() == 'val' + assert api.option('od.dodval1.stval1').owner.isdefault() + assert api.option('od.dodval2.stval2').owner.isdefault() + + +def test_callback_list_dyndescription(): + st = StrOption('st', '', callback=return_list2, multi=True) + dod = DynOptionDescription('dod', '', [st], callback=return_list) + od = OptionDescription('od', '', [dod]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + owner = api.owner.get() + assert api.option('od.dodval1.stval1').value.get() == ['val1', 'val2'] + assert api.option('od.dodval2.stval2').value.get() == ['val2', 'val2'] + assert api.option('od.dodval1.stval1').owner.isdefault() + assert api.option('od.dodval2.stval2').owner.isdefault() + api.option('od.dodval1.stval1').value.set(['val3', 'val2']) + assert api.option('od.dodval1.stval1').value.get() == ['val3', 'val2'] + assert api.option('od.dodval2.stval2').value.get() == ['val2', 'val2'] + assert api.option('od.dodval1.stval1').owner.get() == owner + assert api.option('od.dodval2.stval2').owner.isdefault() + + +def test_mandatory_dyndescription(): + st = StrOption('st', '', properties=('mandatory',)) + dod = DynOptionDescription('dod', '', [st], callback=return_list) + od = OptionDescription('od', '', [dod]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + api.property.read_only() + raises(PropertiesOptionError, "api.option('od.dodval1.stval1').value.get()") + raises(PropertiesOptionError, "api.option('od.dodval2.stval2').value.get()") + api.property.read_write() + api.option('od.dodval1.stval1').value.set('val') + api.property.read_only() + assert api.option('od.dodval1.stval1').value.get() == 'val' + raises(PropertiesOptionError, "api.option('od.dodval2.stval2').value.get()") + api.property.read_write() + api.option('od.dodval1.stval1').value.reset() + api.property.read_only() + raises(PropertiesOptionError, "api.option('od.dodval1.stval1').value.get()") + assert list(api.value.mandatory_warnings()) == ['od.dodval1.stval1', 'od.dodval2.stval2'] + + +#def test_build_dyndescription_context(): +# val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) +# st = StrOption('st', '') +# dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)}) +# od = OptionDescription('od', '', [dod, val1]) +# cfg = Config(od) +# cfg._impl_test = True +# assert str(cfg) == """[dodval1] +#[dodval2] +#val1 = ['val1', 'val2']""" +# assert str(cfg.dodval1) == "stval1 = None" +# assert str(cfg.dodval2) == "stval2 = None" +# cfg.unwrap_from_path('dodval2') + + +#def test_subpath_dyndescription_context(): +# val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) +# st = StrOption('st', '') +# dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)}) +# od = OptionDescription('od', '', [dod, val1]) +# od2 = OptionDescription('od', '', [od]) +# api = getapi(Config(od2)) +# assert str(cfg) == "[od]" +# assert str(cfg.od) == """[dodval1] +#[dodval2] +#val1 = ['val1', 'val2']""" +# assert str(cfg.od.dodval1) == "stval1 = None" +# assert str(cfg.od.dodval2) == "stval2 = None" + + +def test_list_dyndescription_context(): + val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) + st = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)}) + od = OptionDescription('od', '', [dod, val1]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + assert api.option('od.dodval1.stval1').value.get() is None + assert api.option('od.dodval2.stval2').value.get() is None + raises(AttributeError, "api.option('od.dodval3').value.get()") + + +def test_mod_dyndescription_context(): + val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) + st = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)}) + od = OptionDescription('od', '', [dod, val1]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + owner = api.owner.get() + assert api.option('od.dodval1.stval1').value.get() is None + assert api.option('od.dodval2.stval2').value.get() is None + assert api.option('od.dodval1.stval1').owner.isdefault() + assert api.option('od.dodval2.stval2').owner.isdefault() + api.option('od.dodval1.stval1').value.set('yes') + assert api.option('od.dodval1.stval1').value.get() == 'yes' + assert api.option('od.dodval2.stval2').value.get() is None + assert api.option('od.dodval1.stval1').owner.get() == owner + assert api.option('od.dodval2.stval2').owner.isdefault() + api.option('od.dodval2.stval2').value.set('no') + assert api.option('od.dodval1.stval1').value.get() == 'yes' + assert api.option('od.dodval2.stval2').value.get() == 'no' + #assert cfg.getowner(st) == owners.default + assert api.option('od.dodval1.stval1').owner.get() == owner + assert api.option('od.dodval2.stval2').owner.get() == owner + + +def test_del_dyndescription_context(): + val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) + st = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)}) + od = OptionDescription('od', '', [dod, val1]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + owner = api.owner.get() + assert api.option('od.dodval1.stval1').value.get() is None + assert api.option('od.dodval2.stval2').value.get() is None + api.option('od.dodval1.stval1').value.set('yes') + assert api.option('od.dodval1.stval1').owner.get() == owner + api.option('od.dodval1.stval1').value.reset() + assert api.option('od.dodval1.stval1').owner.isdefault() + + +def test_multi_dyndescription_context(): + val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) + st = StrOption('st', '', multi=True) + dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)}) + od = OptionDescription('od', '', [dod, val1]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + owner = api.owner.get() + assert api.option('od.dodval1.stval1').value.get() == [] + assert api.option('od.dodval2.stval2').value.get() == [] + assert api.option('od.dodval1.stval1').owner.isdefault() + assert api.option('od.dodval2.stval2').owner.isdefault() + api.option('od.dodval1.stval1').value.set(['yes']) + assert api.option('od.dodval1.stval1').value.get() == ['yes'] + assert api.option('od.dodval2.stval2').value.get() == [] + assert api.option('od.dodval1.stval1').owner.get() == owner + assert api.option('od.dodval2.stval2').owner.isdefault() + api.option('od.dodval2.stval2').value.set(['no']) + assert api.option('od.dodval1.stval1').value.get() == ['yes'] + assert api.option('od.dodval2.stval2').value.get() == ['no'] + #assert cfg.getowner(st) == owners.default + assert api.option('od.dodval1.stval1').owner.get() == owner + assert api.option('od.dodval2.stval2').owner.get() == owner + api.option('od.dodval1.stval1').value.set(['yes', 'yes']) + assert api.option('od.dodval1.stval1').value.get() == ['yes', 'yes'] + api.option('od.dodval1.stval1').value.set(['yes']) + assert api.option('od.dodval1.stval1').value.get() == ['yes'] + + +def test_prop_dyndescription_context(): + val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) + st = StrOption('st', '', properties=('test',)) + dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)}) + od = OptionDescription('od', '', [dod, val1]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + assert set(api.option('od.dodval1.stval1').property.get()) == set(['test']) + assert set(api.option('od.dodval2.stval2').property.get()) == set(['test']) + api.option('od.dodval2.stval2').property.add('test2') + assert set(api.option('od.dodval1.stval1').property.get()) == set(['test']) + assert set(api.option('od.dodval2.stval2').property.get()) == set(['test', 'test2']) + api.option('od.dodval1.stval1').property.pop('test') + assert set(api.option('od.dodval1.stval1').property.get()) == set([]) + assert set(api.option('od.dodval2.stval2').property.get()) == set(['test', 'test2']) + + +def test_callback_dyndescription_context(): + val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) + st = StrOption('st', '', callback=return_dynval) + dod = DynOptionDescription('dod', '', [st], callback=return_list) + od = OptionDescription('od', '', [dod, val1]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + owner = api.owner.get() + assert api.option('od.dodval1.stval1').value.get() == 'val' + assert api.option('od.dodval2.stval2').value.get() == 'val' + assert api.option('od.dodval1.stval1').owner.isdefault() + assert api.option('od.dodval2.stval2').owner.isdefault() + api.option('od.dodval1.stval1').value.set('val2') + assert api.option('od.dodval1.stval1').value.get() == 'val2' + assert api.option('od.dodval2.stval2').value.get() == 'val' + assert api.option('od.dodval1.stval1').owner.get() == owner + assert api.option('od.dodval2.stval2').owner.isdefault() + api.option('od.dodval1.stval1').value.reset() + assert api.option('od.dodval1.stval1').value.get() == 'val' + assert api.option('od.dodval2.stval2').value.get() == 'val' + assert api.option('od.dodval1.stval1').owner.isdefault() + assert api.option('od.dodval2.stval2').owner.isdefault() + + +def test_mandatory_dyndescription_context(): + val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) + st = StrOption('st', '', properties=('mandatory',)) + dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)}) + od = OptionDescription('od', '', [dod, val1]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + api.property.read_only() + raises(PropertiesOptionError, "api.option('od.dodval1.stval1').value.get()") + raises(PropertiesOptionError, "api.option('od.dodval2.stval2').value.get()") + api.property.read_write() + api.option('od.dodval1.stval1').value.set('val') + api.property.read_only() + assert api.option('od.dodval1.stval1').value.get() == 'val' + raises(PropertiesOptionError, "api.option('od.dodval2.stval2').value.get()") + api.property.read_write() + api.option('od.dodval1.stval1').value.reset() + api.property.read_only() + raises(PropertiesOptionError, "api.option('od.dodval1.stval1').value.get()") + assert list(api.value.mandatory_warnings()) == ['od.dodval1.stval1', 'od.dodval2.stval2'] + + +def test_increase_dyndescription_context(): + val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) + st = StrOption('st', '', properties=('mandatory',)) + dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)}) + od = OptionDescription('od', '', [dod, val1]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + api.property.read_write() + assert api.option('od.dodval1.stval1').value.get() is None + assert api.option('od.dodval2.stval2').value.get() is None + raises(AttributeError, "api.option('od.dodval3').value.get()") + api.option('od.val1').value.set(['val1', 'val2', 'val3']) + assert api.option('od.dodval1.stval1').value.get() is None + assert api.option('od.dodval2.stval2').value.get() is None + assert api.option('od.dodval3.stval3').value.get() is None + + +def test_decrease_dyndescription_context(): + val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) + st = StrOption('st', '', properties=('mandatory',)) + dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)}) + od = OptionDescription('od', '', [dod, val1]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + owner = api.owner.get() + api.property.read_write() + assert api.option('od.dodval1.stval1').value.get() is None + assert api.option('od.dodval2.stval2').value.get() is None + api.option('od.dodval2.stval2').value.set('yes') + assert api.option('od.dodval1.stval1').value.get() is None + assert api.option('od.dodval2.stval2').value.get() == 'yes' + assert api.option('od.dodval1.stval1').owner.isdefault() + assert api.option('od.dodval2.stval2').owner.get() == owner + raises(AttributeError, "api.option('od.dodval3').value.get()") + api.option('od.val1').value.set(['val1']) + assert api.option('od.dodval1.stval1').value.get() is None + raises(AttributeError, "api.option('od.dodval2').value.get()") + raises(AttributeError, "api.option('od.dodval3').value.get()") + assert api.option('od.dodval1.stval1').owner.isdefault() + #FIXME +# raises(AttributeError, "cfg.getowner(stval2)") + raises(AttributeError, "api.option('od.dodval2.stval2').value.get()") +# +# +#def test_requires_dyndescription(): +# boolean = BoolOption('boolean', '', True) +# st = StrOption('st', '', requires=[{'option': boolean, 'expected': False, +# 'action': 'disabled'}]) +# dod = DynOptionDescription('dod', '', [st], callback=return_list) +# od = OptionDescription('od', '', [dod]) +# od2 = OptionDescription('od', '', [od, boolean]) +# api = getapi(Config(od2)) +# api.property.read_write() +# assert api.option('od.dodval1.stval1').value.get() is None +# assert api.option('od.dodval2.stval2').value.get() is None +# # +# cfg.boolean = False +# props = [] +# try: +# cfg.od.dodval1.stval1 +# except PropertiesOptionError as err: +# props = err.proptype +# assert props == ['disabled'] +# props = [] +# try: +# cfg.od.dodval2.stval2 +# except PropertiesOptionError as err: +# props = err.proptype +# assert props == ['disabled'] +# # +# cfg.boolean = True +# assert api.option('od.dodval1.stval1').value.get() is None +# assert api.option('od.dodval2.stval2').value.get() is None +# #transitive +# cfg.cfgimpl_get_settings()[boolean].append('disabled') +# props = [] +# try: +# cfg.od.dodval1.stval1 +# except PropertiesOptionError as err: +# props = err.proptype +# assert props == ['disabled'] +# props = [] +# try: +# cfg.od.dodval2.stval2 +# except PropertiesOptionError as err: +# props = err.proptype +# assert props == ['disabled'] + + +#def test_requires_dyndescription2(): +# boolean = BoolOption('boolean', '', True) +# st = StrOption('st', '') +# dod = DynOptionDescription('dod', '', [st], callback=return_list, +# requires=[{'option': boolean, 'expected': False, +# 'action': 'disabled'}]) +# od = OptionDescription('od', '', [dod]) +# od2 = OptionDescription('od', '', [od, boolean]) +# api = getapi(Config(od2)) +# api.property.read_write() +# assert api.option('od.dodval1.stval1').value.get() is None +# assert api.option('od.dodval2.stval2').value.get() is None +# # +# cfg.boolean = False +# props = [] +# try: +# cfg.od.dodval1.stval1 +# except PropertiesOptionError as err: +# props = err.proptype +# assert props == ['disabled'] +# props = [] +# try: +# cfg.od.dodval2.stval2 +# except PropertiesOptionError as err: +# props = err.proptype +# assert props == ['disabled'] +# # +# cfg.boolean = True +# assert api.option('od.dodval1.stval1').value.get() is None +# assert api.option('od.dodval2.stval2').value.get() is None +# #transitive +# cfg.cfgimpl_get_settings()[boolean].append('disabled') +# props = [] +# try: +# cfg.od.dodval1.stval1 +# except PropertiesOptionError as err: +# props = err.proptype +# assert props == ['disabled'] +# props = [] +# try: +# cfg.od.dodval2.stval2 +# except PropertiesOptionError as err: +# props = err.proptype +# assert props == ['disabled'] +# +# +def test_validator_dyndescription(): + val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) + st = StrOption('st', '', validator=return_true, validator_params={'': ('yes',)}, default='val') + dod = DynOptionDescription('dod', '', [st], callback=return_list) + od = OptionDescription('od', '', [dod, val1]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + assert api.option('od.dodval1.stval1').value.get() == 'val' + raises(ValueError, "api.option('od.dodval1.stval1').value.set('no')") + api.option('od.dodval1.stval1').value.set('val') + + +def test_makedict_dyndescription_context(): + val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) + st = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st], callback=return_list) + od = OptionDescription('od', '', [dod, val1]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + api.option('od.dodval1.stval1').value.set('yes') + assert api.option.make_dict() == {'od.val1': ['val1', 'val2'], 'od.dodval1.stval1': 'yes', 'od.dodval2.stval2': None} + assert api.option.make_dict(flatten=True) == {'val1': ['val1', 'val2'], 'stval1': 'yes', 'stval2': None} + assert api.option.make_dict(withoption='stval1') == {'od.dodval1.stval1': 'yes'} + assert api.option('od').make_dict(withoption='stval1') == {'dodval1.stval1': 'yes'} + assert api.option('od.dodval1').make_dict(withoption='stval1') == {'stval1': 'yes'} + + +def test_find_dyndescription_context(): + val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) + st = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st], callback=return_list) + od = OptionDescription('od', '', [dod, val1]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + api.option('od.dodval1.stval1').value.set('yes') + assert api.option.find_first('stval1', type='value') == "yes" + assert isinstance(api.option.find_first('stval1', type='option'), DynSymLinkOption) + #assert api.option.find(bytype=StrOption, type='path') == ['od.dodval1.stval1', 'od.dodval2.stval2', 'od.val1'] + #opts = api.option.find(byvalue='yes') + #assert len(opts) == 1 + #assert isinstance(opts[0], DynSymLinkOption) + #assert opts[0].impl_getname() == 'stval1' + raises(AttributeError, "api.option.find('strnotexists')") + + +#def test_iter_all_dyndescription_context(): +# val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) +# st = StrOption('st', '') +# dod = DynOptionDescription('dod', '', [st], callback=return_list) +# od = OptionDescription('od', '', [dod, val1]) +# od2 = OptionDescription('od', '', [od]) +# api = getapi(Config(od2)) +# for it in cfg.iter_all(): +# assert it[0] == 'od' +# assert str(it[1]) == str(cfg.od) +# # +# list_od = [] +# for it in cfg.od.iter_all(): +# list_od.append(it[0]) +# assert list_od == ['dodval1', 'dodval2', 'val1'] +# # +# list_od = [] +# for it in cfg.od.dodval1: +# list_od.append(it[0]) +# assert list_od == ['stval1'] + + +def test_information_dyndescription_context(): + val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) + st = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st], callback=return_list) + od = OptionDescription('od', '', [dod, val1]) + od2 = OptionDescription('od', '', [od]) + dod.impl_set_information('testod', 'val1') + st.impl_set_information('testst', 'val2') + api = getapi(Config(od2)) + api.information.set('testcfgod', 'val3') + assert api.option('od.dodval1').information.get('testod') == 'val1' + assert api.option('od.dodval2').information.get('testod') == 'val1' + assert api.option('od.dodval1.stval1').information.get('testst') == 'val2' + assert api.option('od.dodval2.stval2').information.get('testst') == 'val2' + assert api.information.get('testcfgod') == 'val3' +# +# +#def test_consistency_dyndescription(): +# st = StrOption('st', '') +# st2 = StrOption('st2', '') +# dod = DynOptionDescription('dod', '', [st, st2], callback=return_list) +# od = OptionDescription('od', '', [dod]) +# st.impl_add_consistency('not_equal', st2) +# od2 = OptionDescription('od', '', [od]) +# api = getapi(Config(od2)) +# api.option('od.dodval1.stval1').value.set('yes') +# raises(ValueError, "cfg.od.dodval1.st2val1 = 'yes'") +# api.option('od.dodval2.stval2').value.set('yes') +# raises(ValueError, "cfg.od.dodval2.st2val2 = 'yes'") +# raises(ValueError, "cfg.od.dodval1.st2val1 = 'yes'") +# del(cfg.od.dodval2.stval2) +# raises(ValueError, "cfg.od.dodval1.st2val1 = 'yes'") +# cfg.od.dodval2.st2val2 = 'yes' +# raises(ValueError, "api.option('od.dodval2.stval2').value.set('yes')") + + +def test_consistency_dyndescription_default(): + st = StrOption('st', '', 'yes') + st2 = StrOption('st2', '') + dod = DynOptionDescription('dod', '', [st, st2], callback=return_list) + od = OptionDescription('od', '', [dod]) + st.impl_add_consistency('not_equal', st2) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + print('===>', api.option('od.dodval1.st2val1').value.get()) + raises(ValueError, "api.option('od.dodval1.st2val1').value.get()") + raises(ValueError, "api.option('od.dodval2.st2val2').value.get()") + + +def test_consistency_dyndescription_default_multi2(): + st = StrOption('st', '', ['yes'], multi=True) + st2 = StrOption('st2', '', ['yes'], multi=True) + dod = DynOptionDescription('dod', '', [st, st2], callback=return_list) + dod + raises(ValueError, "st.impl_add_consistency('not_equal', st2)") + + +def test_consistency_only_one_dyndescription(): + st = StrOption('st', '') + st + st2 = StrOption('st2', '') + DynOptionDescription('dod', '', [st2], callback=return_list) + raises(ConfigError, "st.impl_add_consistency('not_equal', st2)") + raises(ConfigError, "st2.impl_add_consistency('not_equal', st)") + + +def test_consistency_became_dyndescription(): + st = StrOption('st', '') + st2 = StrOption('st2', '') + st2.impl_add_consistency('not_equal', st) + od = DynOptionDescription('dod', '', [st2], callback=return_list) + od2 = OptionDescription('od', '', [od, st]) + od2 + raises(ConfigError, "c = Config(od2)") + + +def test_consistency_became_dyndescription2(): + st = StrOption('st', '') + st2 = StrOption('st2', '') + st.impl_add_consistency('not_equal', st2) + od = DynOptionDescription('dod', '', [st2], callback=return_list) + od2 = OptionDescription('od', '', [od, st]) + od2 + raises(ConfigError, "c = Config(od2)") + + +def test_consistency_external_dyndescription(): + st = StrOption('st', '') + st1 = StrOption('st1', '') + st2 = StrOption('st2', '') + dod = DynOptionDescription('dod', '', [st1, st2], callback=return_list) + od = OptionDescription('od', '', [dod, st]) + od + raises(ConfigError, "st.impl_add_consistency('not_equal', st2)") + + +def test_consistency_notsame_dyndescription(): + st1 = StrOption('st1', '') + st2 = StrOption('st2', '') + dod = DynOptionDescription('dod', '', [st1, st2], callback=return_list) + tst1 = StrOption('tst1', '') + tst2 = StrOption('tst2', '') + tdod = DynOptionDescription('tdod', '', [tst1, tst2], callback=return_list) + od = OptionDescription('od', '', [dod, tdod]) + od + raises(ConfigError, "st1.impl_add_consistency('not_equal', tst1)") + + +def test_all_dyndescription(): + st = StrOption('st', '') + ip = IPOption('ip', '') + network = NetworkOption('network', '') + netmask = NetmaskOption('netmask', '') + ch = ChoiceOption('ch', '', ('val1', 'val2', 'val3')) + ch1 = ChoiceOption('ch1', '', return_list) + boo = BoolOption('boo', '') + intr = IntOption('intr', '') + floa = FloatOption('floa', '') + uni = UnicodeOption('uni', '') + port = PortOption('port', '') + broad = BroadcastOption('broad', '') + domain = DomainnameOption('domain', '') + email = EmailOption('email', '') + url = URLOption('url', '') + username = UsernameOption('username', '') + filename = FilenameOption('filename', '') + dod = DynOptionDescription('dod', '', [st, ip, network, netmask, ch, ch1, + boo, intr, floa, uni, port, broad, + domain, email, url, username, + filename], callback=return_list) + od = OptionDescription('od', '', [dod]) + api = getapi(Config(od)) + assert api.option('dodval1.stval1').value.get() is None + assert api.option('dodval1.ipval1').value.get() is None + assert api.option('dodval1.networkval1').value.get() is None + assert api.option('dodval1.netmaskval1').value.get() is None + assert api.option('dodval1.chval1').value.get() is None + assert api.option('dodval1.ch1val1').value.get() is None + assert api.option('dodval1.booval1').value.get() is None + assert api.option('dodval1.intrval1').value.get() is None + assert api.option('dodval1.floaval1').value.get() is None + assert api.option('dodval1.unival1').value.get() is None + assert api.option('dodval1.portval1').value.get() is None + assert api.option('dodval1.broadval1').value.get() is None + assert api.option('dodval1.domainval1').value.get() is None + assert api.option('dodval1.emailval1').value.get() is None + assert api.option('dodval1.urlval1').value.get() is None + assert api.option('dodval1.usernameval1').value.get() is None + assert api.option('dodval1.filenameval1').value.get() is None + # + api.option('dodval1.stval1').value.set("no") + api.option('dodval1.ipval1').value.set("1.1.1.1") + api.option('dodval1.networkval1').value.set("1.1.1.0") + api.option('dodval1.netmaskval1').value.set("255.255.255.0") + api.option('dodval1.chval1').value.set("val1") + api.option('dodval1.ch1val1').value.set("val2") + api.option('dodval1.booval1').value.set(True) + api.option('dodval1.intrval1').value.set(1) + api.option('dodval1.floaval1').value.set(0.1) + api.option('dodval1.unival1').value.set("no") + api.option('dodval1.portval1').value.set(80) + api.option('dodval1.broadval1').value.set("1.1.1.255") + api.option('dodval1.domainval1').value.set("test.com") + api.option('dodval1.emailval1').value.set("test@test.com") + api.option('dodval1.urlval1').value.set("http://test.com") + api.option('dodval1.usernameval1').value.set("user1") + api.option('dodval1.filenameval1').value.set("/tmp") + assert api.option('dodval1.stval1').value.get() == "no" + assert api.option('dodval1.ipval1').value.get() == "1.1.1.1" + assert api.option('dodval1.networkval1').value.get() == "1.1.1.0" + assert api.option('dodval1.netmaskval1').value.get() == "255.255.255.0" + assert api.option('dodval1.chval1').value.get() == "val1" + assert api.option('dodval1.ch1val1').value.get() == "val2" + assert api.option('dodval1.booval1').value.get() is True + assert api.option('dodval1.intrval1').value.get() == 1 + assert api.option('dodval1.floaval1').value.get() == 0.1 + assert api.option('dodval1.unival1').value.get() == u"no" + assert api.option('dodval1.portval1').value.get() == 80 + assert api.option('dodval1.broadval1').value.get() == "1.1.1.255" + assert api.option('dodval1.domainval1').value.get() == "test.com" + assert api.option('dodval1.emailval1').value.get() == "test@test.com" + assert api.option('dodval1.urlval1').value.get() == "http://test.com" + assert api.option('dodval1.usernameval1').value.get() == "user1" + assert api.option('dodval1.filenameval1').value.get() == "/tmp" + assert api.option('dodval2.stval2').value.get() is None + assert api.option('dodval2.ipval2').value.get() is None + assert api.option('dodval2.networkval2').value.get() is None + assert api.option('dodval2.netmaskval2').value.get() is None + assert api.option('dodval2.chval2').value.get() is None + assert api.option('dodval2.ch1val2').value.get() is None + assert api.option('dodval2.booval2').value.get() is None + assert api.option('dodval2.intrval2').value.get() is None + assert api.option('dodval2.floaval2').value.get() is None + assert api.option('dodval2.unival2').value.get() is None + assert api.option('dodval2.portval2').value.get() is None + assert api.option('dodval2.broadval2').value.get() is None + assert api.option('dodval2.domainval2').value.get() is None + assert api.option('dodval2.emailval2').value.get() is None + assert api.option('dodval2.urlval2').value.get() is None + assert api.option('dodval2.usernameval2').value.get() is None + assert api.option('dodval2.filenameval2').value.get() is None +# +# +#def test_consistency_ip_netmask_dyndescription(): +# a = IPOption('a', '') +# b = NetmaskOption('b', '') +# dod = DynOptionDescription('dod', '', [a, b], callback=return_list) +# b.impl_add_consistency('ip_netmask', a) +# od = OptionDescription('od', '', [dod]) +# c = Config(od) +# c.dodval1.aval1 = '192.168.1.1' +# c.dodval1.bval1 = '255.255.255.0' +# c.dodval2.aval2 = '192.168.1.2' +# c.dodval2.bval2 = '255.255.255.255' +## c.dodval2.bval2 = '255.255.255.0' +# +# +#def test_consistency_ip_in_network_dyndescription(): +# a = NetworkOption('a', '') +# b = NetmaskOption('b', '') +# c = IPOption('c', '') +# dod = DynOptionDescription('dod', '', [a, b, c], callback=return_list) +# c.impl_add_consistency('in_network', a, b) +# od = OptionDescription('od', '', [dod]) +# cfg = Config(od) +# cfg.dodval1.aval1 = '192.168.1.0' +# cfg.dodval1.bval1 = '255.255.255.0' +# cfg.dodval1.cval1 = '192.168.1.1' + + +#def test_masterslaves_dyndescription(): +# st1 = StrOption('st1', "", multi=True) +# st2 = StrOption('st2', "", multi=True) +# stm = MasterSlaves('st1', '', [st1, st2]) +# #stm.impl_set_group_type(groups.master) +# st = DynOptionDescription('st', '', [stm], callback=return_list) +# od = OptionDescription('od', '', [st]) +# od2 = OptionDescription('od', '', [od]) +# api = getapi(Config(od2)) +# print('--------------- 1') +# owner = api.owner.get() +# print('--------------- 2') +# st1val1 = cfg.unwrap_from_path('od.stval1.st1val1.st1val1') +# print('--------------- 3') +# st2val1 = cfg.unwrap_from_path('od.stval1.st1val1.st2val1') +# print('--------------- 4') +# st1val2 = cfg.unwrap_from_path('od.stval2.st1val2.st1val2') +# print('--------------- 5') +# st2val2 = cfg.unwrap_from_path('od.stval2.st1val2.st2val2') +# print('--------------- 6') +# assert api.option.make_dict() == {'od.stval1.st1val1.st2val1': [], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': []} +# print('--------------- 7') +# assert cfg.od.stval1.st1val1.st1val1 == [] +# print('--------------- 8') +# assert cfg.od.stval1.st1val1.st2val1 == [] +# print('--------------- 9') +# assert cfg.od.stval2.st1val2.st1val2 == [] +# print('--------------- 10') +# assert cfg.od.stval2.st1val2.st2val2 == [] +# print('--------------- 11') +# assert cfg.getowner(st1val1) == owners.default +# print('--------------- 12') +# assert cfg.getowner(st1val2) == owners.default +# print('--------------- 13') +# assert cfg.getowner(st2val1) == owners.default +# print('--------------- 14') +# assert cfg.getowner(st2val2) == owners.default +# print('--------------- 15') +# # +# cfg.od.stval1.st1val1.st1val1.append('yes') +# print('--------------- 16') +# assert api.option.make_dict() == {'od.stval1.st1val1.st2val1': [None], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': ['yes']} +# print('--------------- 17') +# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] +# print('--------------- 18') +# assert cfg.od.stval1.st1val1.st2val1 == [None] +# print('--------------- 19') +# assert cfg.od.stval2.st1val2.st1val2 == [] +# print('--------------- 20') +# assert cfg.od.stval2.st1val2.st2val2 == [] +# print('--------------- 21') +# assert cfg.getowner(st1val1) == owner +# print('--------------- 22') +# assert cfg.getowner(st1val2) == owners.default +# print('--------------- 23') +# assert cfg.getowner(st2val1) == owners.default +# print('--------------- 24') +# assert cfg.getowner(st2val2) == owners.default +# print('--------------- 25') +# # +# cfg.od.stval1.st1val1.st1val1 = ['yes'] +# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] +# assert cfg.od.stval1.st1val1.st2val1 == [None] +# assert cfg.od.stval2.st1val2.st1val2 == [] +# assert cfg.od.stval2.st1val2.st2val2 == [] +# assert cfg.getowner(st1val1) == owner +# assert cfg.getowner(st1val2) == owners.default +# assert cfg.getowner(st2val1) == owners.default +# assert cfg.getowner(st2val2) == owners.default +# # +# cfg.od.stval1.st1val1.st2val1 = ['no'] +# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] +# assert cfg.od.stval1.st1val1.st2val1 == ['no'] +# assert cfg.od.stval2.st1val2.st1val2 == [] +# assert cfg.od.stval2.st1val2.st2val2 == [] +# assert cfg.getowner(st1val1) == owner +# assert cfg.getowner(st1val2) == owners.default +# assert cfg.getowner(st2val1, 0) == owner +## assert cfg.getowner(st2val2) == owners.default +# # +# cfg.od.stval1.st1val1.st1val1.pop(0) +# assert cfg.od.stval1.st1val1.st1val1 == [] +# assert cfg.od.stval1.st1val1.st2val1 == [] +# assert cfg.od.stval2.st1val2.st1val2 == [] +# assert cfg.od.stval2.st1val2.st2val2 == [] +# assert cfg.getowner(st1val1) == owner +# assert cfg.getowner(st1val2) == owners.default +## assert cfg.getowner(st2val1) == owner +## assert cfg.getowner(st2val2) == owners.default +# # +# cfg.od.stval1.st1val1.st1val1 = ['yes'] +# cfg.od.stval1.st1val1.st2val1 = ['yes'] +# assert cfg.getowner(st1val1) == owner +# assert cfg.getowner(st2val1, 0) == owner +# del(cfg.od.stval1.st1val1.st2val1) +# assert cfg.getowner(st1val1) == owner +# assert cfg.getowner(st1val2) == owners.default +## assert cfg.getowner(st2val1) == owners.default +## assert cfg.getowner(st2val2) == owners.default +# # +# cfg.od.stval1.st1val1.st1val1 = ['yes'] +# cfg.od.stval1.st1val1.st2val1 = ['yes'] +# del(cfg.od.stval1.st1val1.st1val1) +# assert cfg.od.stval1.st1val1.st1val1 == [] +# assert cfg.od.stval1.st1val1.st2val1 == [] +# assert cfg.od.stval2.st1val2.st1val2 == [] +# assert cfg.od.stval2.st1val2.st2val2 == [] +# assert cfg.getowner(st1val1) == owners.default +# assert cfg.getowner(st1val2) == owners.default +# assert cfg.getowner(st2val1) == owners.default +# assert cfg.getowner(st2val2) == owners.default +# +# +#def test_masterslaves_default_multi_dyndescription(): +# st1 = StrOption('st1', "", multi=True) +# st2 = StrOption('st2', "", multi=True, default_multi='no') +# stm = MasterSlaves('st1', '', [st1, st2]) +# #stm.impl_set_group_type(groups.master) +# st = DynOptionDescription('st', '', [stm], callback=return_list) +# od = OptionDescription('od', '', [st]) +# od2 = OptionDescription('od', '', [od]) +# api = getapi(Config(od2)) +# owner = api.owner.get() +# st1val1 = cfg.unwrap_from_path('od.stval1.st1val1.st1val1') +# st2val1 = cfg.unwrap_from_path('od.stval1.st1val1.st2val1') +# st1val2 = cfg.unwrap_from_path('od.stval2.st1val2.st1val2') +# st2val2 = cfg.unwrap_from_path('od.stval2.st1val2.st2val2') +# assert cfg.od.stval1.st1val1.st1val1 == [] +# assert cfg.od.stval1.st1val1.st2val1 == [] +# assert cfg.od.stval2.st1val2.st1val2 == [] +# assert cfg.od.stval2.st1val2.st2val2 == [] +# assert cfg.getowner(st1val1) == owners.default +# assert cfg.getowner(st1val2) == owners.default +# assert cfg.getowner(st2val1) == owners.default +# assert cfg.getowner(st2val2) == owners.default +# cfg.od.stval1.st1val1.st1val1.append('yes') +# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] +# assert cfg.od.stval1.st1val1.st2val1 == ['no'] +# assert cfg.od.stval2.st1val2.st1val2 == [] +# assert cfg.od.stval2.st1val2.st2val2 == [] +# assert cfg.getowner(st1val1) == owner +# assert cfg.getowner(st1val2) == owners.default +# assert cfg.getowner(st2val1) == owners.default +# assert cfg.getowner(st2val2) == owners.default +# +# +#def test_masterslaves_submulti_dyndescription(): +# st1 = StrOption('st1', "", multi=True) +# st2 = StrOption('st2', "", multi=submulti) +# stm = MasterSlaves('st1', '', [st1, st2]) +# #stm.impl_set_group_type(groups.master) +# st = DynOptionDescription('st', '', [stm], callback=return_list) +# od = OptionDescription('od', '', [st]) +# od2 = OptionDescription('od', '', [od]) +# api = getapi(Config(od2)) +# owner = api.owner.get() +# st1val1 = cfg.unwrap_from_path('od.stval1.st1val1.st1val1') +# st2val1 = cfg.unwrap_from_path('od.stval1.st1val1.st2val1') +# st1val2 = cfg.unwrap_from_path('od.stval2.st1val2.st1val2') +# st2val2 = cfg.unwrap_from_path('od.stval2.st1val2.st2val2') +# assert cfg.od.stval1.st1val1.st1val1 == [] +# assert cfg.od.stval1.st1val1.st2val1 == [] +# assert cfg.od.stval2.st1val2.st1val2 == [] +# assert cfg.od.stval2.st1val2.st2val2 == [] +# assert cfg.getowner(st1val1) == owners.default +# assert cfg.getowner(st1val2) == owners.default +# assert cfg.getowner(st2val1) == owners.default +# assert cfg.getowner(st2val2) == owners.default +# cfg.od.stval1.st1val1.st1val1.append('yes') +# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] +# assert cfg.od.stval1.st1val1.st2val1 == [[]] +# assert cfg.od.stval2.st1val2.st1val2 == [] +# assert cfg.od.stval2.st1val2.st2val2 == [] +# assert cfg.getowner(st1val1) == owner +# assert cfg.getowner(st1val2) == owners.default +# assert cfg.getowner(st2val1) == owners.default +# assert cfg.getowner(st2val2) == owners.default +# # +# cfg.od.stval1.st1val1.st2val1[0].append('no') +# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] +# assert cfg.od.stval1.st1val1.st2val1 == [['no']] +# assert cfg.od.stval2.st1val2.st1val2 == [] +# assert cfg.od.stval2.st1val2.st2val2 == [] +# assert cfg.getowner(st1val1) == owner +# assert cfg.getowner(st1val2) == owners.default +# assert cfg.getowner(st2val1, 0) == owner +# assert cfg.getowner(st2val2) == owners.default + + +#def test_masterslaves_consistency_ip_dyndescription(): +# a = NetworkOption('net', '', multi=True) +# b = NetmaskOption('mask', '', multi=True) +# c = BroadcastOption('broad', '', multi=True) +# b.impl_add_consistency('network_netmask', a) +# c.impl_add_consistency('broadcast', a, b) +# dod = DynOptionDescription('net', '', [a, b, c], callback=return_list) +# dod.impl_set_group_type(groups.master) +# od = OptionDescription('od', '', [dod]) +# cfg = Config(od) +# cfg.netval1.netval1 = ['192.168.1.0'] +# cfg.netval1.maskval1 = ['255.255.255.0'] +# cfg.netval1.broadval1 = ['192.168.1.255'] +# +# cfg.netval1.netval1 = ['192.168.1.0', '192.168.2.128'] +# cfg.netval1.maskval1 = ['255.255.255.0', '255.255.255.128'] +# cfg.netval1.broadval1 = ['192.168.1.255', '192.168.2.255'] +# cfg.netval1.broadval1[1] = '192.168.2.255' +# # +# assert cfg.netval1.netval1 == ['192.168.1.0', '192.168.2.128'] +# assert cfg.netval1.maskval1 == ['255.255.255.0', '255.255.255.128'] +# assert cfg.netval1.broadval1 == ['192.168.1.255', '192.168.2.255'] +# assert cfg.netval2.netval2 == [] +# assert cfg.netval2.maskval2 == [] +# assert cfg.netval2.broadval2 == [] + + +#def test_masterslaves_consistency_ip_dyndescription_propertyerror(): +# a = NetworkOption('net', '', multi=True) +# b = NetmaskOption('mask', '', multi=True, properties=('mandatory',)) +# c = BroadcastOption('broad', '', multi=True) +# b.impl_add_consistency('network_netmask', a) +# c.impl_add_consistency('broadcast', a, b) +# dod = DynOptionDescription('net', '', [a, b, c], callback=return_list) +# dod.impl_set_group_type(groups.master) +# od = OptionDescription('od', '', [dod]) +# cfg = Config(od) +# api.property.read_write() +# cfg.netval1.netval1 = ['192.168.1.0'] +# api.property.read_only() +# raises(PropertiesOptionError, "cfg.netval1.netval1") +# +# +#def test_masterslaves_callback_dyndescription(): +# st1 = StrOption('st1', "", multi=True) +# st2 = StrOption('st2', "", multi=True, callback=return_dynval, callback_params={'value': ((st1, False),)}) +# stm = MasterSlaves('st1', '', [st1, st2]) +# #stm.impl_set_group_type(groups.master) +# st = DynOptionDescription('st', '', [stm], callback=return_list) +# od = OptionDescription('od', '', [st]) +# od2 = OptionDescription('od', '', [od]) +# api = getapi(Config(od2)) +# owner = api.owner.get() +# st1val1 = cfg.unwrap_from_path('od.stval1.st1val1.st1val1') +# st2val1 = cfg.unwrap_from_path('od.stval1.st1val1.st2val1') +# st1val2 = cfg.unwrap_from_path('od.stval2.st1val2.st1val2') +# st2val2 = cfg.unwrap_from_path('od.stval2.st1val2.st2val2') +# assert api.option.make_dict() == {'od.stval1.st1val1.st2val1': [], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': []} +# assert cfg.od.stval1.st1val1.st1val1 == [] +# assert cfg.od.stval1.st1val1.st2val1 == [] +# assert cfg.od.stval2.st1val2.st1val2 == [] +# assert cfg.od.stval2.st1val2.st2val2 == [] +# assert cfg.getowner(st1val1) == owners.default +# assert cfg.getowner(st1val2) == owners.default +# assert cfg.getowner(st2val1) == owners.default +# assert cfg.getowner(st2val2) == owners.default +# # +# cfg.od.stval1.st1val1.st1val1.append('yes') +# assert api.option.make_dict() == {'od.stval1.st1val1.st2val1': ['yes'], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': ['yes']} +# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] +# assert cfg.od.stval1.st1val1.st2val1 == ['yes'] +# assert cfg.od.stval2.st1val2.st1val2 == [] +# assert cfg.od.stval2.st1val2.st2val2 == [] +# assert cfg.getowner(st1val1) == owner +# assert cfg.getowner(st1val2) == owners.default +# assert cfg.getowner(st2val1) == owners.default +# assert cfg.getowner(st2val2) == owners.default +# # +# cfg.od.stval1.st1val1.st2val1 = ['no'] +# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] +# assert cfg.od.stval1.st1val1.st2val1 == ['no'] +# assert cfg.od.stval2.st1val2.st1val2 == [] +# assert cfg.od.stval2.st1val2.st2val2 == [] +# assert cfg.getowner(st1val1) == owner +# assert cfg.getowner(st1val2) == owners.default +# assert cfg.getowner(st2val1, 0) == owner +## assert cfg.getowner(st2val2) == owners.default +# # +# cfg.od.stval1.st1val1.st1val1.pop(0) +# assert cfg.od.stval1.st1val1.st1val1 == [] +# assert cfg.od.stval1.st1val1.st2val1 == [] +# assert cfg.od.stval2.st1val2.st1val2 == [] +# assert cfg.od.stval2.st1val2.st2val2 == [] +# assert cfg.getowner(st1val1) == owner +# assert cfg.getowner(st1val2) == owners.default +## assert cfg.getowner(st2val1) == owner +## assert cfg.getowner(st2val2) == owners.default +# # +# cfg.od.stval1.st1val1.st1val1 = ['yes'] +# cfg.od.stval1.st1val1.st2val1 = ['yes'] +# assert cfg.getowner(st1val1) == owner +# assert cfg.getowner(st2val1, 0) == owner +# del(cfg.od.stval1.st1val1.st2val1) +# assert cfg.getowner(st1val1) == owner +# assert cfg.getowner(st1val2) == owners.default +# assert cfg.getowner(st2val1) == owners.default +# assert cfg.getowner(st2val2) == owners.default +# # +# cfg.od.stval1.st1val1.st1val1 = ['yes'] +# cfg.od.stval1.st1val1.st2val1 = ['yes'] +# del(cfg.od.stval1.st1val1.st1val1) +# assert cfg.od.stval1.st1val1.st1val1 == [] +# assert cfg.od.stval1.st1val1.st2val1 == [] +# assert cfg.od.stval2.st1val2.st1val2 == [] +# assert cfg.od.stval2.st1val2.st2val2 == [] +# assert cfg.getowner(st1val1) == owners.default +# assert cfg.getowner(st1val2) == owners.default +# assert cfg.getowner(st2val1) == owners.default +# assert cfg.getowner(st2val2) == owners.default +# # +# cfg.od.stval1.st1val1.st2val1 = [] +# cfg.od.stval1.st1val1.st1val1 = ['yes'] +# assert cfg.od.stval1.st1val1.st2val1 == ['yes'] +# +# +#def test_masterslaves_callback_value_dyndescription(): +# st1 = StrOption('st1', "", multi=True) +# st2 = StrOption('st2', "", multi=True, callback=return_dynval, callback_params={'value': ('val',)}) +# stm = MasterSlaves('st1', '', [st1, st2]) +# #stm.impl_set_group_type(groups.master) +# st = DynOptionDescription('st', '', [stm], callback=return_list) +# od = OptionDescription('od', '', [st]) +# od2 = OptionDescription('od', '', [od]) +# api = getapi(Config(od2)) +# assert cfg.od.stval1.st1val1.st1val1 == [] +# assert cfg.od.stval1.st1val1.st2val1 == [] +# cfg.od.stval1.st1val1.st1val1.append('yes') +# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] +# assert cfg.od.stval1.st1val1.st2val1[0] == 'val' +# assert cfg.od.stval1.st1val1.st2val1 == ['val'] +# +# +#def test_masterslaves_callback_nomulti_dyndescription(): +# v1 = StrOption('v1', '', "val") +# st1 = StrOption('st1', "", multi=True) +# st2 = StrOption('st2', "", multi=True, callback=return_dynval, callback_params={'': ((v1, False),)}) +# stm = MasterSlaves('st1', '', [st1, st2]) +# #stm.impl_set_group_type(groups.master) +# st = DynOptionDescription('st', '', [stm], callback=return_list) +# od = OptionDescription('od', '', [st]) +# od2 = OptionDescription('od', '', [od, v1]) +# api = getapi(Config(od2)) +# assert cfg.od.stval1.st1val1.st1val1 == [] +# assert cfg.od.stval1.st1val1.st2val1 == [] +# cfg.od.stval1.st1val1.st1val1.append('yes') +# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] +# assert cfg.od.stval1.st1val1.st2val1 == ['val'] +# +# +#def test_masterslaves_callback_samegroup_dyndescription(): +# st1 = StrOption('st1', "", multi=True) +# st2 = StrOption('st2', "", multi=True) +# st3 = StrOption('st3', "", multi=True, callback=return_dynval, callback_params={'': ((st2, False),)}) +# stm = MasterSlaves('st1', '', [st1, st2, st3]) +# #stm.impl_set_group_type(groups.master) +# st = DynOptionDescription('st', '', [stm], callback=return_list) +# od = OptionDescription('od', '', [st]) +# od2 = OptionDescription('od', '', [od]) +# api = getapi(Config(od2)) +# owner = api.owner.get() +# st1val1 = cfg.unwrap_from_path('od.stval1.st1val1.st1val1') +# st2val1 = cfg.unwrap_from_path('od.stval1.st1val1.st2val1') +# st3val1 = cfg.unwrap_from_path('od.stval1.st1val1.st3val1') +# st1val2 = cfg.unwrap_from_path('od.stval2.st1val2.st1val2') +# st2val2 = cfg.unwrap_from_path('od.stval2.st1val2.st2val2') +# st3val2 = cfg.unwrap_from_path('od.stval2.st1val2.st3val2') +# assert api.option.make_dict() == {'od.stval1.st1val1.st1val1': [], +# 'od.stval1.st1val1.st2val1': [], +# 'od.stval1.st1val1.st3val1': [], +# 'od.stval2.st1val2.st1val2': [], +# 'od.stval2.st1val2.st2val2': [], +# 'od.stval2.st1val2.st3val2': []} +# assert cfg.od.stval1.st1val1.st1val1 == [] +# assert cfg.od.stval1.st1val1.st2val1 == [] +# assert cfg.od.stval1.st1val1.st3val1 == [] +# assert cfg.od.stval2.st1val2.st1val2 == [] +# assert cfg.od.stval2.st1val2.st2val2 == [] +# assert cfg.od.stval2.st1val2.st3val2 == [] +# assert cfg.getowner(st1val1) == owners.default +# assert cfg.getowner(st1val2) == owners.default +# assert cfg.getowner(st2val1) == owners.default +# assert cfg.getowner(st2val2) == owners.default +# assert cfg.getowner(st3val1) == owners.default +# assert cfg.getowner(st3val2) == owners.default +# ## +# cfg.od.stval1.st1val1.st1val1.append('yes') +# assert api.option.make_dict() == {'od.stval1.st1val1.st1val1': ['yes'], +# 'od.stval1.st1val1.st2val1': [None], +# 'od.stval1.st1val1.st3val1': [None], +# 'od.stval2.st1val2.st1val2': [], +# 'od.stval2.st1val2.st2val2': [], +# 'od.stval2.st1val2.st3val2': []} +# assert cfg.getowner(st1val1) == owner +# assert cfg.getowner(st1val2) == owners.default +# assert cfg.getowner(st2val1) == owners.default +# assert cfg.getowner(st2val2) == owners.default +# assert cfg.getowner(st3val1) == owners.default +# assert cfg.getowner(st3val2) == owners.default +# # +# cfg.od.stval1.st1val1.st2val1[0] = 'yes' +# assert api.option.make_dict() == {'od.stval1.st1val1.st1val1': ['yes'], +# 'od.stval1.st1val1.st2val1': ['yes'], +# 'od.stval1.st1val1.st3val1': ['yes'], +# 'od.stval2.st1val2.st1val2': [], +# 'od.stval2.st1val2.st2val2': [], +# 'od.stval2.st1val2.st3val2': []} +# assert cfg.getowner(st1val1) == owner +# assert cfg.getowner(st2val1, 0) == owner +# assert cfg.getowner(st3val1, 0) == owners.default +# assert cfg.getowner(st1val2) == owners.default +# #assert cfg.getowner(st2val2) == owners.default +# #assert cfg.getowner(st3val2) == owners.default + + +def test_invalid_conflict_dyndescription(): + st = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st], callback=return_list) + dodinvalid = StrOption('dodinvalid', '') + dod, dodinvalid + raises(ConflictError, "OptionDescription('od', '', [dod, dodinvalid])") + + +def test_invalid_subod_dyndescription(): + st2 = StrOption('st2', '') + od1 = OptionDescription('od1', '', [st2]) + od1 + raises(ConfigError, "DynOptionDescription('dod', '', [od1], callback=return_list)") + + +def test_invalid_subdynod_dyndescription(): + st2 = StrOption('st2', '') + od1 = DynOptionDescription('od1', '', [st2], callback=return_list) + od1 + raises(ConfigError, "DynOptionDescription('dod', '', [od1], callback=return_list)") + + +def test_invalid_symlink_dyndescription(): + st = StrOption('st', '') + st2 = SymLinkOption('st2', st) + st2 + raises(ConfigError, "DynOptionDescription('dod', '', [st, st2], callback=return_list)") + + +def test_nocallback_dyndescription(): + st = StrOption('st', '') + st2 = StrOption('st2', '') + st, st2 + raises(ConfigError, "DynOptionDescription('dod', '', [st, st2])") + + +#def test_invalid_samevalue_dyndescription(): +# st = StrOption('st', '') +# dod = DynOptionDescription('dod', '', [st], callback=return_same_list) +# od = OptionDescription('od', '', [dod]) +# cfg = Config(od) +# cfg +# raises(ConfigError, "print(cfg)") +# +# +#def test_invalid_name_dyndescription(): +# st = StrOption('st', '') +# dod = DynOptionDescription('dod', '', [st], callback=return_wrong_list) +# od = OptionDescription('od', '', [dod]) +# cfg = Config(od) +# cfg +# raises(ValueError, "print(cfg)") diff --git a/test/new_api/test_freeze.py b/test/new_api/test_freeze.py new file mode 100644 index 0000000..7b67674 --- /dev/null +++ b/test/new_api/test_freeze.py @@ -0,0 +1,221 @@ +# coding: utf-8 +"frozen and hidden values" +from .autopath import do_autopath +do_autopath() + +from py.test import raises + +from tiramisu.setting import owners, groups +from tiramisu import ChoiceOption, BoolOption, IntOption, FloatOption, \ + StrOption, OptionDescription, SymLinkOption, MasterSlaves, Config, \ + getapi +from tiramisu.error import PropertiesOptionError, ConfigError + + +#____________________________________________________________ +#freeze +def make_description_freeze(): + gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref') + gcdummy = BoolOption('dummy', 'dummy', default=False) + objspaceoption = ChoiceOption('objspace', 'Object space', + ('std', 'thunk'), 'std') + booloption = BoolOption('bool', 'Test boolean option', default=True) + intoption = IntOption('int', 'Test int option', default=0) + floatoption = FloatOption('float', 'Test float option', default=2.3) + stroption = StrOption('str', 'Test string option', default="abc") + boolop = BoolOption('boolop', 'Test boolean option op', default=[True], multi=True) + wantref_option = BoolOption('wantref', 'Test requires', default=False, properties=('force_store_value',), + requires=({'option': booloption, 'expected': True, 'action': 'hidden'},)) + wantref2_option = BoolOption('wantref2', 'Test requires', default=False, properties=('force_store_value', 'hidden')) + wantref3_option = BoolOption('wantref3', 'Test requires', default=[False], multi=True, properties=('force_store_value',)) + st2 = SymLinkOption('st2', wantref3_option) + wantframework_option = BoolOption('wantframework', 'Test requires', + default=False, + requires=({'option': booloption, 'expected': True, 'action': 'hidden'},)) + + gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption]) + descr = OptionDescription('tiramisu', '', [gcgroup, booloption, objspaceoption, + wantref_option, wantref2_option, wantref3_option, st2, stroption, + wantframework_option, + intoption, boolop]) + return descr + + +def return_val(): + return 1 + + +def return_val2(value): + return value + + +def return_val3(context, value): + return value + + +def test_freeze_whole_config(): + descr = make_description_freeze() + api = getapi(Config(descr)) + api.property.read_write() + api.property.add('everything_frozen') + assert api.option('gc.dummy').value.get() is False + prop = [] + try: + api.option('gc.dummy').value.set(True) + except PropertiesOptionError as err: + prop = err.proptype + assert 'frozen' in prop + assert api.option('gc.dummy').value.get() is False + # + api.property.pop('everything_frozen') + api.option('gc.dummy').value.set(True) + assert api.option('gc.dummy').value.get() is True + # + api.property.add('everything_frozen') + owners.addowner("everythingfrozen") + prop = [] + try: + api.option('gc.dummy').owner.set('everythingfrozen') + except PropertiesOptionError as err: + prop = err.proptype + assert 'frozen' in prop + + +def test_freeze_one_option(): + "freeze an option " + descr = make_description_freeze() + api = getapi(Config(descr)) + api.property.read_write() + #freeze only one option + api.option('gc.dummy').property.add('frozen') + assert api.option('gc.dummy').value.get() is False + prop = [] + try: + api.option('gc.dummy').value.set(True) + except PropertiesOptionError as err: + prop = err.proptype + assert 'frozen' in prop + + +def test_frozen_value(): + "setattr a frozen value at the config level" + s = StrOption("string", "", default="string") + descr = OptionDescription("options", "", [s]) + api = getapi(Config(descr)) + api.property.read_write() + api.property.add('frozen') + api.option('string').property.add('frozen') + prop = [] + try: + api.option('string').value.set('egg') + except PropertiesOptionError as err: + prop = err.proptype + assert 'frozen' in prop + + +def test_freeze(): + "freeze a whole configuration object" + descr = make_description_freeze() + api = getapi(Config(descr)) + api.property.read_write() + api.property.add('frozen') + api.option('gc.name').property.add('frozen') + prop = [] + try: + api.option('gc.name').value.set('framework') + except PropertiesOptionError as err: + prop = err.proptype + assert 'frozen' in prop + + +def test_freeze_multi(): + descr = make_description_freeze() + api = getapi(Config(descr)) + api.property.read_write() + api.property.add('frozen') + api.option('boolop').property.add('frozen') + prop = [] + try: + api.option('boolop').value.set([True]) + except PropertiesOptionError as err: + prop = err.proptype + assert 'frozen' in prop + + +def test_force_store_value(): + descr = make_description_freeze() + conf = Config(descr) + api = getapi(conf) + assert api.value.get() == {'wantref': ('forced', False), + 'wantref2': ('forced', False), + 'wantref3': ('forced', (False,))} + api.option('wantref').value.set(True) + assert api.value.get() == {'wantref': ('user', True), + 'wantref2': ('forced', False), + 'wantref3': ('forced', (False,))} + api.option('wantref').value.reset() + assert api.value.get() == {'wantref': ('forced', False), + 'wantref2': ('forced', False), + 'wantref3': ('forced', (False,))} + + +def test_force_store_value_no_requirement(): + booloption = BoolOption('bool', 'Test boolean option', default=True) + try: + BoolOption('wantref', 'Test requires', default=False, + requires=({'option': booloption, 'expected': True, 'action': 'force_store_value'},)) + except ValueError: + pass + + +def test_force_store_value_masterslaves_slave(): + b = IntOption('int', 'Test int option', multi=True) + c = StrOption('str', 'Test string option', multi=True, properties=('force_store_value',)) + descr = MasterSlaves("int", "", [b, c]) + raises(ConfigError, "conf = Config(descr)") + + +#def test_force_store_value_masterslaves(): +# b = IntOption('int', 'Test int option', multi=True, properties=('force_store_value',)) +# c = StrOption('str', 'Test string option', multi=True) +# descr = MasterSlaves("int", "", [b, c]) +# api = getapi(Config(descr)) +# assert api.value.get() == {'int': ('forced', ())} + + +def test_force_store_value_masterslaves_sub(): + b = IntOption('int', 'Test int option', multi=True, properties=('force_store_value',)) + c = StrOption('str', 'Test string option', multi=True) + descr = MasterSlaves("int", "", [b, c]) + odr = OptionDescription('odr', '', [descr]) + api = getapi(Config(odr)) + assert api.value.get() == {'int.int': ('forced', ())} + + +def test_force_store_value_callback(): + b = IntOption('int', 'Test int option', properties=('force_store_value',), callback=return_val) + descr = OptionDescription("int", "", [b]) + api = getapi(Config(descr)) + assert api.value.get() == {'int': ('forced', 1)} + + +def test_force_store_value_callback_params(): + b = IntOption('int', 'Test int option', properties=('force_store_value',), callback=return_val2, callback_params={'value': (2,)}) + descr = OptionDescription("int", "", [b]) + api = getapi(Config(descr)) + assert api.value.get() == {'int': ('forced', 2)} + + +def test_force_store_value_callback_params_2(): + b = IntOption('int', 'Test int option', properties=('force_store_value',), callback=return_val3, callback_params={'': ((None,),), 'value': (2,)}) + descr = OptionDescription("int", "", [b]) + api = getapi(Config(descr)) + assert api.value.get() == {'int': ('forced', 2)} + + +def test_force_store_value_callback_params_with_opt(): + a = IntOption('val1', "", 2) + b = IntOption('int', 'Test int option', properties=('force_store_value',), callback=return_val2, callback_params={'value': ((a, False),)}) + descr = OptionDescription("int", "", [a, b]) + api = getapi(Config(descr)) + assert api.value.get() == {'int': ('forced', 2)} diff --git a/test/new_api/test_mandatory.py b/test/new_api/test_mandatory.py new file mode 100644 index 0000000..1dd6d80 --- /dev/null +++ b/test/new_api/test_mandatory.py @@ -0,0 +1,575 @@ +# coding: utf-8 +from .autopath import do_autopath +do_autopath() + +from py.test import raises +from tiramisu.config import Config +from tiramisu import IntOption, StrOption, UnicodeOption, OptionDescription, \ + SymLinkOption, MasterSlaves, getapi, undefined +from tiramisu.error import PropertiesOptionError, ConfigError +from tiramisu.setting import groups + + +def make_description(): + stroption = StrOption('str', 'Test string option', default="abc", + properties=('mandatory', )) + stroption1 = StrOption('str1', 'Test string option', + properties=('mandatory', )) + stroption2 = UnicodeOption('unicode2', 'Test string option', + properties=('mandatory', )) + stroption3 = StrOption('str3', 'Test string option', multi=True, + properties=('mandatory', )) + stroption4 = StrOption('str4', 'Test string option', multi=True, + properties=('mandatory', ), allow_empty_list=True) + descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3, stroption4]) + return descr + + +def return_value(value): + return value + + +def make_description2(): + stroption = StrOption('str', 'Test string option', default="abc", + properties=('mandatory', )) + stroption1 = StrOption('str1', 'Test string option', + properties=('mandatory', )) + stroption2 = SymLinkOption('unicode2', stroption1) + stroption3 = StrOption('str3', 'Test string option', multi=True, + properties=('mandatory', )) + unicode1 = UnicodeOption('unicode1', 'Test string option', callback=return_value, callback_params={'': ((stroption, False),)}, properties=('mandatory', )) + descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3, unicode1]) + return descr + + +def make_description_sym(): + stroption = StrOption('str', 'Test string option', default="abc", + properties=('mandatory', )) + stroption1 = StrOption('str1', 'Test string option', + properties=('mandatory', )) + stroption2 = SymLinkOption('unicode2', stroption1) + stroption3 = StrOption('str3', 'Test string option', multi=True, + properties=('mandatory', )) + descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3]) + return descr + + +def make_description3(): + stroption = StrOption('str', 'Test string option', default="abc", + properties=('mandatory', )) + stroption1 = StrOption('str1', 'Test string option', + properties=('mandatory', )) + stroption2 = SymLinkOption('unicode2', stroption1) + stroption3 = StrOption('str3', 'Test string option', multi=True, + properties=('mandatory', )) + unicode1 = UnicodeOption('unicode1', 'Test string option', callback=return_value, callback_params={'': ((stroption, False),)}, properties=('mandatory', )) + int1 = IntOption('int1', '', callback=return_value, callback_params={'': ((stroption, False),)}, properties=('mandatory', )) + descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3, unicode1, int1]) + return descr + + +def make_description4(): + stroption = StrOption('str', 'Test string option', default="abc", + properties=('mandatory', )) + stroption1 = StrOption('str1', 'Test string option', + properties=('mandatory', )) + stroption2 = UnicodeOption('unicode2', 'Test string option', + properties=('mandatory', )) + stroption3 = StrOption('str3', 'Test string option', multi=True, requires=[{'option': stroption, 'expected': 'yes', 'action': 'mandatory', 'transitive': False}]) + descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3]) + return descr + + +def test_mandatory_ro(): + descr = make_description() + api = getapi(Config(descr)) + api.property.read_only() + prop = [] + try: + api.option('str1').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + api.property.read_write() + api.option('str1').value.set('yes') + api.property.read_only() + assert api.option('str1').value.get() == 'yes' + + +def test_mandatory_rw(): + descr = make_description() + api = getapi(Config(descr)) + api.property.read_write() + #not mandatory in rw + api.option('str1').value.get() + api.option('str1').value.set('yes') + assert api.option('str1').value.get() == 'yes' + + +def test_mandatory_default(): + descr = make_description() + api = getapi(Config(descr)) + api.property.read_only() + #not mandatory in rw + api.option('str').value.get() + api.property.read_write() + api.option('str').value.set('yes') + api.property.read_only() + api.option('str').value.get() + api.property.read_write() + api.option('str').value.set(None) + api.property.read_only() + prop = [] + try: + api.option('str').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + + +def test_mandatory_delete(): + descr = make_description() + api = getapi(Config(descr)) + api.property.read_only() + api.option('str').value.get() + try: + api.option('str1').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + api.property.read_write() + api.option('str1').value.set('yes') + api.property.read_only() + assert api.option('str1').value.get() == 'yes' + api.property.pop('everything_frozen') + prop = [] + try: + api.option('str1').value.reset() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + api.option('str').value.reset() + + assert api.option('str1').value.get() == 'yes' + + +#valeur vide : None, '', u'', ... +def test_mandatory_none(): + descr = make_description() + api = getapi(Config(descr)) + api.option('str1').value.set(None) + assert api.option('str1').owner.get() == 'user' + api.property.read_only() + prop = [] + try: + api.option('str1').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + + +def test_mandatory_empty(): + descr = make_description() + api = getapi(Config(descr)) + api.option('str1').value.set('') + assert api.option('str1').owner.get() == 'user' + api.property.read_only() + prop = [] + try: + api.option('str1').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + + +def test_mandatory_multi_none(): + descr = make_description() + api = getapi(Config(descr)) + api.option('str3').value.set([None]) + assert api.option('str3').owner.get() == 'user' + api.property.read_only() + prop = [] + try: + api.option('str3').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + api.property.read_write() + api.option('str3').value.set(['yes', None]) + assert api.option('str3').owner.get() == 'user' + api.property.read_only() + prop = [] + try: + api.option('str3').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + + +def test_mandatory_multi_empty(): + descr = make_description() + api = getapi(Config(descr)) + api.option('str3').value.set([]) + assert api.option('str3').owner.get() == 'user' + api.property.read_only() + prop = [] + try: + api.option('str3').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + # + api.property.read_write() + api.option('str3').value.set(['']) + assert api.option('str3').owner.get() == 'user' + api.property.read_only() + prop = [] + try: + api.option('str3').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + # + api.property.read_write() + api.option('str3').value.set(['yes', '']) + assert api.option('str3').owner.get() == 'user' + api.property.read_only() + prop = [] + try: + api.option('str3').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + + +def test_mandatory_multi_empty_allow_empty_list(): + descr = make_description() + api = getapi(Config(descr)) + api.option('str4').value.set([]) + assert api.option('str4').owner.get() == 'user' + api.property.read_only() + prop = [] + api.option('str4').value.get() + # + api.property.read_write() + api.option('str4').value.set(['']) + assert api.option('str4').owner.get() == 'user' + api.property.read_only() + prop = [] + try: + api.option('str4').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + # + api.property.read_write() + api.option('str4').value.set(['yes', '']) + assert api.option('str4').owner.get() == 'user' + api.property.read_only() + prop = [] + try: + api.option('str4').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + + +def test_mandatory_multi_append(): + descr = make_description() + api = getapi(Config(descr)) + api.option('str3').value.set(['yes']) + api.property.read_write() + api.option('str3').value.get().append(None) + + +def test_mandatory_disabled(): + descr = make_description() + api = getapi(Config(descr)) + api.option('str1').value.get() + api.option('str1').property.add('disabled') + api.property.read_only() + pop = [] + try: + api.option('str1').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert set(prop) == set(['disabled', 'mandatory']) + + +def test_mandatory_unicode(): + descr = make_description() + api = getapi(Config(descr)) + api.option('unicode2').value.get() + api.property.read_only() + prop = [] + try: + api.option('unicode2').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + api.property.read_write() + api.option('unicode2').value.set('') + api.property.read_only() + prop = [] + try: + api.option('unicode2').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + + +def test_mandatory_warnings_ro(): + descr = make_description() + api = getapi(Config(descr)) + api.option('str').value.set('') + api.property.read_only() + proc = [] + try: + api.option('str').value.get() + except PropertiesOptionError as err: + prop = err.proptype + assert 'mandatory' in prop + assert list(api.value.mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3'] + api.property.read_write() + api.option('str').value.set('a') + api.property.read_only() + assert list(api.value.mandatory_warnings()) == ['str1', 'unicode2', 'str3'] + + +def test_mandatory_warnings_rw(): + descr = make_description() + api = getapi(Config(descr)) + api.option('str').value.set('') + api.property.read_write() + api.option('str').value.get() + assert list(api.value.mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3'] + api.option('str').value.set('a') + assert list(api.value.mandatory_warnings()) == ['str1', 'unicode2', 'str3'] + + +def test_mandatory_warnings_disabled(): + descr = make_description() + api = getapi(Config(descr)) + api.option('str').value.set('') + api.property.read_write() + api.option('str').value.get() + assert set(api.value.mandatory_warnings()) == {'str', 'str1', 'unicode2', 'str3'} + api.option('str').property.add('disabled') + assert set(api.value.mandatory_warnings()) == {'str1', 'unicode2', 'str3'} + + +def test_mandatory_warnings_hidden(): + descr = make_description() + api = getapi(Config(descr)) + api.option('str').value.set('') + api.property.read_write() + api.permissive.set(('hidden',)) + api.option('str').value.get() + assert set(api.value.mandatory_warnings()) == {'str', 'str1', 'unicode2', 'str3'} + api.option('str').property.add('hidden') + assert set(api.value.mandatory_warnings()) == {'str', 'str1', 'unicode2', 'str3'} + + +def test_mandatory_warnings_frozen(): + descr = make_description() + api = getapi(Config(descr)) + api.option('str').value.set('') + api.property.read_write() + api.option('str').value.get() + assert set(api.value.mandatory_warnings()) == {'str', 'str1', 'unicode2', 'str3'} + api.option('str').property.add('frozen') + api.property.read_only() + assert set(api.value.mandatory_warnings()) == {'str', 'str1', 'unicode2', 'str3'} + + +def test_mandatory_master(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True, + properties=('mandatory', )) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", + multi=True) + interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + descr = OptionDescription('o', '', [interface1]) + api = getapi(Config(descr)) + api.property.read_only() + raises(PropertiesOptionError, "api.option('ip_admin_eth0.ip_admin_eth0').value.get()") + + +def test_mandatory_warnings_master(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True, + properties=('mandatory', )) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", + multi=True) + interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + descr = OptionDescription('o', '', [interface1]) + api = getapi(Config(descr)) + assert list(api.value.mandatory_warnings()) == ['ip_admin_eth0.ip_admin_eth0'] + + +def test_mandatory_master_empty(): + 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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + descr = OptionDescription('o', '', [interface1]) + api = getapi(Config(descr)) + api.property.read_write() + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] + # + api.option('ip_admin_eth0.ip_admin_eth0').value.set([undefined]) + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == [None] + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None + api.property.read_only() + raises(PropertiesOptionError, "api.option('ip_admin_eth0.ip_admin_eth0').value.get()") + raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()") + api.property.read_write() + api.option('ip_admin_eth0.ip_admin_eth0').value.reset() + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] + # + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['']) + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == [''] + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None + api.property.read_only() + raises(PropertiesOptionError, "api.option('ip_admin_eth0.ip_admin_eth0').value.get()") + raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()") + api.property.read_write() + # + api.property.read_write() + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['ip']) + api.property.read_only() + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['ip'] + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None + # + api.property.read_write() + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['ip2']) + api.property.read_only() + raises(PropertiesOptionError, "api.option('ip_admin_eth0.ip_admin_eth0').value.reset()") + api.property.read_write() + api.option('ip_admin_eth0.ip_admin_eth0').value.reset() + + +def test_mandatory_warnings_master_empty(): + 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 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + descr = OptionDescription('o', '', [interface1]) + api = getapi(Config(descr)) + api.property.read_write() + api.option('ip_admin_eth0.ip_admin_eth0').value.set([undefined]) + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == [None] + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None + assert list(api.value.mandatory_warnings()) == ['ip_admin_eth0.ip_admin_eth0'] + api.option('ip_admin_eth0.ip_admin_eth0').value.reset() + # + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['']) + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == [''] + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None + assert list(api.value.mandatory_warnings()) == ['ip_admin_eth0.ip_admin_eth0'] + # + api.property.read_write() + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['ip']) + assert list(api.value.mandatory_warnings()) == [] + + +def test_mandatory_slave(): + 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, properties=('mandatory', )) + interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + descr = OptionDescription('o', '', [interface1]) + api = getapi(Config(descr)) + api.property.read_only() + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] + # + api.property.read_write() + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['ip']) + api.property.read_only() + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['ip'] + raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()") + # + api.property.read_write() + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('') + api.property.read_only() + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['ip'] + raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()") + # + api.property.read_write() + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('ip') + api.property.read_only() + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['ip'] + assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == 'ip' + + +def test_mandatory_warnings_slave(): + 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, properties=('mandatory', )) + interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + descr = OptionDescription('o', '', [interface1]) + api = getapi(Config(descr)) + api.property.read_only() + assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] + # + api.property.read_write() + assert list(api.value.mandatory_warnings()) == [] + api.option('ip_admin_eth0.ip_admin_eth0').value.set(['ip']) + assert list(api.value.mandatory_warnings()) == ['ip_admin_eth0.netmask_admin_eth0'] + + +def test_mandatory_warnings_symlink(): + descr = make_description_sym() + api = getapi(Config(descr)) + api.option('str').value.set('') + api.property.read_write() + api.option('str').value.get() + assert list(api.value.mandatory_warnings()) == ['str', 'str1', 'str3'] + api.option('str').property.add('frozen') + api.property.read_only() + assert list(api.value.mandatory_warnings()) == ['str', 'str1', 'str3'] + + +#def test_mandatory_warnings_validate(): +# descr = make_description3() +# api = getapi(Config(descr)) +# api.option('str').value.set('') +# raises(ValueError, "list(api.value.mandatory_warnings())") +# api.option('str').value.set('test') +# raises(ValueError, "list(api.value.mandatory_warnings())") + + +def test_mandatory_warnings_validate_empty(): + descr = make_description2() + api = getapi(Config(descr)) + api.option('str').value.set('') + api.property.read_only() + assert list(api.value.mandatory_warnings()) == ['str', 'str1', 'str3', 'unicode1'] + + +def test_mandatory_warnings_requires(): + descr = make_description4() + api = getapi(Config(descr)) + api.option('str').value.set('') + api.property.read_write() + api.option('str').value.get() + assert list(api.value.mandatory_warnings()) == ['str', 'str1', 'unicode2'] + api.property.read_only() + assert list(api.value.mandatory_warnings()) == ['str', 'str1', 'unicode2'] + api.property.read_write() + api.option('str').value.set('yes') + assert list(api.value.mandatory_warnings()) == ['str1', 'unicode2', 'str3'] + + +def test_mandatory_od_disabled(): + descr = make_description() + descr = OptionDescription('od', '', [descr]) + api = getapi(Config(descr)) + api.property.read_only() + assert list(api.value.mandatory_warnings()) == ['tiram.str1', 'tiram.unicode2', 'tiram.str3'] + api.option('tiram').property.add('disabled') + assert list(api.value.mandatory_warnings()) == [] diff --git a/tiramisu/api.py b/tiramisu/api.py index 5a547da..191de23 100644 --- a/tiramisu/api.py +++ b/tiramisu/api.py @@ -15,11 +15,17 @@ # along with this program. If not, see . # ____________________________________________________________ from inspect import ismethod, getdoc -from .error import APIError, PropertiesOptionError +from .error import APIError, PropertiesOptionError, ConfigError from .i18n import _ from .setting import owners, undefined +from .option import ChoiceOption from time import time from copy import deepcopy + + +TIRAMISU_VERSION = 3 + + try: from .value import Multi except: @@ -27,29 +33,31 @@ except: COUNT_TIME = False -#COUNT_TIME = {} +COUNT_TIME = {} def count(func): global MOD_COUNT_TIME + class_name = func.__str__().split()[1].split('.')[0] func_name = func.__name__ def wrapper(*args, **kwargs): time1 = time() ret = func(*args, **kwargs) time2 = time() diff = (time2 - time1) * 1000.0 - MOD_COUNT_TIME[func_name]['max'] = max(MOD_COUNT_TIME[func_name]['max'], diff) - MOD_COUNT_TIME[func_name]['min'] = min(MOD_COUNT_TIME[func_name]['min'], diff) - MOD_COUNT_TIME[func_name]['total'] += diff - MOD_COUNT_TIME[func_name]['nb'] += 1 + MOD_COUNT_TIME[class_name][func_name]['max'] = max(MOD_COUNT_TIME[class_name][func_name]['max'], diff) + MOD_COUNT_TIME[class_name][func_name]['min'] = min(MOD_COUNT_TIME[class_name][func_name]['min'], diff) + MOD_COUNT_TIME[class_name][func_name]['total'] += diff + MOD_COUNT_TIME[class_name][func_name]['nb'] += 1 #print('%s function took %0.3f ms' % (func_name, diff)) #print(COUNT_TIME) return ret if COUNT_TIME is not False: - COUNT_TIME[func_name] = {'max': 0, - 'min': 1000, - 'nb': 0, - 'total': 0} + COUNT_TIME.setdefault(class_name, {}) + COUNT_TIME[class_name][func_name] = {'max': 0, + 'min': 1000, + 'nb': 0, + 'total': 0} MOD_COUNT_TIME = deepcopy(COUNT_TIME) return wrapper return func @@ -59,19 +67,23 @@ def display_count(): if COUNT_TIME is not False: global MOD_COUNT_TIME #print(MOD_COUNT_TIME) - for func in MOD_COUNT_TIME: - print('>', func) - print('=> nb:', MOD_COUNT_TIME[func]['nb']) - if MOD_COUNT_TIME[func]['nb'] != 0: - print('=> min:', MOD_COUNT_TIME[func]['min']) - print('=> max:', MOD_COUNT_TIME[func]['max']) - print('=> moy:', MOD_COUNT_TIME[func]['total'] / MOD_COUNT_TIME[func]['nb']) + print() + for class_name in MOD_COUNT_TIME: + print('>', class_name) + for func in MOD_COUNT_TIME[class_name]: + print('=>', func) + print('==> nb:', MOD_COUNT_TIME[class_name][func]['nb']) + if MOD_COUNT_TIME[class_name][func]['nb'] != 0: + print('==> min:', MOD_COUNT_TIME[class_name][func]['min']) + print('==> max:', MOD_COUNT_TIME[class_name][func]['max']) + print('==> moy:', MOD_COUNT_TIME[class_name][func]['total'] / MOD_COUNT_TIME[class_name][func]['nb']) MOD_COUNT_TIME = deepcopy(COUNT_TIME) class CommonTiramisuOption(object): icon = '\u2937' tmpl_help = u' {} {}: {}' allow_unrestraint = False + allow_optiondescription = False slave_need_index = True def __init__(self, @@ -82,8 +94,10 @@ class CommonTiramisuOption(object): setting_properties, force_permissive, force_unrestraint): - self.opt = opt - self.path = path + if not self.allow_optiondescription and opt.impl_is_optiondescription(): + raise APIError(_('option must not be an optiondescription')) + self._opt = opt + self._path = path self.index = index if self.slave_need_index: self._test_slave_index() @@ -95,7 +109,8 @@ class CommonTiramisuOption(object): self._unrestraint_not_allowed(force_unrestraint) def _test_slave_index(self): - if self.index is None and self.opt.impl_is_master_slaves('slave'): + if not self._opt.impl_is_optiondescription() and self.index is None and \ + self._opt.impl_is_master_slaves('slave'): raise APIError('index must be set with a slave option') def _unrestraint_not_allowed(self, force_unrestraint): @@ -125,6 +140,7 @@ class CommonTiramisuOption(object): class TiramisuOptionOption(CommonTiramisuOption): """get information from an option""" allow_unrestraint = True + allow_optiondescription = True slave_need_index = False def __init__(self, @@ -145,37 +161,46 @@ class TiramisuOptionOption(CommonTiramisuOption): if config: self.values = self.config.cfgimpl_get_values() + @count def ismulti(self): """test if option could have multi value""" - return self.opt.impl_is_multi() + return self._opt.impl_is_multi() + @count def issubmulti(self): """test if option could have submulti value""" - return self.opt.impl_is_submulti() + return self._opt.impl_is_submulti() + @count def ismasterslaves(self): """test if option is a master or a slave""" - return self.opt.impl_is_master_slaves() + return self._opt.impl_is_master_slaves() + @count def ismaster(self): """test if option is a master""" - return self.opt.impl_is_master_slaves('master') + return self._opt.impl_is_master_slaves('master') + @count def isslave(self): """test if option is a slave""" - return self.opt.impl_is_master_slaves('slave') + return self._opt.impl_is_master_slaves('slave') + @count def getname(self): - return self.opt.impl_getname() + return self._opt.impl_getname() + @count def getdoc(self): - return self.opt.impl_get_display_name() + return self._opt.impl_get_display_name() + @count def getdefault(self): - return self.opt.impl_getdefault() + return self._opt.impl_getdefault() + @count def getdefaultmulti(self): - return self.opt.impl_getdefault_multi() + return self._opt.impl_getdefault_multi() class TiramisuOptionOwner(CommonTiramisuOption): @@ -200,39 +225,46 @@ class TiramisuOptionOwner(CommonTiramisuOption): if config: self.values = self.config.cfgimpl_get_values() + @count def get(self): """get owner for a specified option""" - return self.values.getowner(self.opt, - self.path, - self.setting_properties, + return self.values.getowner(self._opt, + path=self._path, + setting_properties=self.setting_properties, index=self.index, force_permissive=self.force_permissive) @count def isdefault(self): """is option has defaut value""" - return self.values.is_default_owner(self.opt, - self.path, + return self.values.is_default_owner(self._opt, + self._path, self.setting_properties, index=self.index, force_permissive=self.force_permissive) + @count def set(self, owner): """get owner for a specified option""" + if TIRAMISU_VERSION == 2: + if owner in ['default', 'forced', 'meta']: + raise ConfigError() try: obj_owner = getattr(owners, owner) except AttributeError: owners.addowner(owner) obj_owner = getattr(owners, owner) - self.values.setowner(self.opt, - self.path, - obj_owner, - self.index) + self.values.setowner(self._opt, + path=self._path, + owner=obj_owner, + setting_properties=self.setting_properties, + index=self.index) class TiramisuOptionProperty(CommonTiramisuOption): """manager option's property""" #allow_unrestraint = True + allow_optiondescription = True slave_need_index = False def __init__(self, @@ -253,29 +285,49 @@ class TiramisuOptionProperty(CommonTiramisuOption): if config: self.settings = config.cfgimpl_get_settings() + @count def get(self): self._test_slave_index() - return self.settings.getproperties(self.opt, - self.path, - self.setting_properties, - index=self.index) + properties = self.settings.getproperties(self._opt, + self._path, + self.setting_properties, + index=self.index) + if TIRAMISU_VERSION == 2: + properties = properties.get() + return set(properties) + @count def set(self, properties): """set properties for a specified option""" - self.settings.setproperties(self.opt, - self.path, - properties) + properties = frozenset(properties) + self.settings.setproperties(opt=self._opt, + path=self._path, + properties=properties) + @count + def add(self, prop): + props = self.get() + props.add(prop) + self.set(props) + + @count + def pop(self, prop): + props = self.get() + props.remove(prop) + self.set(props) + + @count def reset(self): """reset all personalised properties """ - self.settings.reset(opt=self.opt, - path=self.path) + self.settings.reset(opt=self._opt, + path=self._path) class TiramisuOptionPermissive(CommonTiramisuOption): """manager option's property""" allow_unrestraint = True + allow_optiondescription = True slave_need_index = False def __init__(self, @@ -296,48 +348,47 @@ class TiramisuOptionPermissive(CommonTiramisuOption): if config: self.settings = config.cfgimpl_get_settings() + @count def get(self): """get permissive value for a specified path""" - return self.settings.getpermissive(self.opt, - self.path) + if TIRAMISU_VERSION == 2: + args = [self.setting_properties, self._path] + else: + args = [self._opt, self._path] + return self.settings.getpermissive(*args) + @count def set(self, permissive): - self.settings.setpermissive(self.opt, - self.path, - permissive) + if TIRAMISU_VERSION == 2: + permissive = tuple(permissive) + self.settings.setpermissive(opt=self._opt, + path=self._path, + permissive=permissive) + @count def reset(self, path): """reset all personalised permissive """ self.set(tuple()) +class TiramisuOptionInformation(CommonTiramisuOption): + allow_optiondescription = True + + @count + def get(self, name, default=undefined): + return self._opt.impl_get_information(name, default) + + class TiramisuOptionValue(CommonTiramisuOption): """manager option's value""" slave_need_index = False - def __init__(self, - opt, - path, - index, - config, - setting_properties, - force_permissive, - force_unrestraint): - - super(TiramisuOptionValue, self).__init__(opt, - path, - index, - config, - setting_properties, - force_permissive, - force_unrestraint) - @count def get(self): self._test_slave_index() settings = self.config.cfgimpl_get_settings() - value = self.config.getattr(self.path, + value = self.config.getattr(self._path, index=self.index, setting_properties=self.setting_properties, force_permissive=self.force_permissive) @@ -353,17 +404,17 @@ class TiramisuOptionValue(CommonTiramisuOption): if isinstance(value, list): while undefined in value: idx = value.index(undefined) - value[idx] = values.getdefaultvalue(self.opt, - self.path, + value[idx] = values.getdefaultvalue(self._opt, + self._path, self.setting_properties, idx) else: if value == undefined: - value = values.getdefaultvalue(self.opt, - self.path, + value = values.getdefaultvalue(self._opt, + self._path, self.setting_properties, self.index) - self.config.setattr(self.path, + self.config.setattr(self._path, value, index=self.index, setting_properties=self.setting_properties, @@ -375,27 +426,48 @@ class TiramisuOptionValue(CommonTiramisuOption): """ self._test_slave_index() #FIXME only for master - self.config.delattr(self.path, + self.config.delattr(self._path, index=index, setting_properties=self.setting_properties, force_permissive=self.force_permissive) + @count def reset(self): """reset value for a value""" self._test_slave_index() - self.config.delattr(self.path, + self.config.delattr(self._path, index=self.index, setting_properties=self.setting_properties, force_permissive=self.force_permissive) + @count def len(self): #FIXME only for slave - subconfig_path = self.path.rsplit('.', 1)[0] + subconfig_path = self._path.rsplit('.', 1)[0] subconfig = self.config.getattr(subconfig_path, setting_properties=self.setting_properties, force_permissive=self.force_permissive) return subconfig.cfgimpl_get_length() + def __getattr__(self, name): + if name == 'list': + if isinstance(self._opt, ChoiceOption): + return self._list + raise APIError(_('{} allowed only for choiceoption').format(name)) + + @count + def _list(self): + return self._opt.impl_get_values(context=self.config, + setting_properties=self.setting_properties) + + +def registers(registers, prefix): + for module_name in globals().keys(): + if module_name != prefix and module_name.startswith(prefix): + module = globals()[module_name] + func_name = module_name[len(prefix):].lower() + registers[func_name] = module + class TiramisuOption(object): icon = '\u2937' @@ -410,20 +482,15 @@ class TiramisuOption(object): force_permissive, force_unrestraint): - self.opt = opt - self.path = path + self._opt = opt + self._path = path self.index = index self.config = config self.setting_properties = setting_properties self.force_permissive = force_permissive self.force_unrestraint = force_unrestraint self.registers = {} - self.prefix = self.__class__.__name__ - for module_name in globals().keys(): - if module_name != self.prefix and module_name.startswith(self.prefix): - module = globals()[module_name] - func_name = module_name[len(self.prefix):].lower() - self.registers[func_name] = module + registers(self.registers, self.__class__.__name__) def _help(self): txt = [] @@ -435,8 +502,8 @@ class TiramisuOption(object): def __getattr__(self, subfunc): if subfunc in self.registers: - return self.registers[subfunc](self.opt, - self.path, + return self.registers[subfunc](self._opt, + self._path, self.index, self.config, self.setting_properties, @@ -445,7 +512,21 @@ class TiramisuOption(object): elif subfunc == 'help': return self._help() else: - raise APIError(_('please specify a valid sub function')) + raise APIError(_('please specify a valid sub function ({})').format(subfunc)) + + @count + def make_dict(self, + flatten=False, + withvalue=undefined, + withoption=None, + fullpath=False): + return self.config.getattr(setting_properties=self.setting_properties, + name=self._path).make_dict(setting_properties=self.setting_properties, + flatten=flatten, + fullpath=fullpath, + withoption=withoption, + force_permissive=self.force_permissive, + withvalue=withvalue) class TiramisuContext(object): @@ -461,12 +542,82 @@ class TiramisuContext(object): self.force_unrestraint = force_unrestraint self.setting_properties = setting_properties + +class TiramisuContextInformation(TiramisuContext): + @count + def get(self, name, default=undefined): + return self.config.impl_get_information(name, default) + + @count + def set(self, name, value): + self.config.impl_set_information(name, value) + + @count + def reset(self, name): + self.config.impl_del_information(name) + + +class TiramisuContextValue(TiramisuContext): + @count + def mandatory_warnings(self): + return self.config.cfgimpl_get_values().mandatory_warnings(self.setting_properties) + + @count + def get(self): + return self.config.cfgimpl_get_values().get_modified_values() + + class TiramisuContextOwner(TiramisuContext): + @count def get(self): return self.config.cfgimpl_get_settings().getowner() +class TiramisuContextProperty(TiramisuContext): + @count + def read_only(self): + self.config.cfgimpl_get_settings().read_only() + + @count + def read_write(self): + self.config.cfgimpl_get_settings().read_write() +# #FIXME ? + settings = self.config.cfgimpl_get_settings() + settings.set_context_permissive(frozenset(['hidden'])) + #/FIXME ? + + @count + def add(self, prop): + props = self.get() + props.add(prop) + self.set(props) + + @count + def pop(self, prop): + props = self.get() + props.remove(prop) + self.set(props) + + @count + def get(self): + return set(self.config.cfgimpl_get_settings().get_context_properties()) + + @count + def set(self, props): + self.config.cfgimpl_get_settings().set_context_properties(frozenset(props)) + + +class TiramisuContextPermissive(TiramisuContext): + + @count + def set(self, permissives): + if TIRAMISU_VERSION != 2: + permissives = frozenset(permissives) + self.config.cfgimpl_get_settings().set_context_permissive(permissives) + + class TiramisuContextOption(TiramisuContext): + @count def find_first(self, name, type='option'): @@ -477,6 +628,7 @@ class TiramisuContextOption(TiramisuContext): force_permissive=self.force_permissive, check_properties=not self.force_unrestraint) + @count def find(self, name, type='option'): @@ -486,19 +638,33 @@ class TiramisuContextOption(TiramisuContext): force_permissive=self.force_permissive, check_properties=not self.force_unrestraint) + @count def get(self, path): return self.config.unwrap_from_path(path, validate=False, validate_properties=False) + @count + def make_dict(self, + flatten=False, + withvalue=undefined, + withoption=None, + fullpath=False): + return self.config.make_dict(setting_properties=self.setting_properties, + flatten=flatten, + fullpath=fullpath, + force_permissive=self.force_permissive, + withoption=withoption, + withvalue=withvalue) -class TiramisuOptionDispatcher(TiramisuContextOption): + +class TiramisuDispatcherOption(TiramisuContextOption): def __init__(self, config, force_permissive, force_unrestraint): self.setting_properties = config.cfgimpl_get_settings().get_context_properties() - super(TiramisuOptionDispatcher, self).__init__(config, + super(TiramisuDispatcherOption, self).__init__(config, force_permissive, force_unrestraint, self.setting_properties) @@ -538,32 +704,6 @@ class TiramisuOptionDispatcher(TiramisuContextOption): self.force_unrestraint) -class TiramisuContextConfig(TiramisuContext): - def make_dict(self): - return self.config.make_dict(self.setting_properties) - - -class TiramisuConfigDispatcher(TiramisuContextConfig): - def __init__(self, - config, - force_permissive, - force_unrestraint): - self.setting_properties = config.cfgimpl_get_settings().get_context_properties() - super(TiramisuConfigDispatcher, self).__init__(config, - force_permissive, - force_unrestraint, - self.setting_properties) - - def __call__(self, path): - if path is None: - subconfig = self.config - else: - subconfig = self.config.getconfig(path) - return TiramisuAPI(subconfig, - force_permissive=self.force_permissive, - force_unrestraint=self.force_unrestraint) - - class TiramisuAPI(object): icon = '\u2937' tmpl_help = ' {} {}: {}' @@ -575,6 +715,9 @@ class TiramisuAPI(object): self._config = config self.force_permissive = force_permissive self.force_unrestraint = force_unrestraint + self.registers = {} + registers(self.registers, 'TiramisuContext') + registers(self.registers, 'TiramisuDispatcher') def __getattr__(self, subfunc): if subfunc == 'forcepermissive': @@ -585,20 +728,16 @@ class TiramisuAPI(object): return TiramisuAPI(self._config, force_permissive=self.force_permissive, force_unrestraint=True) + elif subfunc == 'config': + return TiramisuAPI(self._config, + force_permissive=self.force_permissive, + force_unrestraint=True) elif subfunc == 'help': return self._help() - elif subfunc == 'owner': - return TiramisuContextOwner(self._config, - self.force_permissive, - self.force_unrestraint) - elif subfunc == 'config': - return TiramisuConfigDispatcher(self._config, - force_permissive=self.force_permissive, - force_unrestraint=self.force_unrestraint) - elif subfunc == 'option': - return TiramisuOptionDispatcher(self._config, - force_permissive=self.force_permissive, - force_unrestraint=self.force_unrestraint) + elif subfunc in self.registers: + return self.registers[subfunc](self._config, + force_permissive=self.force_permissive, + force_unrestraint=self.force_unrestraint) else: raise APIError(_('please specify a valid sub function ({})').format(subfunc)) @@ -610,17 +749,8 @@ class TiramisuAPI(object): txt.append(module(None, None).help) return '\n'.join(txt) - def read_only(self): - self._config.read_write() - - def read_write(self): - settings = self._config.cfgimpl_get_settings() - self._config.read_write() -# #FIXME ? - settings.set_context_permissive(frozenset(['hidden'])) - #/FIXME ? - +@count def getapi(config): """instanciate TiramisuAPI diff --git a/tiramisu/autolib.py b/tiramisu/autolib.py index c920be9..81d1b18 100644 --- a/tiramisu/autolib.py +++ b/tiramisu/autolib.py @@ -30,7 +30,7 @@ def carry_out_calculation(option, context, callback, callback_params, - setting_properties=undefined, + setting_properties, index=undefined, validate=True, is_validator=False): diff --git a/tiramisu/config.py b/tiramisu/config.py index 4c8257e..9c55133 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -86,6 +86,10 @@ class SubConfig(object): master = descr.getmaster() context_ = context() masterp = master.impl_getpath(context_) + context_.cfgimpl_get_settings().validate_properties(master, + masterp, + setting_properties, + force_permissive=force_permissive) value = context_.cfgimpl_get_values().get_cached_value(master, masterp, setting_properties, @@ -104,6 +108,7 @@ class SubConfig(object): resetted_opts, opt, path): + tresetted_opts = copy(resetted_opts) opt.reset_cache(opt, path, @@ -121,7 +126,7 @@ class SubConfig(object): option = woption() if option in resetted_opts: continue - option_path = opt.impl_getpath(self) + option_path = option.impl_getpath(self) self.reset_one_option_cache(values, settings, resetted_opts, @@ -139,17 +144,6 @@ class SubConfig(object): :param only_expired: if True reset only expired cached values :type only_expired: boolean """ - - def reset_expired_cache(): - # reset cache for expired cache value ony - datetime = int(time()) - values._p_.reset_expired_cache(datetime) - settings._p_.reset_expired_cache(datetime) - - def reset_all_cache(): - values._p_.reset_all_cache() - settings._p_.reset_all_cache() - if resetted_opts is None: resetted_opts = set() @@ -166,9 +160,13 @@ class SubConfig(object): path) elif only_expired: - reset_expired_cache() + # reset cache for expired cache value ony + datetime = int(time()) + values._p_.reset_expired_cache(datetime) + settings._p_.reset_expired_cache(datetime) else: - reset_all_cache() + values._p_.reset_all_cache() + settings._p_.reset_all_cache() def cfgimpl_get_home_by_path(self, path, @@ -676,7 +674,7 @@ class SubConfig(object): setting_properties=setting_properties): path = '.'.join(path.split('.')[:-1]) opt = context.unwrap_from_path(path, - orce_permissive=True) + force_permissive=True) mypath = self.cfgimpl_get_path() if mypath is not None: if mypath == path: @@ -717,7 +715,7 @@ class SubConfig(object): def _make_sub_dict(self, option, - path, + name, pathsvalues, _currpath, flatten, @@ -730,17 +728,18 @@ class SubConfig(object): length = self.cfgimpl_get_length() if length: for idx in range(length): - ret.append(self.getattr(path, + ret.append(self.getattr(name, index=idx, force_permissive=force_permissive, setting_properties=setting_properties)) elif setting_properties: + path = self._get_subpath(name) self.cfgimpl_get_settings().validate_properties(option, path, setting_properties, force_permissive=force_permissive) else: - ret = self.getattr(path, + ret = self.getattr(name, force_permissive=force_permissive, setting_properties=setting_properties) except PropertiesOptionError: @@ -749,7 +748,7 @@ class SubConfig(object): if option.impl_is_optiondescription(): pathsvalues += ret.make_dict(setting_properties, flatten=flatten, - _currpath=_currpath + path.split('.'), + _currpath=_currpath + [name], force_permissive=force_permissive, fullpath=fullpath) else: @@ -764,7 +763,7 @@ class SubConfig(object): # name = '.'.join([root_path, opt.impl_getname()]) name = self._get_subpath(name) else: - name = '.'.join(_currpath + [option.impl_getname()]) + name = '.'.join(_currpath + [name]) pathsvalues.append((name, ret)) def cfgimpl_get_path(self, @@ -789,30 +788,6 @@ class _CommonConfig(SubConfig): descr.impl_build_force_store_values(self, force_store_values) - def read_only(self): - "read only is a global config's setting, see `settings.py`" - self.cfgimpl_get_settings().read_only() - - def read_write(self): - "read write is a global config's setting, see `settings.py`" - self.cfgimpl_get_settings().read_write() - - def getowner(self, - opt, - index=None, - force_permissive=False): - """convenience method to retrieve an option's owner - from the config itself - """ - if not isinstance(opt, Option) and \ - not isinstance(opt, SymLinkOption) and \ - not isinstance(opt, DynSymLinkOption): # pragma: optional cover - raise TypeError(_('opt in getowner must be an option not {0}' - '').format(type(opt))) - return self.cfgimpl_get_values().getowner(opt, - index=index, - force_permissive=force_permissive) - def unwrap_from_path(self, path, setting_properties=None, @@ -847,7 +822,8 @@ class _CommonConfig(SubConfig): else: true_option = option true_path = path - if index is None and true_option.impl_is_master_slaves('slave'): + if not true_option.impl_is_optiondescription() and index is None and \ + true_option.impl_is_master_slaves('slave'): subpath = self._get_subpath(true_path) self.cfgimpl_get_settings().validate_properties(true_option, subpath, diff --git a/tiramisu/error.py b/tiramisu/error.py index ef02c5b..e2811ce 100644 --- a/tiramisu/error.py +++ b/tiramisu/error.py @@ -16,7 +16,6 @@ # ____________________________________________________________ "user defined exceptions" from .i18n import _ -import sys def display_list(lst, separator='and'): @@ -28,28 +27,22 @@ def display_list(lst, separator='and'): return '' elif len(lst) == 1: ret = lst[0] - if sys.version_info[0] < 3 and isinstance(ret, unicode): - ret = ret.encode('utf8') if not isinstance(ret, str): ret = str(ret) - return ret + return '"{}"'.format(ret) else: if isinstance(lst, tuple): lst = list(lst) lst.sort() lst_ = [] for l in lst[:-1]: - if sys.version_info[0] < 3 and isinstance(l, unicode): - l = l.encode('utf8') - elif not isinstance(l, str): + if not isinstance(l, str): l = str(l) lst_.append(l) last = lst[-1] - if sys.version_info[0] < 3 and isinstance(last, unicode): - last = last.encode('utf8') if not isinstance(last, str): last = str(last) - return ', '.join(lst_) + _(' {} ').format(separator) + last + return ', '.join(lst_) + _(' "{}" ').format(separator) + last # Exceptions for an Option diff --git a/tiramisu/option/baseoption.py b/tiramisu/option/baseoption.py index eeb9033..9d42e96 100644 --- a/tiramisu/option/baseoption.py +++ b/tiramisu/option/baseoption.py @@ -56,17 +56,10 @@ def validate_callback(callback, """ def _validate_option(option): #validate option - #FIXME etrange ... - if hasattr(option, 'impl_is_symlinkoption'): - if option.impl_is_symlinkoption(): - cur_opt = option.impl_getopt() - else: - cur_opt = option + if option.impl_is_symlinkoption(): + cur_opt = option.impl_getopt() else: - raise ValueError(_('{}_params must have an option' - ' not a {} for first argument' - ).format(type_, - type(option))) + cur_opt = option if cur_opt != callbackoption: cur_opt._add_dependency(callbackoption) callbackoption._has_dependency = True @@ -406,7 +399,7 @@ class BaseOption(Base): def _impl_valid_string(self, value): if not isinstance(value, str): - return ValueError(_('invalid string')) + raise ValueError(_('invalid string')) def impl_get_display_name(self, dyn_name=None): @@ -498,7 +491,7 @@ def validate_requires_arg(new_option, option = exp['option'] option._add_dependency(new_option) if option is not None: - err = option._validate(exp['value']) + err = option._validate(exp['value'], undefined) if err: raise ValueError(_('malformed requirements expected value ' 'must be valid for option {0}' @@ -513,7 +506,7 @@ def validate_requires_arg(new_option, else: option = get_option(require) if expected is not None: - err = option._validate(expected) + err = option._validate(expected, undefined) if err: raise ValueError(_('malformed requirements expected value ' 'must be valid for option {0}' diff --git a/tiramisu/option/booloption.py b/tiramisu/option/booloption.py index 49f3a54..ade8075 100644 --- a/tiramisu/option/booloption.py +++ b/tiramisu/option/booloption.py @@ -29,6 +29,10 @@ class BoolOption(Option): __slots__ = tuple() _display_name = _('boolean') - def _validate(self, value, context=undefined, current_opt=undefined): + def _validate(self, + value, + setting_properties, + context=undefined, + current_opt=undefined): if not isinstance(value, bool): - return ValueError() + raise ValueError() diff --git a/tiramisu/option/broadcastoption.py b/tiramisu/option/broadcastoption.py index f3fc8b8..ec0a569 100644 --- a/tiramisu/option/broadcastoption.py +++ b/tiramisu/option/broadcastoption.py @@ -30,26 +30,36 @@ class BroadcastOption(Option): __slots__ = tuple() _display_name = _('broadcast address') - def _validate(self, value, context=undefined, current_opt=undefined): - err = self._impl_valid_string(value) - if err: - return err + def _validate(self, + value, + setting_properties, + context=undefined, + current_opt=undefined): + self._impl_valid_string(value) if value.count('.') != 3: - return ValueError() + raise ValueError() for val in value.split('.'): if val.startswith("0") and len(val) > 1: - return ValueError() + raise ValueError() try: IP('{0}/32'.format(value)) except ValueError: - return ValueError() + raise ValueError() - def _cons_broadcast(self, current_opt, opts, vals, warnings_only): + def _cons_broadcast(self, + current_opt, + opts, + vals, + warnings_only): if len(vals) != 3: return ConfigError(_('invalid len for vals')) if None in vals: return broadcast, network, netmask = vals if IP('{0}/{1}'.format(network, netmask)).broadcast() != IP(broadcast): - return ValueError(_('broadcast {4} invalid with network {0}/{1} ({2}/{3})').format( - network, netmask, opts[1].impl_getname(), opts[2].impl_getname(), broadcast)) + raise ValueError(_('broadcast "{4}" invalid with network {0}/{1} ("{2}"/"{3}")' + '').format(network, + netmask, + opts[1].impl_get_display_name(), + opts[2].impl_get_display_name(), + broadcast)) diff --git a/tiramisu/option/choiceoption.py b/tiramisu/option/choiceoption.py index 32895c3..4fc9f7b 100644 --- a/tiramisu/option/choiceoption.py +++ b/tiramisu/option/choiceoption.py @@ -36,16 +36,30 @@ class ChoiceOption(Option): __slots__ = tuple() _display_name = _('choice') - def __init__(self, name, doc, values, default=None, - values_params=None, default_multi=None, requires=None, - multi=False, callback=None, callback_params=None, - validator=None, validator_params=None, - properties=None, warnings_only=False): + def __init__(self, + name, + doc, + values, + default=None, + values_params=None, + default_multi=None, + requires=None, + multi=False, + callback=None, + callback_params=None, + validator=None, + validator_params=None, + properties=None, + warnings_only=False): + """ :param values: is a list of values the option can possibly take """ if isinstance(values, FunctionType): - validate_callback(values, values_params, 'values', self) + validate_callback(values, + values_params, + 'values', + self) else: if values_params is not None: raise ValueError(_('values is not a function, so values_params must be None')) @@ -55,7 +69,9 @@ class ChoiceOption(Option): self._choice_values = values if values_params is not None: self._choice_values_params = values_params - super(ChoiceOption, self).__init__(name, doc, default=default, + super(ChoiceOption, self).__init__(name, + doc, + default=default, default_multi=default_multi, callback=callback, callback_params=callback_params, @@ -66,7 +82,10 @@ class ChoiceOption(Option): properties=properties, warnings_only=warnings_only) - def impl_get_values(self, context, current_opt=undefined): + def impl_get_values(self, + setting_properties, + context, + current_opt=undefined): if current_opt is undefined: current_opt = self #FIXME cache? but in context... @@ -75,25 +94,29 @@ class ChoiceOption(Option): if context is None: values = [] else: - values = carry_out_calculation(current_opt, context=context, + values = carry_out_calculation(current_opt, + setting_properties=setting_properties, + context=context, callback=values, callback_params=getattr(self, '_choice_values_params', {})) - if isinstance(values, Exception): - return values if values is not undefined and not isinstance(values, list): raise ConfigError(_('calculated values for {0} is not a list' '').format(self.impl_getname())) return values - def _validate(self, value, context=undefined, current_opt=undefined): - values = self.impl_get_values(context, current_opt=current_opt) - if isinstance(values, Exception): - return values + def _validate(self, + value, + setting_properties, + context=undefined, + current_opt=undefined): + values = self.impl_get_values(setting_properties, + context, + current_opt=current_opt) if values is not undefined and not value in values: if len(values) == 1: - return ValueError(_('only {0} is allowed' - '').format(values[0])) + raise ValueError(_('only {0} is allowed' + '').format(values[0])) else: - return ValueError(_('only {0} are allowed' - '').format(display_list(values))) + raise ValueError(_('only {0} are allowed' + '').format(display_list(values))) diff --git a/tiramisu/option/dateoption.py b/tiramisu/option/dateoption.py index 3e2b0ea..f7ce4b9 100644 --- a/tiramisu/option/dateoption.py +++ b/tiramisu/option/dateoption.py @@ -29,11 +29,13 @@ class DateOption(Option): __slots__ = tuple() _display_name = _('date') - def _validate(self, value, context=undefined, current_opt=undefined): - err = self._impl_valid_string(value) - if err: - return err + def _validate(self, + value, + setting_properties, + context=undefined, + current_opt=undefined): + self._impl_valid_string(value) try: datetime.strptime(value, "%Y-%m-%d") except ValueError: - return ValueError() + raise ValueError() diff --git a/tiramisu/option/domainnameoption.py b/tiramisu/option/domainnameoption.py index 3e12755..979e986 100644 --- a/tiramisu/option/domainnameoption.py +++ b/tiramisu/option/domainnameoption.py @@ -36,11 +36,23 @@ class DomainnameOption(Option): __slots__ = tuple() _display_name = _('domain name') - def __init__(self, name, doc, default=None, default_multi=None, - requires=None, multi=False, callback=None, - callback_params=None, validator=None, validator_params=None, - properties=None, allow_ip=False, type_='domainname', - warnings_only=False, allow_without_dot=False): + def __init__(self, + name, + doc, + default=None, + default_multi=None, + requires=None, + multi=False, + callback=None, + callback_params=None, + validator=None, + validator_params=None, + properties=None, + allow_ip=False, + type_='domainname', + warnings_only=False, + allow_without_dot=False): + if type_ not in ['netbios', 'hostname', 'domainname']: raise ValueError(_('unknown type_ {0} for hostname').format(type_)) extra = {'_dom_type': type_} @@ -50,8 +62,6 @@ class DomainnameOption(Option): raise ValueError(_('allow_without_dot must be a boolean')) extra['_allow_ip'] = allow_ip extra['_allow_without_dot'] = allow_without_dot - # FIXME should be - # regexp = r'^((?!-)[a-z0-9-]{1,63}(? part_name_length: - return ValueError(_("invalid length (max {0})" + raise ValueError(_("invalid length (max {0})" "").format(part_name_length)) if self._get_extra('_allow_ip') is True: try: IP('{0}/32'.format(value)) - return except ValueError: pass + else: + return else: try: IP('{0}/32'.format(value)) except ValueError: pass else: - return ValueError(_('must not be an IP')) + raise ValueError(_('must not be an IP')) part_name_length = self._get_len(self._get_extra('_dom_type')) if self._get_extra('_dom_type') == 'domainname': if not self._get_extra('_allow_without_dot') and not "." in value: - return ValueError(_("must have dot")) + raise ValueError(_("must have dot")) if len(value) > 255: - return ValueError(_("invalid length (max 255)")) + raise ValueError(_("invalid length (max 255)")) for dom in value.split('.'): - err = _valid_length(dom) - if err: - return err + _valid_length(dom) else: - return _valid_length(value) + _valid_length(value) def _second_level_validation(self, value, warnings_only): if self._get_extra('_has_upper').search(value): - return ValueError(_('some characters are uppercase')) + raise ValueError(_('some characters are uppercase')) if not self._get_extra('_domain_re').search(value): if warnings_only: - return ValueError(_('some characters may cause problems')) + raise ValueError(_('some characters may cause problems')) else: - return ValueError() + raise ValueError() diff --git a/tiramisu/option/floatoption.py b/tiramisu/option/floatoption.py index 9d2c6fc..5518fcf 100644 --- a/tiramisu/option/floatoption.py +++ b/tiramisu/option/floatoption.py @@ -29,6 +29,10 @@ class FloatOption(Option): __slots__ = tuple() _display_name = _('float') - def _validate(self, value, context=undefined, current_opt=undefined): + def _validate(self, + value, + setting_properties, + context=undefined, + current_opt=undefined): if not isinstance(value, float): - return ValueError() + raise ValueError() diff --git a/tiramisu/option/intoption.py b/tiramisu/option/intoption.py index fb47ef6..616d9a0 100644 --- a/tiramisu/option/intoption.py +++ b/tiramisu/option/intoption.py @@ -29,6 +29,10 @@ class IntOption(Option): __slots__ = tuple() _display_name = _('integer') - def _validate(self, value, context=undefined, current_opt=undefined): + def _validate(self, + value, + setting_properties, + context=undefined, + current_opt=undefined): if not isinstance(value, int): - return ValueError() + raise ValueError() diff --git a/tiramisu/option/ipoption.py b/tiramisu/option/ipoption.py index d49297b..c2b084d 100644 --- a/tiramisu/option/ipoption.py +++ b/tiramisu/option/ipoption.py @@ -31,14 +31,26 @@ class IPOption(Option): __slots__ = tuple() _display_name = _('IP') - def __init__(self, name, doc, default=None, default_multi=None, - requires=None, multi=False, callback=None, - callback_params=None, validator=None, validator_params=None, - properties=None, private_only=False, allow_reserved=False, + def __init__(self, + name, + doc, + default=None, + default_multi=None, + requires=None, + multi=False, + callback=None, + callback_params=None, + validator=None, + validator_params=None, + properties=None, + private_only=False, + allow_reserved=False, warnings_only=False): extra = {'_private_only': private_only, '_allow_reserved': allow_reserved} - super(IPOption, self).__init__(name, doc, default=default, + super(IPOption, self).__init__(name, + doc, + default=default, default_multi=default_multi, callback=callback, callback_params=callback_params, @@ -50,47 +62,62 @@ class IPOption(Option): warnings_only=warnings_only, extra=extra) - def _validate(self, value, context=undefined, current_opt=undefined): + def _validate(self, + value, + setting_properties, + context=undefined, + current_opt=undefined): # sometimes an ip term starts with a zero # but this does not fit in some case, for example bind does not like it - err = self._impl_valid_string(value) - if err: - return err + self._impl_valid_string(value) if value.count('.') != 3: - return ValueError() + raise ValueError() for val in value.split('.'): if val.startswith("0") and len(val) > 1: - return ValueError() + raise ValueError() # 'standard' validation try: IP('{0}/32'.format(value)) except ValueError: - return ValueError() + raise ValueError() - def _second_level_validation(self, value, warnings_only): + def _second_level_validation(self, + value, + warnings_only): ip = IP('{0}/32'.format(value)) if not self._get_extra('_allow_reserved') and ip.iptype() == 'RESERVED': if warnings_only: msg = _("shouldn't in reserved class") else: msg = _("mustn't be in reserved class") - return ValueError(msg) + raise ValueError(msg) if self._get_extra('_private_only') and ip.iptype() != 'PRIVATE': if warnings_only: msg = _("should be in private class") else: msg = _("must be in private class") - return ValueError(msg) + raise ValueError(msg) - def _cons_in_network(self, current_opt, opts, vals, warnings_only): + def _cons_in_network(self, + current_opt, + opts, + vals, + warnings_only): if len(vals) != 3: return ConfigError(_('invalid len for vals')) if None in vals: return ip, network, netmask = vals - if IP(ip) not in IP('{0}/{1}'.format(network, netmask)): - msg = _('{4} is not in network {0}/{1} ({2}/{3})') - return ValueError(msg.format(network, netmask, - opts[1].impl_getname(), opts[2].impl_getname(), ip)) + if IP(ip) not in IP('{0}/{1}'.format(network, + netmask)): + msg = _('"{4}" is not in network "{0}"/"{1}" ("{2}"/"{3}")') + raise ValueError(msg.format(network, + netmask, + opts[1].impl_get_display_name(), + opts[2].impl_getname(), + ip)) # test if ip is not network/broadcast IP - return opts[2]._cons_ip_netmask(current_opt, (opts[2], opts[0]), (netmask, ip), warnings_only) + opts[2]._cons_ip_netmask(current_opt, + (opts[2], opts[0]), + (netmask, ip), + warnings_only) diff --git a/tiramisu/option/masterslave.py b/tiramisu/option/masterslave.py index dd393ac..2e8af43 100644 --- a/tiramisu/option/masterslave.py +++ b/tiramisu/option/masterslave.py @@ -175,7 +175,7 @@ class MasterSlaves(OptionDescription): context): if option.impl_is_master_slaves('master') and isinstance(value, list): if len(value) < context._impl_length: - return ValueError(_('cannot reduce length of master "{}"' + raise ValueError(_('cannot reduce length of master "{}"' '').format(option.impl_get_display_name())) def is_masterslaves(self): diff --git a/tiramisu/option/netmaskoption.py b/tiramisu/option/netmaskoption.py index 4dc154e..86f652b 100644 --- a/tiramisu/option/netmaskoption.py +++ b/tiramisu/option/netmaskoption.py @@ -31,50 +31,72 @@ class NetmaskOption(Option): __slots__ = tuple() _display_name = _('netmask address') - def _validate(self, value, context=undefined, current_opt=undefined): - err = self._impl_valid_string(value) - if err: - return err + def _validate(self, + value, + setting_properties, + context=undefined, + current_opt=undefined): + self._impl_valid_string(value) if value.count('.') != 3: - return ValueError() + raise ValueError() for val in value.split('.'): if val.startswith("0") and len(val) > 1: - return ValueError() + raise ValueError() try: IP('0.0.0.0/{0}'.format(value)) except ValueError: - return ValueError() + raise ValueError() - def _cons_network_netmask(self, current_opt, opts, vals, warnings_only): + def _cons_network_netmask(self, + current_opt, + opts, + vals, + warnings_only): #opts must be (netmask, network) options if None in vals: return - return self.__cons_netmask(opts, vals[0], vals[1], False, warnings_only) + return self.__cons_netmask(opts, + vals[0], + vals[1], + False, + warnings_only) - def _cons_ip_netmask(self, current_opt, opts, vals, warnings_only): + def _cons_ip_netmask(self, + current_opt, + opts, + vals, + warnings_only): #opts must be (netmask, ip) options if None in vals: return - return self.__cons_netmask(opts, vals[0], vals[1], True, warnings_only) + self.__cons_netmask(opts, + vals[0], + vals[1], + True, + warnings_only) - def __cons_netmask(self, opts, val_netmask, val_ipnetwork, make_net, + def __cons_netmask(self, + opts, + val_netmask, + val_ipnetwork, + make_net, warnings_only): if len(opts) != 2: return ConfigError(_('invalid len for opts')) msg = None try: - ip = IP('{0}/{1}'.format(val_ipnetwork, val_netmask), - make_net=make_net) + ip = IP('{0}/{1}'.format(val_ipnetwork, val_netmask), make_net=make_net) #if cidr == 32, ip same has network if make_net and ip.prefixlen() != 32: val_ip = IP(val_ipnetwork) if ip.net() == val_ip: - msg = _("this is a network with netmask {0} ({1})") + msg = _('this is a network with netmask "{0}" ("{1}")') if ip.broadcast() == val_ip: - msg = _("this is a broadcast with netmask {0} ({1})") + msg = _('this is a broadcast with netmask "{0}" ("{1}")') except ValueError: if not make_net: - msg = _('with netmask {0} ({1})') + msg = _('with netmask "{0}" ("{1}")') if msg is not None: - return ValueError(msg.format(val_netmask, opts[1].impl_getname())) + raise ValueError(msg.format(val_netmask, + opts[1].impl_get_diplay_name())) diff --git a/tiramisu/option/networkoption.py b/tiramisu/option/networkoption.py index 7733831..b5b2359 100644 --- a/tiramisu/option/networkoption.py +++ b/tiramisu/option/networkoption.py @@ -30,25 +30,29 @@ class NetworkOption(Option): __slots__ = tuple() _display_name = _('network address') - def _validate(self, value, context=undefined, current_opt=undefined): - err = self._impl_valid_string(value) - if err: - return err + def _validate(self, + value, + setting_properties, + context=undefined, + current_opt=undefined): + self._impl_valid_string(value) if value.count('.') != 3: - return ValueError() + raise ValueError() for val in value.split('.'): if val.startswith("0") and len(val) > 1: - return ValueError() + raise ValueError() try: IP(value) except ValueError: - return ValueError() + raise ValueError() - def _second_level_validation(self, value, warnings_only): + def _second_level_validation(self, + value, + warnings_only): ip = IP(value) if ip.iptype() == 'RESERVED': if warnings_only: msg = _("shouldn't be in reserved class") else: msg = _("mustn't be in reserved class") - return ValueError(msg) + raise ValueError(msg) diff --git a/tiramisu/option/option.py b/tiramisu/option/option.py index 6705dfc..279bf75 100644 --- a/tiramisu/option/option.py +++ b/tiramisu/option/option.py @@ -133,7 +133,8 @@ class Option(OnlyOption): is_multi=is_multi) if is_multi and default_multi is not None: def test_multi_value(value): - err = self._validate(value) + err = self._validate(value, + undefined) if err: raise ValueError(_("invalid default_multi value {0} " "for option {1}: {2}").format(str(value), @@ -152,10 +153,8 @@ class Option(OnlyOption): _setattr(self, '_default_multi', default_multi) if unique is not undefined: _setattr(self, '_unique', unique) - err = self.impl_validate(default, - is_multi=is_multi) - if err: - raise err + self.impl_validate(default, + is_multi=is_multi) if (is_multi and default != []) or \ (not is_multi and default is not None): if is_multi: @@ -300,8 +299,7 @@ class Option(OnlyOption): force_index=None, current_opt=undefined, is_multi=None, - display_error=True, - display_warnings=True, + check_error=True, multi=None, setting_properties=undefined): """ @@ -315,14 +313,13 @@ class Option(OnlyOption): """ if current_opt is undefined: current_opt = self - - if display_warnings and setting_properties is undefined and context is not undefined: - setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=False) - display_warnings = display_warnings and (setting_properties is undefined or 'warnings' in setting_properties) + + if check_error is False and not 'warnings' in setting_properties: + return def _is_not_unique(value): #FIXME pourquoi la longueur doit etre egal ??? - if display_error and self.impl_is_unique() and len(set(value)) != len(value): + if check_error and self.impl_is_unique() and len(set(value)) != len(value): for idx, val in enumerate(value): if val in value[idx+1:]: raise ValueError(_('invalid value "{}", this value is already in "{}"' @@ -361,16 +358,18 @@ class Option(OnlyOption): raise ValueError(_('invalid value "{}" for "{}" ' 'which must not be a list').format(_value, self.impl_get_display_name())) + #FIXME a revoir ... is_warnings_only = getattr(self, '_warnings_only', False) try: if _value is not None: - if display_error: + if check_error: # option validation self._validate(_value, + setting_properties, context, current_opt) - if ((display_error and not is_warnings_only) or - (display_warnings and is_warnings_only)): + if ((check_error and not is_warnings_only) or + (not check_error and is_warnings_only)): calculation_validator(_value, _index) self._second_level_validation(_value, @@ -379,8 +378,7 @@ class Option(OnlyOption): _value, context, _index, - display_warnings, - display_error, + check_error, setting_properties) except ValueError as err: if debug: # pragma: no cover @@ -402,12 +400,12 @@ class Option(OnlyOption): err_msg = '{0}'.format(err) if err_msg: msg += ', {}'.format(err_msg) - if is_warnings_only: + if check_error: + raise ValueError(msg) + else: warnings.warn_explicit(ValueWarning(msg, self), ValueWarning, self.__class__.__name__, 0) - else: - raise ValueError(msg) if is_multi is None: is_multi = self.impl_is_multi() @@ -563,10 +561,10 @@ class Option(OnlyOption): all_cons_opts, params) #validate default value when add consistency - err = self.impl_validate(self.impl_getdefault()) - if err: - self._del_consistency() - raise err + self.impl_validate(self.impl_getdefault()) + #FIXME + #if err: + # self._del_consistency() if func != '_cons_not_equal': #consistency could generate warnings or errors self._has_dependency = True @@ -584,8 +582,7 @@ class Option(OnlyOption): value, context, index, - display_warnings, - display_error, + check_error, setting_properties): if context is not undefined: descr = context.cfgimpl_get_description() @@ -601,7 +598,7 @@ class Option(OnlyOption): if consistencies is not None: for func, all_cons_opts, params in consistencies: warnings_only = params.get('warnings_only', False) - if (warnings_only and display_warnings) or (not warnings_only and display_error): + if (warnings_only and not check_error) or (not warnings_only and check_error): transitive = params.get('transitive', True) #all_cons_opts[0] is the option where func is set if isinstance(option, DynSymLinkOption): @@ -745,6 +742,7 @@ class RegexpOption(Option): def _validate(self, value, + setting_properties, context=undefined, current_opt=undefined): err = self._impl_valid_string(value) diff --git a/tiramisu/option/optiondescription.py b/tiramisu/option/optiondescription.py index df333bb..d8e222d 100644 --- a/tiramisu/option/optiondescription.py +++ b/tiramisu/option/optiondescription.py @@ -99,7 +99,7 @@ class CacheOptionDescription(BaseOption): params)) # if context is set to callback, must be reset each time a value change if hasattr(option, '_has_calc_context'): - _dependencies.append(option) + self._add_dependency(option) is_slave = None if is_multi: all_requires = option.impl_getrequires() @@ -150,10 +150,10 @@ class CacheOptionDescription(BaseOption): return False def impl_build_force_store_values(self, - config, + context, force_store_values): - session = config._impl_values._p_.getsession() - value_set = False + value_setted = False + values = context.cfgimpl_get_values() for subpath, option in self._cache_force_store_values: if option.impl_is_master_slaves('slave'): # problem with index @@ -162,19 +162,24 @@ class CacheOptionDescription(BaseOption): if option._is_subdyn(): raise ConfigError(_('a dynoption ({0}) cannot have ' 'force_store_value property').format(subpath)) - if force_store_values and not config._impl_values._p_.hasvalue(subpath, session): - value = impl_build_force_store_values.getvalue(option, - subpath, - index=None, - setting_properties=undefined, - self_properties=undefined, - validate=False) - value_set = True - config._impl_values._p_.setvalue(subpath, value, - owners.forced, None, session, False) + if force_store_values is False: + raise Exception('ok ca existe ...') + if force_store_values and not values._p_.hasvalue(subpath): + value = values.getvalue(option, + subpath, + index=None, + setting_properties=None, + self_properties=None, + validate=False) + value_setted = True + values._p_.setvalue(subpath, + value, + owners.forced, + None, + False) - if value_set: - config._impl_values._p_.commit() + if value_setted: + values._p_.commit() def _build_cache_option(self, _currpath=None, diff --git a/tiramisu/option/passwordoption.py b/tiramisu/option/passwordoption.py index 38d8f5b..cb40d0d 100644 --- a/tiramisu/option/passwordoption.py +++ b/tiramisu/option/passwordoption.py @@ -29,7 +29,9 @@ class PasswordOption(Option): __slots__ = tuple() _display_name = _('password') - def _validate(self, value, context=undefined, current_opt=undefined): - err = self._impl_valid_string(value) - if err: - return err + def _validate(self, + value, + setting_properties, + context=undefined, + current_opt=undefined): + self._impl_valid_string(value) diff --git a/tiramisu/option/portoption.py b/tiramisu/option/portoption.py index 6f55252..005a1e8 100644 --- a/tiramisu/option/portoption.py +++ b/tiramisu/option/portoption.py @@ -40,12 +40,25 @@ class PortOption(Option): port_re = re.compile(r"^[0-9]*$") _display_name = _('port') - def __init__(self, name, doc, default=None, default_multi=None, - requires=None, multi=False, callback=None, - callback_params=None, validator=None, validator_params=None, - properties=None, allow_range=False, allow_zero=False, - allow_wellknown=True, allow_registred=True, - allow_private=False, warnings_only=False): + def __init__(self, + name, + doc, + default=None, + default_multi=None, + requires=None, + multi=False, + callback=None, + callback_params=None, + validator=None, + validator_params=None, + properties=None, + allow_range=False, + allow_zero=False, + allow_wellknown=True, + allow_registred=True, + allow_private=False, + warnings_only=False): + extra = {'_allow_range': allow_range, '_min_value': None, '_max_value': None} @@ -69,7 +82,9 @@ class PortOption(Option): if extra['_max_value'] is None: raise ValueError(_('max value is empty')) - super(PortOption, self).__init__(name, doc, default=default, + super(PortOption, self).__init__(name, + doc, + default=default, default_multi=default_multi, callback=callback, callback_params=callback_params, @@ -81,30 +96,29 @@ class PortOption(Option): warnings_only=warnings_only, extra=extra) - def _validate(self, value, context=undefined, current_opt=undefined): + def _validate(self, + value, + setting_properties, + context=undefined, + current_opt=undefined): if isinstance(value, int): - if sys.version_info[0] >= 3: # pragma: no cover - value = str(value) - else: - value = unicode(value) - err = self._impl_valid_string(value) - if err: - return err + value = str(value) + self._impl_valid_string(value) if self._get_extra('_allow_range') and ":" in str(value): value = str(value).split(':') if len(value) != 2: - return ValueError(_('range must have two values only')) + raise ValueError(_('range must have two values only')) if not value[0] < value[1]: - return ValueError(_('first port in range must be' - ' smaller than the second one')) + raise ValueError(_('first port in range must be' + ' smaller than the second one')) else: value = [value] for val in value: if not self.port_re.search(val): - return ValueError() + raise ValueError() val = int(val) if not self._get_extra('_min_value') <= val <= self._get_extra('_max_value'): - return ValueError(_('must be an integer between {0} ' - 'and {1}').format(self._get_extra('_min_value'), - self._get_extra('_max_value'))) + raise ValueError(_('must be an integer between {0} ' + 'and {1}').format(self._get_extra('_min_value'), + self._get_extra('_max_value'))) diff --git a/tiramisu/option/stroption.py b/tiramisu/option/stroption.py index c4b79ee..3d7ab9b 100644 --- a/tiramisu/option/stroption.py +++ b/tiramisu/option/stroption.py @@ -30,23 +30,16 @@ class StrOption(Option): __slots__ = tuple() _display_name = _('string') - def _validate(self, value, context=undefined, current_opt=undefined): + def _validate(self, + value, + setting_properties, + context=undefined, + current_opt=undefined): if not isinstance(value, str): - return ValueError() + raise ValueError() -if sys.version_info[0] >= 3: # pragma: no cover - #UnicodeOption is same as StrOption in python 3+ - class UnicodeOption(StrOption): - __slots__ = tuple() - pass -else: - class UnicodeOption(Option): - "represents the choice of a unicode string" - __slots__ = tuple() - _empty = u'' - _display_name = _('unicode string') - - def _validate(self, value, context=undefined, current_opt=undefined): - if not isinstance(value, unicode): - return ValueError() +#UnicodeOption is same as StrOption in python 3+ +class UnicodeOption(StrOption): + __slots__ = tuple() + _display_name = _('unicode') diff --git a/tiramisu/option/symlinkoption.py b/tiramisu/option/symlinkoption.py index 2ffc222..f58e09e 100644 --- a/tiramisu/option/symlinkoption.py +++ b/tiramisu/option/symlinkoption.py @@ -38,6 +38,10 @@ class SymLinkOption(OnlyOption): _setattr(self, '_opt', opt) opt._add_dependency(self) + def __getattr__(self, + name): + return getattr(self._opt, name) + def impl_has_dependency(self, self_is_dep=True): """If self_is_dep is True, it has dependency (self._opt), so return True if self_is_dep is False, cannot has validation or callback, so return False @@ -47,37 +51,32 @@ class SymLinkOption(OnlyOption): def impl_is_symlinkoption(self): return True - def __getattr__(self, - name, - context=undefined): - return getattr(self.impl_getopt(), name) - def impl_getopt(self): return self._opt - def impl_get_information(self, - key, - default=undefined): - return self.impl_getopt().impl_get_information(key, default) + #def impl_get_information(self, + # key, + # default=undefined): + # return self._opt.impl_get_information(key, default) def impl_is_readonly(self): return True - def impl_getproperties(self): - return self.impl_getopt().impl_getproperties() + #def impl_getproperties(self): + # return self._opt.impl_getproperties() - def impl_get_callback(self): - return self.impl_getopt().impl_get_callback() + #def impl_get_callback(self): + # return self._opt.impl_get_callback() - def impl_has_callback(self): - "to know if a callback has been defined or not" - return self.impl_getopt().impl_has_callback() + #def impl_has_callback(self): + # "to know if a callback has been defined or not" + # return self._opt.impl_has_callback() - def impl_is_multi(self): - return self.impl_getopt().impl_is_multi() + #def impl_is_multi(self): + # return self._opt.impl_is_multi() - def _is_subdyn(self): - return getattr(self.impl_getopt(), '_subdyn', None) is not None + #def _is_subdyn(self): + # return getattr(self._opt, '_subdyn', None) is not None def _get_consistencies(self): return () @@ -100,15 +99,14 @@ class DynSymLinkOption(object): self._suffix = suffix def __getattr__(self, - name, - context=undefined): - return getattr(self.impl_getopt(), name) + name): + return getattr(self._opt, name) def impl_getname(self): return self._opt.impl_getname() + self._suffix def impl_get_display_name(self): - return self.impl_getopt().impl_get_display_name(dyn_name=self.impl_getname()) + return self._opt.impl_get_display_name(dyn_name=self.impl_getname()) def impl_getopt(self): return self._opt @@ -125,23 +123,20 @@ class DynSymLinkOption(object): def impl_validate(self, value, context=undefined, - validate=True, force_index=None, is_multi=None, - display_error=True, - display_warnings=True, + check_error=True, multi=None, setting_properties=undefined): - return self.impl_getopt().impl_validate(value, - context, - validate, - force_index, - current_opt=self, - is_multi=is_multi, - display_error=display_error, - display_warnings=display_warnings, - multi=multi, - setting_properties=setting_properties) + # add current_opt ! + self._opt.impl_validate(value, + context, + force_index, + current_opt=self, + is_multi=is_multi, + check_error=check_error, + multi=multi, + setting_properties=setting_properties) def impl_is_dynsymlinkoption(self): return True diff --git a/tiramisu/option/syndynoptiondescription.py b/tiramisu/option/syndynoptiondescription.py index 5298fb2..dd1b5dd 100644 --- a/tiramisu/option/syndynoptiondescription.py +++ b/tiramisu/option/syndynoptiondescription.py @@ -40,16 +40,23 @@ class SynDynOptionDescription(object): def __getattr__(self, name): return getattr(self._opt, name) + def impl_getopt(self): + return self._opt + def impl_getchild(self, name, setting_properties, subconfig): - if name.endswith(self._suffix): - oname = name[:-len(self._suffix)] - child = self._children[1][self._children[0].index(oname)] - return self._impl_get_dynchild(child, - self._suffix, - subconfig.cfgimpl_get_path()) + try: + if name.endswith(self._suffix): + oname = name[:-len(self._suffix)] + child = self._children[1][self._children[0].index(oname)] + return self._impl_get_dynchild(child, + self._suffix, + subconfig.cfgimpl_get_path()) + except ValueError: + # when oname not in self._children + pass raise AttributeError(_('unknown Option {0} ' 'in SynDynOptionDescription {1}' '').format(name, self.impl_getname())) diff --git a/tiramisu/option/urloption.py b/tiramisu/option/urloption.py index c5fb989..9745e29 100644 --- a/tiramisu/option/urloption.py +++ b/tiramisu/option/urloption.py @@ -32,13 +32,15 @@ class URLOption(DomainnameOption): path_re = re.compile(r"^[A-Za-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$") _display_name = _('URL') - def _validate(self, value, context=undefined, current_opt=undefined): - err = self._impl_valid_string(value) - if err: - return err + def _validate(self, + value, + setting_properties, + context=undefined, + current_opt=undefined): + self._impl_valid_string(value) match = self.proto_re.search(value) if not match: - return ValueError(_('must start with http:// or ' + raise ValueError(_('must start with http:// or ' 'https://')) value = value[len(match.group(0)):] # get domain/files @@ -56,18 +58,17 @@ class URLOption(DomainnameOption): else: domain, port = splitted if not 0 <= int(port) <= 65535: - return ValueError(_('port must be an between 0 and ' + raise ValueError(_('port must be an between 0 and ' '65536')) # validate domainname - err = super(URLOption, self)._validate(domain) - if err: - return err - err = super(URLOption, self)._second_level_validation(domain, False) - if err: - return err + super(URLOption, self)._validate(domain, + setting_properties, + context, + current_opt) + super(URLOption, self)._second_level_validation(domain, False) # validate file if files is not None and files != '' and not self.path_re.search(files): - return ValueError(_('must ends with a valid resource name')) + raise ValueError(_('must ends with a valid resource name')) def _second_level_validation(self, value, warnings_only): pass diff --git a/tiramisu/setting.py b/tiramisu/setting.py index 708878a..63be4cf 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -349,10 +349,10 @@ class Settings(object): opt = opt.impl_getopt() path = opt.impl_getpath(self._getcontext()) meta = self._getcontext().cfgimpl_get_meta() - if meta is None: - return self._pp_.getpermissive(path) - return meta.cfgimpl_get_settings().getpermissive(opt, - path) + if meta is not None: + return meta.cfgimpl_get_settings().getpermissive(opt, + path) + return self._pp_.getpermissive(path) def apply_requires(self, opt, @@ -589,6 +589,7 @@ class Settings(object): opt, path, setting_properties, + self_properties=undefined, index=None, force_permissive=False): """ @@ -599,10 +600,11 @@ class Settings(object): was present """ # opt properties - self_properties = self.getproperties(opt, - path, - setting_properties=setting_properties, - index=index) + if self_properties is undefined: + self_properties = self.getproperties(opt, + path, + setting_properties=setting_properties, + index=index) # calc properties properties = self_properties & setting_properties - set(['frozen']) @@ -612,7 +614,7 @@ class Settings(object): value = self._getcontext().cfgimpl_get_values().get_cached_value(opt, path, setting_properties, - validate=False, + validate=True, self_properties=self_properties, index=index) if not self.validate_mandatory(opt, @@ -663,6 +665,10 @@ class Settings(object): force_allow_empty_list=True, index=index)) + def validate_frozen(self, + setting_properties, + self_properties): + return 'everything_frozen' in setting_properties or 'frozen' in self_properties #____________________________________________________________ # read only/read write diff --git a/tiramisu/value.py b/tiramisu/value.py index aa1edd2..8ea31de 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -90,15 +90,14 @@ class Values(object): """ ntime = None # try to retrive value in cache - if 'cache' in setting_properties and self._p_.hascache(path, - index): + if setting_properties and 'cache' in setting_properties and \ + self._p_.hascache(path, + index): if 'expire' in setting_properties: ntime = int(time()) is_cached, value = self._p_.getcache(path, ntime, - None) - if index: - value = value[index] + index) if is_cached: return value @@ -120,15 +119,14 @@ class Values(object): validate, force_permissive=force_permissive) # store value in cache - #FIXME pas de cache pour les slaves !!! - if index is None and 'cache' in setting_properties and \ + if setting_properties and 'cache' in setting_properties and \ validate and force_permissive is False \ and trusted_cached_properties is True: if 'expire' in setting_properties: if ntime is None: ntime = int(time()) ntime = ntime + expires_time - self._p_.setcache(path, value, ntime, None) + self._p_.setcache(path, value, ntime, index) # and return it return value @@ -164,15 +162,13 @@ class Values(object): opt.impl_validate(value, context, force_index=index, - display_error=True, - display_warnings=False, + check_error=True, setting_properties=setting_properties) if display_warnings: opt.impl_validate(value, context, force_index=index, - display_error=False, - display_warnings=display_warnings, + check_error=False, setting_properties=setting_properties) return value @@ -411,12 +407,11 @@ class Values(object): else: tested_context = context tested_values = self - tested_values.validate_setitem(opt, - value, - path, - force_permissive, - setting_properties, - index) + tested_values.setvalue_validation(opt, + value, + path, + setting_properties, + index) self._setvalue(opt, path, @@ -425,22 +420,22 @@ class Values(object): index=index, commit=_commit) - def validate_setitem(self, - opt, - value, - path, - force_permissive, - setting_properties, - index): + def setvalue_validation(self, + opt, + value, + path, + setting_properties, + index): context = self._getcontext() settings = context.cfgimpl_get_settings() # First validate properties with this value - properties = settings.getproperties(opt, - path, - setting_properties=setting_properties, - index=index) - if 'everything_frozen' in setting_properties or 'frozen' in properties: + self_properties = settings.getproperties(opt, + path, + setting_properties=setting_properties, + index=index) + if settings.validate_frozen(setting_properties, + self_properties): datas = {'opt': opt, 'path': path, 'setting_properties': setting_properties, @@ -455,7 +450,7 @@ class Values(object): index, value, setting_properties, - properties): + self_properties): datas = {'opt': opt, 'path': path, 'setting_properties': setting_properties, @@ -469,13 +464,13 @@ class Values(object): # Value must be valid for option opt.impl_validate(value, context, - display_warnings=False, + check_error=True, force_index=index, setting_properties=setting_properties) # No error found so emit warnings opt.impl_validate(value, context, - display_error=False, + check_error=False, force_index=index, setting_properties=setting_properties) @@ -602,6 +597,7 @@ class Values(object): opt, path, owner, + setting_properties, index=None): """ sets a owner to an option @@ -621,6 +617,10 @@ class Values(object): if not self._p_.hasvalue(path): raise ConfigError(_('no value for {0} cannot change owner to {1}' '').format(path, owner)) + self.setowner_validation(opt, + path, + setting_properties, + index) self._p_.setowner(path, owner, index=index) def is_default_owner(self, @@ -663,12 +663,16 @@ class Values(object): path, setting_properties, validate=False) - #FIXME ce n'est pas deja fait dans le reset ? - #sinon c'est un validate_properties qu'il faut faire ... - #fake_value.get_cached_value(opt, - # path, - # setting_properties=setting_properties, - # force_permissive=force_permissive) + value = fake_value._getdefaultvalue(opt, + path, + None, + validate, + setting_properties) + fake_value.setvalue_validation(opt, + value, + path, + setting_properties, + None) if opt.impl_is_master_slaves('master'): opt.impl_get_master_slaves().reset(opt, self, @@ -714,11 +718,16 @@ class Values(object): index, setting_properties, validate=False) - fake_value.get_cached_value(opt, - path, - setting_properties, - index=index, - force_permissive=force_permissive) + value = fake_value._getdefaultvalue(opt, + path, + index, + validate, + setting_properties) + fake_value.setvalue_validation(opt, + value, + path, + setting_properties, + index) self._p_.resetvalue_index(path, index) def reset_master(self, @@ -746,6 +755,33 @@ class Values(object): setting_properties, force_permissive) + + def setowner_validation(self, + opt, + path, + setting_properties, + index): + + context = self._getcontext() + settings = context.cfgimpl_get_settings() + # First validate properties with this value + self_properties = settings.getproperties(opt, + path, + setting_properties=setting_properties, + index=index) + if settings.validate_frozen(setting_properties, + self_properties): + datas = {'opt': opt, + 'path': path, + 'setting_properties': setting_properties, + 'index': index, + 'debug': True} + raise PropertiesOptionError(None, + ['frozen'], + settings, + datas, + 'option') + #______________________________________________________________________ # information @@ -771,7 +807,7 @@ class Values(object): # mandatory warnings def mandatory_warnings(self, - force_permissive=True): + setting_properties): """convenience function to trace Options that are mandatory and where no value has been set @@ -779,65 +815,82 @@ class Values(object): """ context = self._getcontext() settings = context.cfgimpl_get_settings() - setting_properties = context.cfgimpl_get_settings().get_context_properties() + # copy + setting_properties = set(setting_properties) setting_properties.update(['mandatory', 'empty']) - def _is_properties_option(err, path): - #FIXME hum ... - if not isinstance(err, Exception): - pass - elif isinstance(err, PropertiesOptionError): - if err.proptype == ['mandatory']: - return path - elif isinstance(err, ConfigError): - #assume that uncalculated value is an empty value - return path - else: - raise err - - def _mandatory_warnings(description, currpath=None): - if currpath is None: - currpath = [] - for opt in description._impl_getchildren(context=context): + def _mandatory_warnings(description, currpath): + is_masterslaves = description.is_masterslaves() + lenmaster = None + for opt in description.impl_getchildren(context=context, + setting_properties=setting_properties): name = opt.impl_getname() path = '.'.join(currpath + [name]) if opt.impl_is_optiondescription(): - #FIXME ? - if not settings.validate_properties(opt, - True, - False, - path=path, - force_permissive=True, - setting_properties=setting_properties): + try: + settings.validate_properties(opt, + path, + setting_properties, + force_permissive=True) for path in _mandatory_warnings(opt, currpath + [name]): yield path - else: - if opt.impl_is_symlinkoption(): - continue + except PropertiesOptionError: + pass + elif not opt.impl_is_symlinkoption(): self_properties = settings.getproperties(opt, path, setting_properties=setting_properties) if 'mandatory' in self_properties or 'empty' in self_properties: - values = self.get_cached_value(opt, - path, - setting_properties, - trusted_cached_properties=False, - force_permissive=True, - self_properties=self_properties, - validate=True, - display_warnings=False) - if opt.impl_is_master_slaves('slave') and isinstance(values, list): - for val in values: - ret = _is_properties_option(val, path) - if ret is not None: - yield ret - break - else: - ret = _is_properties_option(values, path) - if ret is not None: - yield ret + try: + if opt.impl_is_master_slaves('slave'): + if lenmaster is None: + # master is a length (so int) if value is already calculated + # otherwise get value and calculate length + values = self.get_cached_value(optmaster, + pathmaster, + setting_properties, + self_properties=self_properties, + trusted_cached_properties=False, + force_permissive=True, + validate=True, + display_warnings=False) + + lenmaster = len(values) + if not lenmaster: + settings.validate_properties(opt, + path, + setting_properties, + self_properties=self_properties, + force_permissive=True) + else: + for index in range(lenmaster): + settings.validate_properties(opt, + path, + setting_properties, + self_properties=self_properties, + index=index, + force_permissive=True) + else: + settings.validate_properties(opt, + path, + setting_properties, + self_properties=self_properties, + force_permissive=True) + except PropertiesOptionError as err: + if err.proptype == frozenset(['mandatory']): + yield path + if is_masterslaves and lenmaster is None: + break + except ConfigError as err: + #assume that uncalculated value is an empty value + yield path + if is_masterslaves and lenmaster is None: + break + if is_masterslaves and lenmaster is None: + pathmaster = path + optmaster = opt descr = context.cfgimpl_get_description() - for path in _mandatory_warnings(descr): + for path in _mandatory_warnings(descr, []): yield path