From d4459634293380a5f93f13bf3a103d033e3b9017 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Thu, 13 Jul 2017 22:04:06 +0200 Subject: [PATCH] add permissive cache --- test/test_cache.py | 131 +++++++++++++++++------- test/test_option_setting.py | 12 +++ test/test_state.py | 88 ++++++++-------- tiramisu/config.py | 38 ++++--- tiramisu/setting.py | 69 ++++++++++--- tiramisu/storage/__init__.py | 5 +- tiramisu/storage/dictionary/__init__.py | 6 +- tiramisu/storage/dictionary/setting.py | 29 ++++-- tiramisu/storage/sqlite3/__init__.py | 4 +- tiramisu/storage/sqlite3/setting.py | 58 ++++++----- tiramisu/storage/sqlite3/value.py | 17 ++- tiramisu/value.py | 4 +- 12 files changed, 307 insertions(+), 154 deletions(-) diff --git a/test/test_cache.py b/test/test_cache.py index e425832..493029d 100644 --- a/test/test_cache.py +++ b/test/test_cache.py @@ -86,7 +86,7 @@ def test_cache_reset(): assert 'u1' in values._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c) assert 'u2' not in values._p_.get_cached(c) - assert 'u2' not in settings._p_.get_cached(c) + assert 'u2' in settings._p_.get_cached(c) #when remove a value c.u1 assert 'u1' in values._p_.get_cached(c) @@ -95,7 +95,7 @@ def test_cache_reset(): assert 'u1' in values._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c) assert 'u2' not in values._p_.get_cached(c) - assert 'u2' not in settings._p_.get_cached(c) + assert 'u2' in settings._p_.get_cached(c) #when add/del property c.u1 assert 'u1' in values._p_.get_cached(c) @@ -144,7 +144,7 @@ def test_cache_reset_multi(): assert 'u1' in values._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c) assert 'u3' not in values._p_.get_cached(c) - assert 'u3' not in settings._p_.get_cached(c) + assert 'u3' in settings._p_.get_cached(c) #when append value c.u1 c.u3 @@ -156,7 +156,7 @@ def test_cache_reset_multi(): assert 'u1' in values._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c) assert 'u3' not in values._p_.get_cached(c) - assert 'u3' not in settings._p_.get_cached(c) + assert 'u3' in settings._p_.get_cached(c) #when pop value c.u1 c.u3 @@ -168,7 +168,7 @@ def test_cache_reset_multi(): assert 'u1' in values._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c) assert 'u3' not in values._p_.get_cached(c) - assert 'u3' not in settings._p_.get_cached(c) + assert 'u3' in settings._p_.get_cached(c) #when remove a value c.u1 assert 'u1' in values._p_.get_cached(c) @@ -177,7 +177,7 @@ def test_cache_reset_multi(): assert 'u1' in values._p_.get_cached(c) assert 'u1' in settings._p_.get_cached(c) assert 'u3' not in values._p_.get_cached(c) - assert 'u3' not in settings._p_.get_cached(c) + assert 'u3' in settings._p_.get_cached(c) def test_reset_cache(): @@ -313,7 +313,8 @@ def test_force_cache(): 'u2': {None: (None, None)}, 'u3': {None: ([], None)}, 'u4': {None: (None, None)}} - assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u1': {None: (set(['empty']), None)}, + assert c.cfgimpl_get_settings()._p_.get_cached(c) == {None: {None: (set(['cache', 'validator', 'warnings']), None)}, + 'u1': {None: (set(['empty']), None)}, 'u2': {None: (set([]), None)}, 'u3': {None: (set(['empty']), None)}, 'u4': {None: (set(['disabled']), None)}} @@ -323,7 +324,8 @@ def test_force_cache(): assert c.cfgimpl_get_values()._p_.get_cached(c) == {'u1': {None: ([], None)}, 'u2': {None: (None, None)}, 'u3': {None: ([], None)}} - assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u1': {None: (set(['empty']), None)}, + assert c.cfgimpl_get_settings()._p_.get_cached(c) == {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)}} @@ -354,7 +356,7 @@ def test_cache_master_slave(): 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(cfg) - assert set(cache.keys()) == set(['ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0']) + 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]) assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None, 0]) @@ -371,7 +373,7 @@ def test_cache_master_slave(): 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(cfg) - assert set(cache.keys()) == set(['ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0']) + 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]) assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None, 0, 1]) @@ -393,7 +395,8 @@ def test_cache_callback(): cfg.cfgimpl_get_settings().remove('expire') cfg.read_write() cfg.cfgimpl_get_values().force_cache() - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}, + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, 'val2': {None: (set(['mandatory']), None)}, 'val3': {None: (set([]), None)}, 'val4': {None: (set([]), None)}, @@ -404,12 +407,15 @@ def test_cache_callback(): 'val4': {None: ('val', None)}, 'val5': {None: (['yes'], None)}} cfg.val1 = 'new' - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val3': {None: (set([]), None)}, + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, + 'val3': {None: (set([]), None)}, 'val5': {None: (set(['empty']), None)}} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val3': {None: ('yes', None)}, 'val5': {None: (['yes'], None)}} cfg.cfgimpl_get_values().force_cache() - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}, + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, 'val2': {None: (set(['mandatory']), None)}, 'val3': {None: (set([]), None)}, 'val4': {None: (set([]), None)}, @@ -420,8 +426,10 @@ def test_cache_callback(): 'val4': {None: ('new', None)}, 'val5': {None: (['yes'], None)}} cfg.val3 = 'new2' - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}, + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, 'val2': {None: (set(['mandatory']), None)}, + 'val3': {None: (set([]), None)}, 'val4': {None: (set([]), None)}, 'val5': {None: (set(['empty']), None)}} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1': {None: ('new', None)}, @@ -429,7 +437,8 @@ def test_cache_callback(): 'val4': {None: ('new', None)}, 'val5': {None: (['yes'], None)}} cfg.cfgimpl_get_values().force_cache() - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}, + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, 'val2': {None: (set(['mandatory']), None)}, 'val3': {None: (set([]), None)}, 'val4': {None: (set([]), None)}, @@ -440,16 +449,19 @@ def test_cache_callback(): 'val4': {None: ('new', None)}, 'val5': {None: (['yes'], None)}} cfg.val4 = 'new3' - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}, + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, 'val2': {None: (set(['mandatory']), None)}, 'val3': {None: (set([]), None)}, + 'val4': {None: (set([]), None)}, 'val5': {None: (set(['empty']), None)}} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1': {None: ('new', None)}, 'val2': {None: ('new', None)}, 'val3': {None: ('new2', None)}, 'val5': {None: (['yes'], None)}} cfg.cfgimpl_get_values().force_cache() - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}, + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, 'val2': {None: (set(['mandatory']), None)}, 'val3': {None: (set([]), None)}, 'val4': {None: (set([]), None)}, @@ -460,16 +472,19 @@ def test_cache_callback(): 'val4': {None: ('new3', None)}, 'val5': {None: (['yes'], None)}} cfg.val5.append('new4') - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}, + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, 'val2': {None: (set(['mandatory']), None)}, 'val3': {None: (set([]), None)}, - 'val4': {None: (set([]), None)}} + 'val4': {None: (set([]), None)}, + 'val5': {None: (set(['empty']), None)}} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1': {None: ('new', None)}, 'val2': {None: ('new', None)}, 'val3': {None: ('new2', None)}, 'val4': {None: ('new3', None)}} cfg.cfgimpl_get_values().force_cache() - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}, + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, 'val2': {None: (set(['mandatory']), None)}, 'val3': {None: (set([]), None)}, 'val4': {None: (set([]), None)}, @@ -491,15 +506,19 @@ def test_cache_master_and_slaves_master(): cfg.cfgimpl_get_settings().remove('expire') cfg.read_write() cfg.cfgimpl_get_values().force_cache() - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}, + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, 'val1.val1': {None: (set(['empty']), None)}, 'val1.val2': {None: (set([]), None)}} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([], None)}, 'val1.val2': {None: ([], None)}} cfg.val1.val1.append() - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}} + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, + 'val1.val1': {None: (set(['empty']), None)}} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {} cfg.cfgimpl_get_values().force_cache() - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}, + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, 'val1.val1': {None: (set(['empty']), None)}, 'val1.val2': {None: (set([]), None), 0: (set([]), None)}} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([None], None)}, @@ -507,11 +526,14 @@ def test_cache_master_and_slaves_master(): cfg.val1.val1.append() cfg.cfgimpl_get_values().force_cache() cfg.val1.val2[1] = 'oui' - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}, - 'val1.val1': {None: (set(['empty']), None)}} + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, + 'val1.val1': {None: (set(['empty']), None)}, + 'val1.val2': {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)}} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([None, None], None)}} cfg.cfgimpl_get_values().force_cache() - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}, + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, 'val1.val1': {None: (set(['empty']), None)}, 'val1.val2': {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)}} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([None, None], None)}, @@ -528,15 +550,19 @@ def test_cache_master_callback(): cfg.cfgimpl_get_settings().remove('expire') cfg.read_write() cfg.cfgimpl_get_values().force_cache() - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}, + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, 'val1.val1': {None: (set(['empty']), None)}, 'val1.val2': {None: (set([]), None)}} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([], None)}, 'val1.val2': {None: ([], None)}} cfg.val1.val1.append() - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}} + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, + 'val1.val1': {None: (set(['empty']), None)}} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {} cfg.cfgimpl_get_values().force_cache() - assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {'val1': {None: (set([]), None)}, + assert cfg.cfgimpl_get_settings()._p_.get_cached(cfg) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'val1': {None: (set([]), None)}, 'val1.val1': {None: (set(['empty']), None)}, 'val1.val2': {None: (set([]), None), 0: (set([]), None)}} assert cfg.cfgimpl_get_values()._p_.get_cached(cfg) == {'val1.val1': {None: ([None], None)}, @@ -554,32 +580,67 @@ def test_cache_requires(): assert c.cfgimpl_get_settings()._p_.get_cached(c) == {} assert c.cfgimpl_get_values()._p_.get_cached(c) == {} assert c.ip_address_service == None - assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'activate_service': {None: (set([]), None)}, + assert c.cfgimpl_get_settings()._p_.get_cached(c) == {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(c) == {'ip_address_service': {None: (None, None)}} c.cfgimpl_get_values().force_cache() - assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'activate_service': {None: (set([]), None)}, + assert c.cfgimpl_get_settings()._p_.get_cached(c) == {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(c) == {'ip_address_service': {None: (None, None)}, 'activate_service': {None: (True, None)}} c.ip_address_service = '1.1.1.1' - assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'activate_service': {None: (set([]), None)}} + assert c.cfgimpl_get_settings()._p_.get_cached(c) == {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(c) == {'activate_service': {None: (True, None)}} c.cfgimpl_get_values().force_cache() - assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'activate_service': {None: (set([]), None)}, + assert c.cfgimpl_get_settings()._p_.get_cached(c) == {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(c) == {'ip_address_service': {None: ('1.1.1.1', None)}, 'activate_service': {None: (True, None)}} c.activate_service = False - assert c.cfgimpl_get_settings()._p_.get_cached(c) == {} + assert c.cfgimpl_get_settings()._p_.get_cached(c) == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'activate_service': {None: (set([]), None)}} assert c.cfgimpl_get_values()._p_.get_cached(c) == {} c.cfgimpl_get_values().force_cache() - assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'activate_service': {None: (set([]), None)}, + assert c.cfgimpl_get_settings()._p_.get_cached(c) == {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(c) == {'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) + c.cfgimpl_get_settings().remove('expire') + c.read_write() + assert c.cfgimpl_get_settings()._p_.get_cached(c) == {} + assert c.cfgimpl_get_values()._p_.get_cached(c) == {} + assert c.ip_address_service == None + assert c.cfgimpl_get_settings()._p_.get_cached(c) == {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(c) == {'ip_address_service': {None: (None, None)}} + c.cfgimpl_get_settings().remove('disabled') + assert c.ip_address_service == None + assert c.cfgimpl_get_settings()._p_.get_cached(c) == {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings']), None)}, + 'activate_service': {None: (set([]), None)}, + 'ip_address_service': {None: (set([]), None)}} + c.cfgimpl_get_settings().append('test') + assert c.ip_address_service == None + assert c.cfgimpl_get_settings()._p_.get_cached(c) == {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings', 'test']), None)}, + 'activate_service': {None: (set([]), None)}, + 'ip_address_service': {None: (set([]), None)}} diff --git a/test/test_option_setting.py b/test/test_option_setting.py index 4e67308..55a6dbd 100644 --- a/test/test_option_setting.py +++ b/test/test_option_setting.py @@ -536,6 +536,18 @@ def test_reset_properties_force_store_value(): raises(ValueError, 'setting.reset(all_properties=True, opt=option)') +def test_set_modified_value(): + gcdummy = BoolOption('dummy', 'dummy', default=False, properties=('force_store_value',)) + gcgroup = OptionDescription('gc', '', [gcdummy]) + descr = OptionDescription('tiramisu', '', [gcgroup]) + cfg = Config(descr) + setting = cfg.cfgimpl_get_settings() + option = cfg.cfgimpl_get_description().gc.dummy + assert setting._p_.get_modified_properties() == {} + setting._p_.set_modified_properties({None: set(('frozen', 'expire', 'cache', 'validator', 'warnings'))}) + assert setting._p_.get_modified_properties() == {None: set(('frozen', 'expire', 'cache', 'validator', 'warnings'))} + + def test_pprint(): msg_error = _("cannot access to {0} \"{1}\" because has {2} {3}") msg_is = _('the value of "{0}" is "{1}"') diff --git a/test/test_state.py b/test/test_state.py index cc22408..fbf0280 100644 --- a/test/test_state.py +++ b/test/test_state.py @@ -536,47 +536,47 @@ def test_state_groupconfig(): pass -def test_state_unkown_setting_owner(): - """load an unknow _owner, should create it""" - assert not 'supernewuser' in owners.__dict__ - val = """ccopy_reg -_reconstructor -p0 -(ctiramisu.setting -Settings -p1 -c__builtin__ -object -p2 -Ntp3 -Rp4 -(dp5 -S'_owner' -p6 -S'supernewuser' -p7 -sS'_p_' -p8 -g0 -(ctiramisu.storage.dictionary.setting -Settings -p9 -g2 -Ntp10 -Rp11 -(dp12 -S'_cache' -p13 -(dp14 -sS'_permissives' -p15 -(dp16 -sS'_properties' -p17 -(dp18 -sbsb. -.""" - if sys.version_info[0] >= 3: # pragma: optional cover - val = bytes(val, "UTF-8") - loads(val) - assert 'supernewuser' in owners.__dict__ +#def test_state_unkown_setting_owner(): +# """load an unknow _owner, should create it""" +# assert not 'supernewuser' in owners.__dict__ +# val = """ccopy_reg +#_reconstructor +#p0 +#(ctiramisu.setting +#Settings +#p1 +#c__builtin__ +#object +#p2 +#Ntp3 +#Rp4 +#(dp5 +#S'_owner' +#p6 +#S'supernewuser' +#p7 +#sS'_p_' +#p8 +#g0 +#(ctiramisu.storage.dictionary.setting +#Properties +#p9 +#g2 +#Ntp10 +#Rp11 +#(dp12 +#S'_cache' +#p13 +#(dp14 +#sS'_permissives' +#p15 +#(dp16 +#sS'_properties' +#p17 +#(dp18 +#sbsb. +#.""" +# if sys.version_info[0] >= 3: # pragma: optional cover +# val = bytes(val, "UTF-8") +# loads(val) +# assert 'supernewuser' in owners.__dict__ diff --git a/tiramisu/config.py b/tiramisu/config.py index ce96f39..46310b4 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -73,7 +73,7 @@ class SubConfig(object): def cfgimpl_reset_cache(self, only_expired=False, - only=('values', 'settings'), + only=('values', 'properties', 'permissives', 'settings'), opt=None, path=None): """reset all settings in cache @@ -84,13 +84,15 @@ class SubConfig(object): context = self._cfgimpl_get_context() if 'values' in only: values = context.cfgimpl_get_values() - if 'settings' in only: + if 'settings' in only or 'properties' in only or 'permissives' in only: settings = context.cfgimpl_get_settings() if only_expired: if 'values' in only: values._p_.reset_expired_cache(int(time())) - if 'settings' in only: + if 'settings' in only or 'properties' in only: settings._p_.reset_expired_cache(int(time())) + if 'settings' in only or 'permissives' in only: + settings._pp_.reset_expired_cache(int(time())) elif not None in (opt, path): if opt.__class__.__name__ == 'DynOptionDescription': descr = context.cfgimpl_get_description() @@ -102,8 +104,10 @@ class SubConfig(object): path = subpath + '.' + spath[-1] + suffix if 'values' in only: values._p_.delcache(path) - if 'settings' in only: + if 'settings' in only or 'properties' in only: settings._p_.delcache(path) + if 'settings' in only or 'permissives' in only: + settings._pp_.delcache(path) elif not isinstance(opt, DynSymLinkOption) and opt._is_subdyn(): descr = context.cfgimpl_get_description() spath = path.split('.') @@ -126,23 +130,33 @@ class SubConfig(object): path += '.' + spath3 + suffix if 'values' in only: values._p_.delcache(path) - if 'settings' in only: + if 'settings' in only or 'properties' in only: settings._p_.delcache(path) + if 'settings' in only or 'permissives' in only: + settings._pp_.delcache(path) else: if 'values' in only: values._p_.delcache(path) - if 'settings' in only: + if 'settings' in only or 'permissives' in only: settings._p_.delcache(path) + if 'settings' in only or 'permissives' in only: + settings._pp_.delcache(path) for option in getattr(opt, '_dependencies', []): if 'values' in only: option.reset_cache(opt, values, 'values') if 'settings' in only: option.reset_cache(opt, settings, 'settings') + else: + if 'properties' in only: + option.reset_cache(opt, settings, 'properties') + if 'permissives' in only: + option.reset_cache(opt, settings, 'permissives') else: if 'values' in only: values._p_.reset_all_cache() if 'settings' in only: settings._p_.reset_all_cache() + settings._pp_.reset_all_cache() def cfgimpl_get_home_by_path(self, path, force_permissive=False, returns_raise=False, _setting_properties=undefined): @@ -752,8 +766,8 @@ class _CommonConfig(SubConfig): session)) config.cfgimpl_get_settings()._p_.set_modified_properties(self.cfgimpl_get_settings( )._p_.get_modified_properties()) - config.cfgimpl_get_settings()._p_.set_modified_permissives(self.cfgimpl_get_settings( - )._p_.get_modified_permissives()) + config.cfgimpl_get_settings()._pp_.set_modified_permissives(self.cfgimpl_get_settings( + )._pp_.get_modified_permissives()) return config @@ -781,7 +795,7 @@ class Config(_CommonConfig): self._impl_settings = force_settings self._impl_values = Values(self, force_values) else: - settings, values = get_storages(self, session_id, persistent) + properties, permissives, values = get_storages(self, session_id, persistent) if name is undefined: name = 'config' if session_id is not None: @@ -790,7 +804,7 @@ class Config(_CommonConfig): raise ValueError(_("name is mandatory for the config").format(name)) if name is not None and not valid_name(name): # pragma: optional cover raise ValueError(_("invalid name: {0} for config").format(name)) - self._impl_settings = Settings(self, settings) + self._impl_settings = Settings(self, properties, permissives) self._impl_values = Values(self, values) super(Config, self).__init__(descr, weakref.ref(self)) self._impl_meta = None @@ -829,8 +843,8 @@ class GroupConfig(_CommonConfig): raise ConflictError(_('config name must be uniq in ' 'groupconfig for {0}').format(name)) self._impl_children = children - settings, values = get_storages(self, session_id, persistent) - self._impl_settings = Settings(self, settings) + properties, permissives, values = get_storages(self, session_id, persistent) + self._impl_settings = Settings(self, properties, permissives) self._impl_values = Values(self, values) super(GroupConfig, self).__init__(_descr, weakref.ref(self)) self._impl_meta = None diff --git a/tiramisu/setting.py b/tiramisu/setting.py index 7a1cc90..81bc02f 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -310,9 +310,9 @@ class Property(object): #____________________________________________________________ class Settings(object): "``config.Config()``'s configuration options settings" - __slots__ = ('context', '_owner', '_p_', '__weakref__') + __slots__ = ('context', '_owner', '_p_', '_pp_', '__weakref__') - def __init__(self, context, storage): + def __init__(self, context, properties, permissives): """ initializer @@ -325,7 +325,8 @@ class Settings(object): # generic owner self._owner = owners.user self.context = weakref.ref(context) - self._p_ = storage + self._p_ = properties + self._pp_ = permissives def _getcontext(self): """context could be None, we need to test it @@ -370,7 +371,7 @@ class Settings(object): if opt is not None and _path is None: _path = opt.impl_getpath(self._getcontext()) self._p_.delproperties(_path) - self._getcontext().cfgimpl_reset_cache(opt=opt, path=_path) + self._getcontext().cfgimpl_reset_cache(opt=opt, path=_path, only=('settings',)) def _getproperties(self, opt=None, path=None, setting_properties=undefined, read_write=True, @@ -378,14 +379,27 @@ class Settings(object): """ """ if opt is None: - props = self._p_.getproperties(path, default_properties) + ntime = int(time()) + if self._p_.hascache(path, index): + is_cached, props = self._p_.getcache(path, ntime, index) + else: + is_cached = False + if not is_cached or 'cache' not in props: + props = self._p_.getproperties(path, default_properties) + if 'cache' in props: + if 'expire' in props: + ntime = ntime + expires_time + else: + ntime = None + self._p_.setcache(path, props, ntime, index) else: - if setting_properties is undefined: - setting_properties = self._getproperties(read_write=False) if path is None: # pragma: optional cover raise ValueError(_('if opt is not None, path should not be' ' None in _getproperties')) + if setting_properties is undefined: + setting_properties = self._getproperties(read_write=False) is_cached = False + if apply_requires: if 'cache' in setting_properties and 'expire' in setting_properties: ntime = int(time()) @@ -440,6 +454,26 @@ class Settings(object): self._p_.setproperties(path, properties) self._getcontext().cfgimpl_reset_cache(opt=opt, path=path) + def getpermissive(self, setting_properties, path=None): + if 'cache' in setting_properties and 'expire' in setting_properties: + ntime = int(time()) + else: + ntime = None + if 'cache' in setting_properties and self._pp_.hascache(path, None): + is_cached, perm = self._pp_.getcache(path, ntime, None) + else: + is_cached = False + if not is_cached: + if path is not None: + perm = self._pp_.getpermissive(path) + else: + perm = self._pp_.getpermissive() + if 'cache' in setting_properties: + if 'expire' in setting_properties: + ntime = ntime + expires_time + self._pp_.setcache(path, perm, ntime, None) + return perm + #____________________________________________________________ def validate_properties(self, opt_or_descr, is_descr, check_frozen, path, value=None, force_permissive=False, @@ -472,10 +506,10 @@ class Settings(object): # remove opt permissive # permissive affect option's permission with or without permissive # global property - properties -= self._p_.getpermissive(path) + properties -= self.getpermissive(setting_properties, path) # remove global permissive if need if force_permissive is True or 'permissive' in setting_properties: - properties -= self._p_.getpermissive() + properties -= self.getpermissive(setting_properties) # calc properties properties &= setting_properties @@ -540,8 +574,15 @@ class Settings(object): path = opt.impl_getpath(self._getcontext()) if not isinstance(permissive, tuple): # pragma: optional cover raise TypeError(_('permissive must be a tuple')) - self._p_.setpermissive(path, permissive) - self._getcontext().cfgimpl_reset_cache(opt=opt, path=path) + self._pp_.setpermissive(path, permissive) + setting_properties = self._getproperties(read_write=False) + self._getcontext().cfgimpl_reset_cache(opt=opt, path=path, only=('values',)) + if 'cache' in setting_properties: + if 'expire' in setting_properties: + ntime = int(time()) + expires_time + else: + ntime = None + self._pp_.setcache(path, set(permissive), ntime, None) #____________________________________________________________ def setowner(self, owner): @@ -549,6 +590,7 @@ class Settings(object): if not isinstance(owner, owners.Owner): # pragma: optional cover raise TypeError(_("invalid generic owner {0}").format(str(owner))) self._owner = owner + #FIXME qu'est ce qui se passe si pas de owner ?? def getowner(self): return self._owner @@ -718,16 +760,17 @@ class Settings(object): return self._p_.get_modified_properties() def get_modified_permissives(self): - return self._p_.get_modified_permissives() + return self._pp_.get_modified_permissives() def __getstate__(self): - return {'_p_': self._p_, '_owner': str(self._owner)} + return {'_p_': self._p_, '_pp_': self._pp_, '_owner': str(self._owner)} def _impl_setstate(self, storage): self._p_._storage = storage def __setstate__(self, states): self._p_ = states['_p_'] + self._pp_ = states['_pp_'] try: self._owner = getattr(owners, states['_owner']) except AttributeError: diff --git a/tiramisu/storage/__init__.py b/tiramisu/storage/__init__.py index ff74d79..58c68ab 100644 --- a/tiramisu/storage/__init__.py +++ b/tiramisu/storage/__init__.py @@ -133,9 +133,10 @@ def get_storages(context, session_id, persistent): session_id = gen_id(context) imp = storage_type.get() storage = imp.Storage(session_id, persistent) - settings = imp.Settings(storage) + properties = imp.Properties(storage) + permissives = imp.Permissives(storage) values = imp.Values(storage) - return settings, values + return properties, permissives, values def get_storages_option(type_): diff --git a/tiramisu/storage/dictionary/__init__.py b/tiramisu/storage/dictionary/__init__.py index 9ff39ef..312f8ef 100644 --- a/tiramisu/storage/dictionary/__init__.py +++ b/tiramisu/storage/dictionary/__init__.py @@ -23,9 +23,9 @@ The advantage of this solution is that you can easily create a Config and use it. But if something goes wrong, you will lost your modifications. """ from .value import Values -from .setting import Settings +from .setting import Properties, Permissives from .storage import setting, Storage, list_sessions, delete_session from .option import StorageBase, StorageOptionDescription, StorageMasterSlaves -__all__ = (setting, Values, Settings, Storage, list_sessions, delete_session, - StorageBase, StorageOptionDescription, StorageMasterSlaves) +__all__ = ('setting', 'Values', 'Properties', 'Permissives', 'Storage', 'list_sessions', + 'delete_session', 'StorageBase', 'StorageOptionDescription', 'StorageMasterSlaves') diff --git a/tiramisu/storage/dictionary/setting.py b/tiramisu/storage/dictionary/setting.py index 9022bc1..07f6787 100644 --- a/tiramisu/storage/dictionary/setting.py +++ b/tiramisu/storage/dictionary/setting.py @@ -19,16 +19,15 @@ from copy import copy from ..util import Cache -class Settings(Cache): - __slots__ = ('_properties', '_permissives') +class Properties(Cache): + __slots__ = ('_properties',) def __init__(self, storage): # properties attribute: the name of a property enables this property # key is None for global properties self._properties = {} # permissive properties - self._permissives = {} - super(Settings, self).__init__(storage) + super(Properties, self).__init__(storage) # properties def setproperties(self, path, properties): @@ -47,12 +46,6 @@ class Settings(Cache): if path in self._properties: del(self._properties[path]) - def setpermissive(self, path, permissive): - self._permissives[path] = frozenset(permissive) - - def getpermissive(self, path=None): - return self._permissives.get(path, frozenset()) - def get_modified_properties(self): """return all modified settings in a dictionary example: {'path1': set(['prop1', 'prop2'])} @@ -62,6 +55,21 @@ class Settings(Cache): def set_modified_properties(self, properties): self._properties = properties + +class Permissives(Cache): + __slots__ = ('_permissives',) + + def __init__(self, storage): + # permissive properties + self._permissives = {} + super(Permissives, self).__init__(storage) + + def setpermissive(self, path, permissive): + self._permissives[path] = frozenset(permissive) + + def getpermissive(self, path=None): + return self._permissives.get(path, frozenset()) + def get_modified_permissives(self): """return all modified permissives in a dictionary example: {'path1': set(['perm1', 'perm2'])} @@ -70,3 +78,4 @@ class Settings(Cache): def set_modified_permissives(self, permissives): self._permissives = permissives + diff --git a/tiramisu/storage/sqlite3/__init__.py b/tiramisu/storage/sqlite3/__init__.py index 3bd8e0c..b377610 100644 --- a/tiramisu/storage/sqlite3/__init__.py +++ b/tiramisu/storage/sqlite3/__init__.py @@ -21,7 +21,7 @@ You should not configure differents Configs with same session_id. """ from .value import Values -from .setting import Settings +from .setting import Properties, Permissives from .storage import Storage, list_sessions, delete_session -__all__ = ('Values', 'Settings', 'Storage', 'list_sessions', 'delete_session') +__all__ = ('Values', 'Properties', 'Permissives', 'Storage', 'list_sessions', 'delete_session') diff --git a/tiramisu/storage/sqlite3/setting.py b/tiramisu/storage/sqlite3/setting.py index 6aab6dc..2923538 100644 --- a/tiramisu/storage/sqlite3/setting.py +++ b/tiramisu/storage/sqlite3/setting.py @@ -18,11 +18,11 @@ from .sqlite3db import Sqlite3DB -class Settings(Sqlite3DB): +class Properties(Sqlite3DB): __slots__ = tuple() def __init__(self, storage): - super(Settings, self).__init__(storage) + super(Properties, self).__init__(storage) # properties def setproperties(self, path, properties): @@ -63,6 +63,33 @@ class Settings(Sqlite3DB): self._storage.execute("DELETE FROM property WHERE path = ? AND session_id = ?", (path, self._session_id)) + def get_modified_properties(self): + """return all modified settings in a dictionary + example: {'path1': set(['prop1', 'prop2'])} + """ + ret = {} + for path, properties, _ in self._storage.select("SELECT * FROM property " + "WHERE session_id = ?", + (self._session_id,), + only_one=False): + path = self._sqlite_decode_path(path) + ret[path] = self._sqlite_decode(properties) + return ret + + def set_modified_properties(self, properties): + self._storage.execute("DELETE FROM property", commit=False) + for path, property_ in properties.items(): + self._storage.execute("INSERT INTO property(path, properties, session_id) " + "VALUES (?, ?, ?)", (path, + self._sqlite_encode(property_), + self._session_id, + ), False) + self._storage._conn.commit() + + +class Permissives(Sqlite3DB): + __slots__ = tuple() + # permissive def setpermissive(self, path, permissive): path = self._sqlite_encode_path(path) @@ -83,35 +110,12 @@ class Settings(Sqlite3DB): else: return frozenset(self._sqlite_decode(permissives[0])) - def get_modified_properties(self): - """return all modified settings in a dictionary - example: {'path1': set(['prop1', 'prop2'])} - """ - ret = {} - for path, properties, _ in self._storage.select("SELECT * FROM property " - "WHERE session_id = ?", - (self._session_id,), - only_one=False): - path = self._sqlite_decode_path(path) - ret[path] = self._sqlite_decode(properties) - return ret - - def set_modified_properties(self, properties): - self._storage.execute("DELETE FROM property", commit=False) - for path, property_ in properties.items(): - self._storage.execute("INSERT INTO property(path, property, session_id) " - "VALUES (?, ?, ?)", (path, - self._sqlite_encode(property_), - self._session_id, - ), False) - self._storage._conn.commit() - def get_modified_permissives(self): """return all modified permissives in a dictionary example: {'path1': set(['perm1', 'perm2'])} """ ret = {} - for path, permissives in self._storage.select("SELECT * FROM permissive " + for path, permissives in self._storage.select("SELECT path, permissives FROM permissive " "WHERE session_id = ?", (self._session_id,), only_one=False): @@ -122,7 +126,7 @@ class Settings(Sqlite3DB): def set_modified_permissives(self, permissives): self._storage.execute("DELETE FROM permissive", commit=False) for path, permissive in permissives.items(): - self._storage.execute("INSERT INTO permissive(path, permissive, session_id) " + self._storage.execute("INSERT INTO permissive(path, permissives, session_id) " "VALUES (?, ?, ?)", (path, self._sqlite_encode(permissive), self._session_id, diff --git a/tiramisu/storage/sqlite3/value.py b/tiramisu/storage/sqlite3/value.py index eb1b8b4..034293d 100644 --- a/tiramisu/storage/sqlite3/value.py +++ b/tiramisu/storage/sqlite3/value.py @@ -231,10 +231,19 @@ class Values(Sqlite3DB): index = export[1][idx] value = export[2][idx] owner = export[3][idx] - self._storage.execute("INSERT INTO value(path, value, owner, idx, session_id) VALUES " - "(?, ?, ?, ?, ?)", (path, self._sqlite_encode(value), - str(owner), index, - self._session_id)) + if index is None: + self._storage.execute("INSERT INTO value(path, value, owner, idx, session_id) VALUES " + "(?, ?, ?, ?, ?)", (path, self._sqlite_encode(value), + str(owner), index, + self._session_id), commit=False) + else: + for val in zip(index, value, owner): + self._storage.execute("INSERT INTO value(path, value, owner, idx, session_id)" + "VALUES (?, ?, ?, ?, ?)", (path, + self._sqlite_encode(val[1]), + str(val[2]), val[0], + self._session_id), + commit=False) self._storage._conn.commit() def get_max_length(self, path, session): diff --git a/tiramisu/value.py b/tiramisu/value.py index fa28747..fe6e267 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -199,7 +199,7 @@ class Values(object): self._setvalue(opt, path, value, force_owner=owners.forced) else: self._p_.resetvalue(path, session) - context.cfgimpl_reset_cache(opt=opt, path=path) + context.cfgimpl_reset_cache(opt=opt, path=path, only=('values', 'properties')) def _isempty(self, opt, value, force_allow_empty_list=False, index=None): "convenience method to know if an option is empty" @@ -430,7 +430,7 @@ class Values(object): def _setvalue(self, opt, path, value, force_owner=undefined, index=None): context = self._getcontext() - context.cfgimpl_reset_cache(opt=opt, path=path) + context.cfgimpl_reset_cache(opt=opt, path=path, only=('values', 'properties')) if force_owner is undefined: owner = context.cfgimpl_get_settings().getowner() else: