Manipulate properties is now more convenient:

c.cfgimpl_get_settings().has_property('hidden') => 'hidden' in c.cfgimpl_get_settings()
c.cfgimpl_get_settings().has_property('hidden', option1) => 'frozen' in c.cfgimpl_get_settings()[opt]

c.cfgimpl_get_settings().get_properties(option1) => c.cfgimpl_get_settings()[option1]
c.cfgimpl_get_settings().get_properties(option1) => c.cfgimpl_get_settings()[option1]

c.cfgimpl_get_settings().add_property('hidden', option1) => c.cfgimpl_get_settings()[optiont1].append('hidden')
c.cfgimpl_get_settings().del_property('hidden', option1) => c.cfgimpl_get_settings()[optiont1].remove('hidden')

c.cfgimpl_get_settings().enable_property('hidden') => c.cfgimpl_get_settings().append('hidden')
c.cfgimpl_get_settings().disable_property('hidden') => c.cfgimpl_get_settings().remove('hidden')
This commit is contained in:
Emmanuel Garette 2013-04-20 17:30:05 +02:00
parent 54fe8d0f4b
commit d4ef47759e
11 changed files with 443 additions and 172 deletions

179
test/test_cache.py Normal file
View File

@ -0,0 +1,179 @@
# coding: utf-8
import autopath
from tiramisu import setting
setting.expires_time = 1
from tiramisu.option import IntOption, OptionDescription
from tiramisu.config import Config
from time import sleep
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():
od1 = make_description()
c = Config(od1)
values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings()
c.u1
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
c.u2
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
assert od1.u2 in values._cache
assert od1.u2 in settings._cache
def test_cache_reset():
od1 = make_description()
c = Config(od1)
values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings()
#when change a value
c.u1
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
c.u2 = 1
assert od1.u1 not in values._cache
assert od1.u1 not in settings._cache
#when remove a value
c.u1
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
del(c.u2)
assert od1.u1 not in values._cache
assert od1.u1 not in settings._cache
#when add/del property
c.u1
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
c.cfgimpl_get_settings()[od1.u2].append('test')
assert od1.u1 not in values._cache
assert od1.u1 not in settings._cache
c.u1
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
c.cfgimpl_get_settings()[od1.u2].remove('test')
assert od1.u1 not in values._cache
assert od1.u1 not in settings._cache
#when enable/disabled property
c.u1
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
c.cfgimpl_get_settings().append('test')
assert od1.u1 not in values._cache
assert od1.u1 not in settings._cache
c.u1
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
c.cfgimpl_get_settings().remove('test')
assert od1.u1 not in values._cache
assert od1.u1 not in settings._cache
def test_cache_reset_multi():
od1 = make_description()
c = Config(od1)
values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings()
#when change a value
c.u1
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
c.u3 = [1]
assert od1.u1 not in values._cache
assert od1.u1 not in settings._cache
#when append value
c.u1
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
c.u3.append(1)
assert od1.u1 not in values._cache
assert od1.u1 not in settings._cache
#when pop value
c.u1
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
c.u3.pop(1)
assert od1.u1 not in values._cache
assert od1.u1 not in settings._cache
#when remove a value
c.u1
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
del(c.u3)
assert od1.u1 not in values._cache
assert od1.u1 not in settings._cache
def test_reset_cache():
od1 = make_description()
c = Config(od1)
values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings()
c.u1
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
c.cfgimpl_reset_cache()
assert od1.u1 not in values._cache
assert od1.u1 not in settings._cache
c.u1
sleep(1)
c.u2
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
assert od1.u2 in values._cache
assert od1.u2 in settings._cache
c.cfgimpl_reset_cache()
assert od1.u1 not in values._cache
assert od1.u1 not in settings._cache
assert od1.u2 not in values._cache
assert od1.u2 not in settings._cache
def test_reset_cache_only_expired():
od1 = make_description()
c = Config(od1)
values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings()
c.u1
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
c.cfgimpl_reset_cache(True)
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
sleep(1)
c.u2
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
assert od1.u2 in values._cache
assert od1.u2 in settings._cache
c.cfgimpl_reset_cache(True)
assert od1.u1 not in values._cache
assert od1.u1 not in settings._cache
assert od1.u2 in values._cache
assert od1.u2 in settings._cache
def test_reset_cache_only():
od1 = make_description()
c = Config(od1)
values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings()
c.u1
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
c.cfgimpl_reset_cache(only=('values',))
assert od1.u1 not in values._cache
assert od1.u1 in settings._cache
c.u1
assert od1.u1 in values._cache
assert od1.u1 in settings._cache
c.cfgimpl_reset_cache(only=('settings',))
assert od1.u1 in values._cache
assert od1.u1 not in settings._cache

View File

@ -39,7 +39,7 @@ def test_freeze_whole_config():
conf = Config(descr) conf = Config(descr)
setting = conf.cfgimpl_get_settings() setting = conf.cfgimpl_get_settings()
setting.read_write() setting.read_write()
setting.enable_property('everything_frozen') setting.append('everything_frozen')
assert conf.gc.dummy is False assert conf.gc.dummy is False
prop = [] prop = []
try: try:
@ -47,7 +47,7 @@ def test_freeze_whole_config():
except PropertiesOptionError, err: except PropertiesOptionError, err:
prop = err.proptype prop = err.proptype
assert 'frozen' in prop assert 'frozen' in prop
setting.disable_property('everything_frozen') setting.remove('everything_frozen')
conf.gc.dummy = True conf.gc.dummy = True
assert conf.gc.dummy is True assert conf.gc.dummy is True
@ -60,7 +60,7 @@ def test_freeze_one_option():
setting.read_write() setting.read_write()
#freeze only one option #freeze only one option
dummy = conf.unwrap_from_path('gc.dummy') dummy = conf.unwrap_from_path('gc.dummy')
setting.add_property('frozen', dummy) setting[dummy].append('frozen')
assert conf.gc.dummy is False assert conf.gc.dummy is False
prop = [] prop = []
try: try:
@ -77,8 +77,8 @@ def test_frozen_value():
config = Config(descr) config = Config(descr)
setting = config.cfgimpl_get_settings() setting = config.cfgimpl_get_settings()
setting.read_write() setting.read_write()
setting.enable_property('frozen') setting.append('frozen')
setting.add_property('frozen', s) setting[s].append('frozen')
prop = [] prop = []
try: try:
config.string = "egg" config.string = "egg"
@ -93,9 +93,9 @@ def test_freeze():
conf = Config(descr) conf = Config(descr)
setting = conf.cfgimpl_get_settings() setting = conf.cfgimpl_get_settings()
setting.read_write() setting.read_write()
setting.enable_property('frozen') setting.append('frozen')
name = conf.unwrap_from_path("gc.name") name = conf.unwrap_from_path("gc.name")
setting.add_property('frozen', name) setting[name].append('frozen')
prop = [] prop = []
try: try:
conf.gc.name = 'framework' conf.gc.name = 'framework'
@ -109,9 +109,9 @@ def test_freeze_multi():
conf = Config(descr) conf = Config(descr)
setting = conf.cfgimpl_get_settings() setting = conf.cfgimpl_get_settings()
setting.read_write() setting.read_write()
setting.enable_property('frozen') setting.append('frozen')
obj = conf.unwrap_from_path('boolop') obj = conf.unwrap_from_path('boolop')
setting.add_property('frozen', obj) setting[obj].append('frozen')
prop = [] prop = []
try: try:
conf.boolop = [True] conf.boolop = [True]
@ -125,11 +125,11 @@ def test_freeze_get_multi():
conf = Config(descr) conf = Config(descr)
setting = conf.cfgimpl_get_settings() setting = conf.cfgimpl_get_settings()
setting.read_write() setting.read_write()
setting.enable_property('frozen') setting.append('frozen')
valmulti = conf.boolop valmulti = conf.boolop
valmulti.append(False) valmulti.append(False)
obj = conf.unwrap_from_path('boolop') obj = conf.unwrap_from_path('boolop')
setting.add_property('frozen', obj) setting[obj].append('frozen')
prop = [] prop = []
try: try:
valmulti.append(False) valmulti.append(False)

View File

@ -171,7 +171,7 @@ def test_mandatory_disabled():
except PropertiesOptionError, err: except PropertiesOptionError, err:
prop = err.proptype prop = err.proptype
assert prop == ['mandatory'] assert prop == ['mandatory']
setting.add_property('disabled', descr.str1) setting[descr.str1].append('disabled')
prop = [] prop = []
try: try:
config.str1 config.str1
@ -242,7 +242,7 @@ def test_mandatory_warnings_disabled():
setting.read_write() setting.read_write()
config.str config.str
assert list(mandatory_warnings(config)) == ['str', 'str1', 'unicode2', 'str3'] assert list(mandatory_warnings(config)) == ['str', 'str1', 'unicode2', 'str3']
setting.add_property('disabled', descr.str) setting[descr.str].append('disabled')
assert list(mandatory_warnings(config)) == ['str1', 'unicode2', 'str3'] assert list(mandatory_warnings(config)) == ['str1', 'unicode2', 'str3']
@ -254,6 +254,6 @@ def test_mandatory_warnings_frozen():
setting.read_write() setting.read_write()
config.str config.str
assert list(mandatory_warnings(config)) == ['str', 'str1', 'unicode2', 'str3'] assert list(mandatory_warnings(config)) == ['str', 'str1', 'unicode2', 'str3']
setting.add_property('frozen', descr.str) setting[descr.str].append('frozen')
setting.read_only() setting.read_only()
assert list(mandatory_warnings(config)) == ['str', 'str1', 'unicode2', 'str3'] assert list(mandatory_warnings(config)) == ['str', 'str1', 'unicode2', 'str3']

View File

@ -159,11 +159,11 @@ def test_hidden_if_in():
setting.read_write() setting.read_write()
intoption = cfg.unwrap_from_path('int') intoption = cfg.unwrap_from_path('int')
stroption = cfg.unwrap_from_path('str') stroption = cfg.unwrap_from_path('str')
assert not setting.has_property('hidden', stroption) assert not 'hidden' in setting[stroption]
cfg.int = 1 cfg.int = 1
raises(PropertiesOptionError, "cfg.str") raises(PropertiesOptionError, "cfg.str")
raises(PropertiesOptionError, 'cfg.str="uvw"') raises(PropertiesOptionError, 'cfg.str="uvw"')
assert setting.has_property('hidden', stroption) assert 'hidden' in setting[stroption]
def test_hidden_if_in_with_group(): def test_hidden_if_in_with_group():
gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref') gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
@ -183,7 +183,7 @@ def test_hidden_if_in_with_group():
cfg = Config(descr) cfg = Config(descr)
setting = cfg.cfgimpl_get_settings() setting = cfg.cfgimpl_get_settings()
setting.read_write() setting.read_write()
assert not setting.has_property('hidden', stroption) assert not 'hidden' in setting[stroption]
cfg.int = 1 cfg.int = 1
raises(PropertiesOptionError, "cfg.gc.name") raises(PropertiesOptionError, "cfg.gc.name")
@ -241,8 +241,8 @@ def test_has_callback():
config.bool = False config.bool = False
# because dummy has a callback # because dummy has a callback
dummy = config.unwrap_from_path('gc.dummy') dummy = config.unwrap_from_path('gc.dummy')
setting.enable_property('freeze') setting.append('freeze')
setting.add_property('frozen', dummy) setting[dummy].append('frozen')
raises(PropertiesOptionError, "config.gc.dummy = True") raises(PropertiesOptionError, "config.gc.dummy = True")
def test_freeze_and_has_callback(): def test_freeze_and_has_callback():
@ -251,8 +251,9 @@ def test_freeze_and_has_callback():
setting = config.cfgimpl_get_settings() setting = config.cfgimpl_get_settings()
setting.read_write() setting.read_write()
config.bool = False config.bool = False
config.cfgimpl_get_settings().enable_property('freeze') setting = config.cfgimpl_get_settings()
setting.append('freeze')
dummy = config.unwrap_from_path('gc.dummy') dummy = config.unwrap_from_path('gc.dummy')
config.cfgimpl_get_settings().add_property('frozen', dummy) setting[dummy].append('frozen')
raises(PropertiesOptionError, "config.gc.dummy = True") raises(PropertiesOptionError, "config.gc.dummy = True")
#____________________________________________________________ #____________________________________________________________

View File

@ -58,8 +58,9 @@ def test_force_default_on_freeze():
config = Config(group) config = Config(group)
config.dummy1 = True config.dummy1 = True
config.dummy2 = False config.dummy2 = False
config.cfgimpl_get_settings().add_property('frozen', dummy1) setting = config.cfgimpl_get_settings()
config.cfgimpl_get_settings().add_property('frozen', dummy2) setting[dummy1].append('frozen')
setting[dummy2].append('frozen')
assert config.dummy1 == False assert config.dummy1 == False
assert config.dummy2 == False assert config.dummy2 == False

View File

@ -145,10 +145,10 @@ def test_multi_with_requires():
config = Config(descr) config = Config(descr)
setting = config.cfgimpl_get_settings() setting = config.cfgimpl_get_settings()
setting.read_write() setting.read_write()
assert not config.cfgimpl_get_settings().has_property('hidden', stroption) assert not 'hidden' in setting[stroption]
config.int = 1 config.int = 1
raises(PropertiesOptionError, "config.str = ['a', 'b']") raises(PropertiesOptionError, "config.str = ['a', 'b']")
assert config.cfgimpl_get_settings().has_property('hidden', stroption) assert 'hidden' in setting[stroption]
def test__requires_with_inverted(): def test__requires_with_inverted():
@ -158,9 +158,10 @@ def test__requires_with_inverted():
requires=[('int', 1, 'hide', 'inverted')], multi=True) requires=[('int', 1, 'hide', 'inverted')], multi=True)
descr = OptionDescription("options", "", [s, intoption, stroption]) descr = OptionDescription("options", "", [s, intoption, stroption])
config = Config(descr) config = Config(descr)
assert not config.cfgimpl_get_settings().has_property('hidden', stroption) setting = config.cfgimpl_get_settings()
assert not 'hidden' in setting[stroption]
config.int = 1 config.int = 1
assert not config.cfgimpl_get_settings().has_property('hidden', stroption) assert not 'hidden' in setting[stroption]
def test_multi_with_requires_in_another_group(): def test_multi_with_requires_in_another_group():
@ -174,10 +175,10 @@ def test_multi_with_requires_in_another_group():
config = Config(descr2) config = Config(descr2)
setting = config.cfgimpl_get_settings() setting = config.cfgimpl_get_settings()
setting.read_write() setting.read_write()
assert not config.cfgimpl_get_settings().has_property('hidden', stroption) assert not 'hidden' in setting[stroption]
config.int = 1 config.int = 1
raises(PropertiesOptionError, "config.opt.str = ['a', 'b']") raises(PropertiesOptionError, "config.opt.str = ['a', 'b']")
assert config.cfgimpl_get_settings().has_property('hidden', stroption) assert 'hidden' in setting[stroption]
def test_apply_requires_from_config(): def test_apply_requires_from_config():
@ -191,10 +192,10 @@ def test_apply_requires_from_config():
config = Config(descr2) config = Config(descr2)
setting = config.cfgimpl_get_settings() setting = config.cfgimpl_get_settings()
setting.read_write() setting.read_write()
assert not config.cfgimpl_get_settings().has_property('hidden', stroption) assert not 'hidden' in setting[stroption]
config.int = 1 config.int = 1
raises(PropertiesOptionError, 'config.opt.str') raises(PropertiesOptionError, 'config.opt.str')
assert config.cfgimpl_get_settings().has_property('hidden', stroption) assert 'hidden' in setting[stroption]
def test_apply_requires_with_disabled(): def test_apply_requires_with_disabled():
@ -208,10 +209,10 @@ def test_apply_requires_with_disabled():
config = Config(descr2) config = Config(descr2)
setting = config.cfgimpl_get_settings() setting = config.cfgimpl_get_settings()
setting.read_write() setting.read_write()
assert not config.cfgimpl_get_settings().has_property('disabled', stroption) assert not 'disabled' in setting[stroption]
config.int = 1 config.int = 1
raises(PropertiesOptionError, 'config.opt.str') raises(PropertiesOptionError, 'config.opt.str')
assert config.cfgimpl_get_settings().has_property('disabled', stroption) assert 'disabled' in setting[stroption]
def test_multi_with_requires_with_disabled_in_another_group(): def test_multi_with_requires_with_disabled_in_another_group():
@ -225,10 +226,10 @@ def test_multi_with_requires_with_disabled_in_another_group():
config = Config(descr2) config = Config(descr2)
setting = config.cfgimpl_get_settings() setting = config.cfgimpl_get_settings()
setting.read_write() setting.read_write()
assert not config.cfgimpl_get_settings().has_property('disabled', stroption) assert not 'disabled' in setting[stroption]
config.int = 1 config.int = 1
raises(PropertiesOptionError, "config.opt.str = ['a', 'b']") raises(PropertiesOptionError, "config.opt.str = ['a', 'b']")
assert config.cfgimpl_get_settings().has_property('disabled', stroption) assert 'disabled' in setting[stroption]
def test_multi_with_requires_that_is_multi(): def test_multi_with_requires_that_is_multi():
@ -240,10 +241,10 @@ def test_multi_with_requires_that_is_multi():
config = Config(descr) config = Config(descr)
setting = config.cfgimpl_get_settings() setting = config.cfgimpl_get_settings()
setting.read_write() setting.read_write()
assert not config.cfgimpl_get_settings().has_property('hidden', stroption) assert not 'hidden' in setting[stroption]
config.int = [1, 1] config.int = [1, 1]
raises(PropertiesOptionError, "config.str = ['a', 'b']") raises(PropertiesOptionError, "config.str = ['a', 'b']")
assert config.cfgimpl_get_settings().has_property('hidden', stroption) assert 'hidden' in setting[stroption]
def test_multi_with_bool(): def test_multi_with_bool():

View File

@ -45,7 +45,7 @@ def test_is_hidden():
setting = config.cfgimpl_get_settings() setting = config.cfgimpl_get_settings()
setting.read_write() setting.read_write()
dummy = config.unwrap_from_path('gc.dummy') dummy = config.unwrap_from_path('gc.dummy')
assert not config.cfgimpl_get_settings().has_property('frozen', dummy) assert not 'frozen' in setting[dummy]
# setattr # setattr
raises(PropertiesOptionError, "config.gc.dummy == False") raises(PropertiesOptionError, "config.gc.dummy == False")
# getattr # getattr
@ -59,13 +59,13 @@ def test_group_is_hidden():
setting.read_write() setting.read_write()
gc = config.unwrap_from_path('gc') gc = config.unwrap_from_path('gc')
config.unwrap_from_path('gc.dummy') config.unwrap_from_path('gc.dummy')
config.cfgimpl_get_settings().add_property('hidden', gc) setting[gc].append('hidden')
raises(PropertiesOptionError, "config.gc.dummy") raises(PropertiesOptionError, "config.gc.dummy")
assert config.cfgimpl_get_settings().has_property('hidden', gc) assert 'hidden' in setting[gc]
raises(PropertiesOptionError, "config.gc.float") raises(PropertiesOptionError, "config.gc.float")
# manually set the subconfigs to "show" # manually set the subconfigs to "show"
config.cfgimpl_get_settings().del_property('hidden', gc) setting[gc].remove('hidden')
assert not config.cfgimpl_get_settings().has_property('hidden', gc) assert not 'hidden' in setting[gc]
assert config.gc.float == 2.3 assert config.gc.float == 2.3
#dummy est en hide #dummy est en hide
prop = [] prop = []
@ -83,17 +83,17 @@ def test_group_is_hidden_multi():
setting.read_write() setting.read_write()
obj = config.unwrap_from_path('objspace') obj = config.unwrap_from_path('objspace')
objspace = config.objspace objspace = config.objspace
config.cfgimpl_get_settings().add_property('hidden', obj) setting[obj].append('hidden')
raises(PropertiesOptionError, "config.objspace") raises(PropertiesOptionError, "config.objspace")
assert config.cfgimpl_get_settings().has_property('hidden', obj) assert 'hidden' in setting[obj]
prop = [] prop = []
try: try:
objspace.append('std') objspace.append('std')
except PropertiesOptionError, err: except PropertiesOptionError, err:
prop = err.proptype prop = err.proptype
assert 'hidden' in prop assert 'hidden' in prop
config.cfgimpl_get_settings().del_property('hidden', obj) setting[obj].remove('hidden')
assert not config.cfgimpl_get_settings().has_property('hidden', obj) assert not 'hidden' in setting[obj]
config.objspace.append('std') config.objspace.append('std')
@ -103,8 +103,8 @@ def test_global_show():
setting = config.cfgimpl_get_settings() setting = config.cfgimpl_get_settings()
setting.read_write() setting.read_write()
dummy = config.unwrap_from_path('gc.dummy') dummy = config.unwrap_from_path('gc.dummy')
config.cfgimpl_get_settings().add_property('hidden', dummy) setting[dummy].append('hidden')
assert config.cfgimpl_get_settings().has_property('hidden', dummy) assert 'hidden' in setting[dummy]
raises(PropertiesOptionError, "config.gc.dummy == False") raises(PropertiesOptionError, "config.gc.dummy == False")
@ -112,11 +112,12 @@ def test_with_many_subgroups():
descr = make_description() descr = make_description()
config = Config(descr) config = Config(descr)
booltwo = config.unwrap_from_path('gc.subgroup.booltwo') booltwo = config.unwrap_from_path('gc.subgroup.booltwo')
assert not config.cfgimpl_get_settings().has_property('hidden', booltwo) setting = config.cfgimpl_get_settings()
assert not 'hidden' in setting[booltwo]
assert config.gc.subgroup.booltwo is False assert config.gc.subgroup.booltwo is False
config.cfgimpl_get_settings().add_property('hidden', booltwo) setting[booltwo].append('hidden')
path = 'gc.subgroup.booltwo' path = 'gc.subgroup.booltwo'
homeconfig, name = config.cfgimpl_get_home_by_path(path) homeconfig, name = config.cfgimpl_get_home_by_path(path)
assert name == "booltwo" assert name == "booltwo"
getattr(homeconfig._cfgimpl_descr, name) getattr(homeconfig._cfgimpl_descr, name)
assert config.cfgimpl_get_settings().has_property('hidden', booltwo) assert 'hidden' in setting[booltwo]

View File

@ -2,15 +2,17 @@
import autopath import autopath
from py.test import raises from py.test import raises
from tiramisu.config import * from tiramisu.config import Config
from tiramisu.option import * from tiramisu.option import BoolOption, OptionDescription, ChoiceOption,\
IntOption, FloatOption, StrOption
def make_description(): def make_description():
gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref') gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
gcdummy = BoolOption('dummy', 'dummy', default=False) gcdummy = BoolOption('dummy', 'dummy', default=False)
gcdummy2 = BoolOption('hide', 'dummy', default=True) gcdummy2 = BoolOption('hide', 'dummy', default=True)
objspaceoption = ChoiceOption('objspace', 'Object space', objspaceoption = ChoiceOption('objspace', 'Object space',
['std', 'thunk'], 'std') ['std', 'thunk'], 'std')
booloption = BoolOption('bool', 'Test boolean option', default=True) booloption = BoolOption('bool', 'Test boolean option', default=True)
intoption = IntOption('int', 'Test int option', default=0) intoption = IntOption('int', 'Test int option', default=0)
floatoption = FloatOption('float', 'Test float option', default=2.3) floatoption = FloatOption('float', 'Test float option', default=2.3)
@ -22,16 +24,11 @@ def make_description():
gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption, gcdummy2]) gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption, gcdummy2])
descr = OptionDescription('tiram', '', [gcgroup, booloption, objspaceoption, descr = OptionDescription('tiram', '', [gcgroup, booloption, objspaceoption,
wantref_option, stroption, wantref_option, stroption,
wantframework_option, wantframework_option,
intoption, boolop]) intoption, boolop])
return descr return descr
#def test_base_config_and_groups():
# descr = make_description()
# # overrides the booloption default value
# config = Config(descr, bool=False)
# assert config.gc.hide == True
def test_root_config_answers_ok(): def test_root_config_answers_ok():
"if you hide the root config, the options in this namespace behave normally" "if you hide the root config, the options in this namespace behave normally"
@ -40,16 +37,19 @@ def test_root_config_answers_ok():
descr = OptionDescription('tiramisu', '', [gcdummy, boolop]) descr = OptionDescription('tiramisu', '', [gcdummy, boolop])
cfg = Config(descr) cfg = Config(descr)
settings = cfg.cfgimpl_get_settings() settings = cfg.cfgimpl_get_settings()
settings.enable_property('hiddend') #cfgimpl_hide() settings.append('hidden')
assert cfg.dummy == False assert cfg.dummy is False
assert cfg.boolop == True assert cfg.boolop is True
def test_optname_shall_not_start_with_numbers(): def test_optname_shall_not_start_with_numbers():
raises(ValueError, "gcdummy = BoolOption('123dummy', 'dummy', default=False)") raises(ValueError, "gcdummy = BoolOption('123dummy', 'dummy', default=False)")
raises(ValueError, "descr = OptionDescription('123tiramisu', '', [])") raises(ValueError, "descr = OptionDescription('123tiramisu', '', [])")
#def test_option_has_an_api_name():
# gcdummy = BoolOption('cfgimpl_get_settings', 'dummy', default=False) def test_option_has_an_api_name():
# boolop = BoolOption('boolop', 'Test boolean option op', default=True) print "FIXME"
# descr = OptionDescription('tiramisu', '', [gcdummy, boolop]) #gcdummy = BoolOption('cfgimpl_get_settings', 'dummy', default=False)
# raises(ValueError, "cfg = Config(descr)") #boolop = BoolOption('boolop', 'Test boolean option op', default=True)
#descr = OptionDescription('tiramisu', '', [gcdummy, boolop])
#raises(ValueError, "cfg = Config(descr)")

83
test/test_permissive.py Normal file
View File

@ -0,0 +1,83 @@
# coding: utf-8
import autopath
from tiramisu.option import IntOption, OptionDescription
from tiramisu.config import Config
from tiramisu.error import PropertiesOptionError
def make_description():
u1 = IntOption('u1', '', properties=('frozen', 'mandatory', 'disabled', ))
return OptionDescription('od1', '', [u1])
def test_permissive():
descr = make_description()
config = Config(descr)
setting = config.cfgimpl_get_settings()
setting.read_write()
props = []
try:
config.u1
except PropertiesOptionError, err:
props = err.proptype
assert props == ['disabled']
setting.set_permissive(('disabled',))
props = []
try:
config.u1
except PropertiesOptionError, err:
props = err.proptype
assert props == ['disabled']
setting.append('permissive')
config.u1
setting.remove('permissive')
props = []
try:
config.u1
except PropertiesOptionError, err:
props = err.proptype
assert props == ['disabled']
def test_permissive_mandatory():
descr = make_description()
config = Config(descr)
setting = config.cfgimpl_get_settings()
setting.read_only()
props = []
try:
config.u1
except PropertiesOptionError, err:
props = err.proptype
assert props == ['disabled', 'mandatory']
setting.set_permissive(('mandatory', 'disabled',))
setting.append('permissive')
config.u1
setting.remove('permissive')
try:
config.u1
except PropertiesOptionError, err:
props = err.proptype
assert props == ['disabled', 'mandatory']
def test_permissive_frozen():
descr = make_description()
config = Config(descr)
setting = config.cfgimpl_get_settings()
setting.read_write()
setting.set_permissive(('frozen', 'disabled',))
try:
config.u1 = 1
except PropertiesOptionError, err:
props = err.proptype
assert props == ['disabled', 'frozen']
setting.append('permissive')
config.u1 = 1
assert config.u1 == 1
setting.remove('permissive')
try:
config.u1 = 1
except PropertiesOptionError, err:
props = err.proptype
assert props == ['disabled', 'frozen']

View File

@ -139,29 +139,58 @@ def populate_multitypes():
populate_multitypes() populate_multitypes()
class Property(object):
__slots__ = ('_setting', '_properties', '_opt')
def __init__(self, setting, prop, opt=None):
self._opt = opt
self._setting = setting
self._properties = prop
def append(self, propname):
if not propname in self._properties:
self._properties.append(propname)
self._setting._set_properties(self._properties, self._opt)
self._setting.context.cfgimpl_reset_cache()
def remove(self, propname):
if propname in self._properties:
self._properties.remove(propname)
self._setting._set_properties(self._properties, self._opt)
self._setting.context.cfgimpl_reset_cache()
def __contains__(self, propname):
return propname in self._properties
#____________________________________________________________ #____________________________________________________________
class Setting(object): class Setting(object):
"``Config()``'s configuration options" "``Config()``'s configuration options"
__slots__ = ('properties', 'permissives', 'owner', 'context', '_cache') __slots__ = ('context', '_properties', '_permissives', '_owner', '_cache')
def __init__(self, context): def __init__(self, context):
# properties attribute: the name of a property enables this property # properties attribute: the name of a property enables this property
# key is None for global properties # key is None for global properties
self.properties = {None: ['expire']} self._properties = {None: ['expire']}
# permissive properties # permissive properties
self.permissives = {} self._permissives = {}
# generic owner # generic owner
self.owner = owners.user self._owner = owners.user
self.context = context self.context = context
self._cache = {} self._cache = {}
#____________________________________________________________ #____________________________________________________________
# properties methods # properties methods
def has_properties(self, opt=None): def __contains__(self, propname):
"has properties means the Config's properties attribute is not empty" return propname in self._get_properties()
return bool(len(self.get_properties(opt)))
def get_properties(self, opt=None, is_apply_req=True): def __getitem__(self, opt):
return Property(self, self._get_properties(opt), opt)
def __setitem__(self, opt, value):
raise ValueError('you must only append/remove properties')
def _get_properties(self, opt=None, is_apply_req=True):
if opt is not None and opt in self._cache: if opt is not None and opt in self._cache:
exp = time() exp = time()
props, created = self._cache[opt] props, created = self._cache[opt]
@ -173,84 +202,65 @@ class Setting(object):
if is_apply_req: if is_apply_req:
apply_requires(opt, self.context) apply_requires(opt, self.context)
default = list(opt._properties) default = list(opt._properties)
props = self.properties.get(opt, default) props = self._properties.get(opt, default)
if opt is not None: if opt is not None:
self._set_cache(opt, props) self._set_cache(opt, props)
return props return props
def has_property(self, propname, opt=None): def append(self, propname):
"""has property propname in the Config's properties attribute
:param property: string wich is the name of the property"""
return propname in self.get_properties(opt)
def enable_property(self, propname):
"puts property propname in the Config's properties attribute" "puts property propname in the Config's properties attribute"
props = self.get_properties() Property(self, self._get_properties()).append(propname)
if propname not in props:
props.append(propname)
self.set_properties(props)
self.context.cfgimpl_reset_cache()
def disable_property(self, propname): def remove(self, propname):
"deletes property propname in the Config's properties attribute" "deletes property propname in the Config's properties attribute"
props = self.get_properties() Property(self, self._get_properties()).remove(propname)
if propname in props:
props.remove(propname)
self.set_properties(props)
self.context.cfgimpl_reset_cache()
def set_properties(self, properties, opt=None): def _set_properties(self, properties, opt=None):
"""save properties for specified opt """save properties for specified opt
(never save properties if same has option properties) (never save properties if same has option properties)
""" """
if opt is None: if opt is None:
self.properties[opt] = properties self._properties[opt] = properties
else: else:
if opt._properties == properties: if opt._properties == properties:
if opt in self.properties: if opt in self._properties:
del(self.properties[opt]) del(self._properties[opt])
else: else:
self.properties[opt] = properties self._properties[opt] = properties
def add_property(self, propname, opt, is_apply_req=True): def _validate_frozen(self, opt, value, is_write):
if opt is None: if not is_write:
raise ValueError("option must not be None in add_property") return False
properties = self.get_properties(opt, is_apply_req) if 'permissive' in self and 'frozen' in self._get_permissive():
if not propname in properties: return False
properties.append(propname) if 'everything_frozen' in self or (
self.set_properties(properties, opt) 'frozen' in self and 'frozen' in self[opt]):
self.context.cfgimpl_reset_cache() return True
return False
def del_property(self, propname, opt, is_apply_req=True): def _validate_mandatory(self, opt, value, force_properties):
if opt is None: if 'permissive' in self and 'mandatory' in self._get_permissive():
raise ValueError("option must not be None in del_property") return False
properties = self.get_properties(opt, is_apply_req) check_mandatory = 'mandatory' in self
if propname in properties:
properties.remove(propname)
self.set_properties(properties, opt)
self.context.cfgimpl_reset_cache()
def _validate_mandatory(self, opt, value, force_properties=None):
set_mandatory = self.has_property('mandatory')
if force_properties is not None: if force_properties is not None:
set_mandatory = ('mandatory' in force_properties or check_mandatory = ('mandatory' in force_properties or
set_mandatory) check_mandatory)
if set_mandatory and self.has_property('mandatory', opt) and \ if check_mandatory and 'mandatory' in self[opt] and \
self.context.cfgimpl_get_values()._is_empty(opt, value): self.context.cfgimpl_get_values()._is_empty(opt, value):
return True return True
return False return False
def _calc_properties(self, opt_or_descr, force_permissive, force_properties): def _calc_properties(self, opt_or_descr, force_permissive, force_properties):
properties = set(self.get_properties(opt_or_descr)) properties = set(self._get_properties(opt_or_descr))
#remove this properties, those properties are validate in after #remove this properties, those properties are validate in after
properties = properties - set(['mandatory', 'frozen']) properties = properties - set(['mandatory', 'frozen'])
set_properties = set(self.get_properties()) set_properties = set(self._get_properties())
if force_properties is not None: if force_properties is not None:
set_properties.update(set(force_properties)) set_properties.update(set(force_properties))
properties = properties & set_properties properties = properties & set_properties
if force_permissive is True or self.has_property('permissive'): if force_permissive is True or 'permissive' in self:
properties = properties - set(self.get_permissive()) properties = properties - set(self._get_permissive())
properties = properties - set(self.get_permissive(opt_or_descr)) properties = properties - set(self._get_permissive(opt_or_descr))
return list(properties) return list(properties)
#____________________________________________________________ #____________________________________________________________
@ -263,13 +273,9 @@ class Setting(object):
" to an option named: {0} with properties" " to an option named: {0} with properties"
" {1}") " {1}")
if not is_descr: if not is_descr:
if self._validate_mandatory(opt_or_descr, value, if self._validate_mandatory(opt_or_descr, value, force_properties):
force_properties=force_properties):
properties.append('mandatory') properties.append('mandatory')
#frozen if self._validate_frozen(opt_or_descr, value, is_write):
if is_write and (self.has_property('everything_frozen') or (
self.has_property('frozen') and
self.has_property('frozen', opt_or_descr))):
properties.append('frozen') properties.append('frozen')
raise_text = _('cannot change the value to {0} for ' raise_text = _('cannot change the value to {0} for '
'option {1} this option is frozen') 'option {1} this option is frozen')
@ -278,47 +284,47 @@ class Setting(object):
str(properties)), str(properties)),
properties) properties)
def get_permissive(self, opt=None): def _get_permissive(self, opt=None):
return self.permissives.get(opt, []) return self._permissives.get(opt, [])
def set_permissive(self, permissive, opt=None): def set_permissive(self, permissive, opt=None):
if not isinstance(permissive, list): if not isinstance(permissive, tuple):
raise TypeError(_('permissive must be a list')) raise TypeError(_('permissive must be a tuple'))
self.permissives[opt] = permissive self._permissives[opt] = permissive
#____________________________________________________________ #____________________________________________________________
def setowner(self, owner): def setowner(self, owner):
":param owner: sets the default value for owner at the Config level" ":param owner: sets the default value for owner at the Config level"
if not isinstance(owner, owners.Owner): if not isinstance(owner, owners.Owner):
raise TypeError(_("invalid generic owner {0}").format(str(owner))) raise TypeError(_("invalid generic owner {0}").format(str(owner)))
self.owner = owner self._owner = owner
def getowner(self): def getowner(self):
return self.owner return self._owner
#____________________________________________________________ #____________________________________________________________
def read_only(self): def read_only(self):
"convenience method to freeze, hidde and disable" "convenience method to freeze, hidde and disable"
self.enable_property('everything_frozen') self.append('everything_frozen')
self.enable_property('frozen') # can be usefull... self.append('frozen') # can be usefull...
self.disable_property('hidden') self.remove('hidden')
self.enable_property('disabled') self.append('disabled')
self.enable_property('mandatory') self.append('mandatory')
self.enable_property('validator') self.append('validator')
self.disable_property('permissive') self.remove('permissive')
def read_write(self): def read_write(self):
"convenience method to freeze, hidde and disable" "convenience method to freeze, hidde and disable"
self.disable_property('everything_frozen') self.remove('everything_frozen')
self.enable_property('frozen') # can be usefull... self.append('frozen') # can be usefull...
self.enable_property('hidden') self.append('hidden')
self.enable_property('disabled') self.append('disabled')
self.disable_property('mandatory') self.remove('mandatory')
self.enable_property('validator') self.append('validator')
self.disable_property('permissive') self.remove('permissive')
def _set_cache(self, opt, props): def _set_cache(self, opt, props):
if self.has_property('expire'): if 'expire' in self:
self._cache[opt] = (props, time() + expires_time) self._cache[opt] = (props, time() + expires_time)
pass pass
@ -346,7 +352,8 @@ def apply_requires(opt, config):
#for symlink #for symlink
if hasattr(opt, '_requires') and opt._requires is not None: if hasattr(opt, '_requires') and opt._requires is not None:
# filters the callbacks # filters the callbacks
setting = config.cfgimpl_get_settings() settings = config.cfgimpl_get_settings()
setting = Property(settings, settings._get_properties(opt, False), opt)
trigger_actions = build_actions(opt._requires) trigger_actions = build_actions(opt._requires)
optpath = config.cfgimpl_get_context().cfgimpl_get_description().get_path_by_opt(opt) optpath = config.cfgimpl_get_context().cfgimpl_get_description().get_path_by_opt(opt)
for requires in trigger_actions.values(): for requires in trigger_actions.values():
@ -365,22 +372,20 @@ def apply_requires(opt, config):
value = config.cfgimpl_get_context()._getattr(path, force_permissive=True) value = config.cfgimpl_get_context()._getattr(path, force_permissive=True)
except PropertiesOptionError, err: except PropertiesOptionError, err:
properties = err.proptype properties = err.proptype
#FIXME: AttributeError or PropertiesOptionError ? raise PropertiesOptionError(_("option '{0}' has requirement's property error: "
raise AttributeError(_("option '{0}' has requirement's property error: " "{1} {2}").format(opt._name, path, properties))
"{1} {2}").format(opt._name, path, properties))
except AttributeError: except AttributeError:
raise AttributeError(_("required option not found: " raise AttributeError(_("required option not found: "
"{0}").format(path)) "{0}").format(path))
if value == expected: if value == expected:
if inverse: if inverse:
setting.del_property(action, opt, False) setting.remove(action)
else: else:
setting.add_property(action, opt, False) setting.append(action)
matches = True matches = True
#FIXME optimisation : fait un double break non ? voire un return
# no requirement has been triggered, then just reverse the action # no requirement has been triggered, then just reverse the action
if not matches: if not matches:
if inverse: if inverse:
setting.add_property(action, opt, False) setting.append(action)
else: else:
setting.del_property(action, opt, False) setting.remove(action)

View File

@ -96,14 +96,14 @@ class Values(object):
# options with callbacks # options with callbacks
setting = self.context.cfgimpl_get_settings() setting = self.context.cfgimpl_get_settings()
value = self._get_value(opt) value = self._get_value(opt)
is_frozen = setting.has_property('frozen', opt) is_frozen = 'frozen' in setting[opt]
if opt.has_callback(): if opt.has_callback():
#if value is set and : #if value is set and :
# - not frozen # - not frozen
# - frozen and not force_default_on_freeze # - frozen and not force_default_on_freeze
if not self.is_default_owner(opt) and ( if not self.is_default_owner(opt) and (
not is_frozen or (is_frozen and not is_frozen or (is_frozen and
not setting.has_property('force_default_on_freeze', opt))): not 'force_default_on_freeze' in setting[opt])):
pass pass
else: else:
value = self._getcallback_value(opt) value = self._getcallback_value(opt)
@ -112,15 +112,15 @@ class Values(object):
#suppress value if already set #suppress value if already set
self._reset(opt) self._reset(opt)
# frozen and force default # frozen and force default
elif is_frozen and setting.has_property('force_default_on_freeze', opt): elif is_frozen and 'force_default_on_freeze' in setting[opt]:
value = opt.getdefault() value = opt.getdefault()
if opt.is_multi(): if opt.is_multi():
value = Multi(value, self.context, opt) value = Multi(value, self.context, opt)
if validate and not opt.validate(value, self.context, setting.has_property('validator')): if validate and not opt.validate(value, self.context, 'validator' in setting):
raise ValueError(_('invalid calculated value returned' raise ValueError(_('invalid calculated value returned'
' for option {0}: {1}').format(opt._name, value)) ' for option {0}: {1}').format(opt._name, value))
if self.is_default_owner(opt) and \ if self.is_default_owner(opt) and \
setting.has_property('force_store_value', opt): 'force_store_value' in setting[opt]:
self.setitem(opt, value) self.setitem(opt, value)
setting.validate_properties(opt, False, False, value=value, setting.validate_properties(opt, False, False, value=value,
force_permissive=force_permissive, force_permissive=force_permissive,
@ -136,7 +136,7 @@ class Values(object):
def _setitem(self, opt, value, force_permissive=False, force_properties=None): def _setitem(self, opt, value, force_permissive=False, force_properties=None):
#valid opt #valid opt
if not opt.validate(value, self.context, if not opt.validate(value, self.context,
self.context.cfgimpl_get_settings().has_property('validator')): 'validator' in self.context.cfgimpl_get_settings()):
raise ValueError(_('invalid value {}' raise ValueError(_('invalid value {}'
' for option {}').format(value, opt._name)) ' for option {}').format(value, opt._name))
if opt.is_multi() and not isinstance(value, Multi): if opt.is_multi() and not isinstance(value, Multi):
@ -172,7 +172,7 @@ class Values(object):
return self.getowner(opt) == owners.default return self.getowner(opt) == owners.default
def _set_cache(self, opt, val): def _set_cache(self, opt, val):
if self.context.cfgimpl_get_settings().has_property('expire'): if 'expire' in self.context.cfgimpl_get_settings():
self._cache[opt] = (val, time() + expires_time) self._cache[opt] = (val, time() + expires_time)
def reset_cache(self, only_expired): def reset_cache(self, only_expired):