coverages

This commit is contained in:
Emmanuel Garette 2018-09-15 22:44:49 +02:00
parent 84d1f85b90
commit 2d063f8170
16 changed files with 163 additions and 95 deletions

View File

@ -189,6 +189,44 @@ def test_choiceoption_calc_opt_multi_function():
raises(ValueError, "cfg.option('ch2').value.get()")
def test_choiceoption_calc_opt_multi_function_kwargs():
str_ = StrOption('str', '', ['val1'], multi=True)
choice = ChoiceOption('choice',
"",
default_multi='val2',
values=return_val,
values_params=Params(kwargs={'val': ParamOption(str_)}),
multi=True)
ch2 = ChoiceOption('ch2',
"",
default=['val2'],
values=return_val,
values_params=Params(kwargs={'val': ParamOption(str_)}),
multi=True)
odesc = OptionDescription('od', '', [str_, choice, ch2])
cfg = Config(odesc)
cfg.property.read_write()
owner = cfg.owner.get()
assert cfg.option('choice').owner.isdefault()
assert cfg.option('choice').value.get() == []
#
cfg.option('choice').value.set(['val1'])
assert cfg.option('choice').owner.get() == owner
#
raises(ValueError, "cfg.option('choice').value.set([undefined])")
#
cfg.option('choice').value.set(['val1'])
assert cfg.option('choice').owner.get() == owner
#
cfg.option('choice').value.reset()
assert cfg.option('choice').owner.isdefault()
#
raises(ValueError, "cfg.option('choice').value.set('no')")
assert cfg.option('choice').owner.isdefault()
#
raises(ValueError, "cfg.option('ch2').value.get()")
def test_choiceoption_calc_invalid():
str_ = StrOption('str', '', ['val1'], multi=True)
str_

View File

@ -361,6 +361,17 @@ def test_callback_value_force_permissive():
api.option('val3').value.get() is None
def test_callback_value_force_permissive_kwargs():
val1 = StrOption('val1', "", 'val', properties=('disabled',))
val2 = StrOption('val2', "", callback=return_value, callback_params=Params(value=ParamOption(val1)))
val3 = StrOption('val3', "", callback=return_value, callback_params=Params(value=ParamOption(val1, True)))
maconfig = OptionDescription('rootconfig', '', [val1, val2, val3])
api = Config(maconfig)
api.property.read_only()
raises(ConfigError, "api.option('val2').value.get()")
api.option('val3').value.get() is None
def test_callback_symlink():
val1 = StrOption('val1', "", 'val')
val2 = SymLinkOption('val2', val1)

View File

@ -5,7 +5,7 @@ do_autopath()
from py.test import raises
from tiramisu import IntOption, UnicodeOption, OptionDescription, Config
from tiramisu.error import PropertiesOptionError
from tiramisu.error import PropertiesOptionError, ConfigError
from tiramisu.api import TIRAMISU_VERSION
@ -102,12 +102,18 @@ def test_permissive_frozen():
assert frozenset(props) == frozenset(['disabled'])
if TIRAMISU_VERSION == 3:
def test_invalid_permissive():
descr = make_description()
api = Config(descr)
api.property.read_write()
raises(TypeError, "api.unrestraint.permissive.set(['frozen', 'disabled'])")
def test_invalid_permissive():
descr = make_description()
api = Config(descr)
api.property.read_write()
raises(TypeError, "api.unrestraint.permissive.set(['frozen', 'disabled'])")
def test_forbidden_permissive():
descr = make_description()
api = Config(descr)
api.property.read_write()
raises(ConfigError, "api.permissive.set(frozenset(['force_default_on_freeze']))")
def test_permissive_option():

View File

@ -323,23 +323,41 @@ def test_exportation_importation():
try:
c = Config(o, session_id='test_persistent', persistent=True)
d = Config(o, session_id='test_persistent2', persistent=True)
e = Config(o, session_id='test_persistent3', persistent=True)
except ValueError:
# storage is not persistent
pass
else:
c.owner.set('export')
assert c.option('b').value.get() is None
c.option('b').value.set(True)
assert c.option('b').value.get() is True
assert c.owner.get() == 'export'
del c
#
c = Config(o, session_id='test_persistent', persistent=True)
assert c.value.exportation() == [['b'], [None], [True], ['user']]
assert c.owner.get() == 'export'
assert c.value.exportation() == [['b'], [None], [True], ['export']]
d.value.importation(c.value.exportation())
assert c.value.exportation() == [['b'], [None], [True], ['user']]
assert d.value.exportation() == [['b'], [None], [True], ['user']]
assert c.value.exportation() == [['b'], [None], [True], ['export']]
assert c.owner.get() == 'export'
assert d.value.exportation() == [['b'], [None], [True], ['export']]
assert d.owner.get() == 'user'
del d
#
d = Config(o, session_id='test_persistent2', persistent=True)
assert d.value.exportation() == [['b'], [None], [True], ['user']]
assert d.value.exportation() == [['b'], [None], [True], ['export']]
assert d.owner.get() == 'user'
#
e.value.importation(c.value.exportation(with_default_owner=True))
assert e.value.exportation() == [['b'], [None], [True], ['export']]
assert e.owner.get() == 'export'
del e
#
e = Config(o, session_id='test_persistent3', persistent=True)
assert e.value.exportation() == [['b'], [None], [True], ['export']]
assert e.owner.get() == 'export'
#
delete_session('test_persistent')
delete_session('test_persistent2')
delete_session('test_persistent3')

View File

@ -63,6 +63,16 @@ def test_symlink_addproperties():
raises(TypeError, "api.option('c').property.reset()")
def test_symlink_getpermissive():
boolopt = BoolOption('b', '', default=True, properties=('test',))
linkopt = SymLinkOption("c", boolopt)
descr = OptionDescription('opt', '', [boolopt, linkopt])
api = Config(descr)
api.property.read_write()
api.option('b').permissive.set(frozenset(['perm']))
api.option('c').permissive.get() == frozenset(['perm'])
def test_symlink_addpermissive():
boolopt = BoolOption('b', '', default=True, properties=('test',))
linkopt = SymLinkOption("c", boolopt)

View File

@ -778,8 +778,18 @@ class TiramisuContextValue(TiramisuContext):
def importation(self, values):
"""import values"""
if None not in values[0]:
context_owner = self.config_bag.context.cfgimpl_get_values().get_context_owner()
else:
context_owner = None
self.config_bag.context.cfgimpl_get_values()._p_.importation(values)
self.config_bag.context.cfgimpl_reset_cache(None, None)
if context_owner is not None:
self.config_bag.context.cfgimpl_get_values()._p_.setvalue(None,
None,
context_owner,
None,
True)
class TiramisuContextOwner(TiramisuContext):

View File

@ -17,11 +17,13 @@ from .i18n import _
class Params:
__slots__ = ('args', 'kwargs')
def __init__(self, args=None, kwargs=None):
def __init__(self, args=None, kwargs=None, **kwgs):
if args is None:
args = tuple()
if kwargs is None:
kwargs = {}
if kwgs:
kwargs.update(kwgs)
if isinstance(args, Param):
args = (args,)
else:

View File

@ -270,7 +270,7 @@ class Base(object):
'callback')
# first part is validator
val = getattr(self, '_val_call', (None,))[0]
if callback_params == {}:
if not callback_params:
val_call = (callback,)
else:
val_call = (callback, callback_params)
@ -321,9 +321,9 @@ class Base(object):
def impl_get_callback(self):
call = getattr(self, '_val_call', (None, None))[1]
if call is None:
ret_call = (None, {})
ret_call = (None, None)
elif len(call) == 1:
ret_call = (call[0], {})
ret_call = (call[0], None)
else:
ret_call = call
return ret_call

View File

@ -58,7 +58,7 @@ class ChoiceOption(Option):
values_params = self._build_calculator_params(values,
values_params,
'values')
if values_params != {}:
if values_params:
self._choice_values_params = values_params
else:
if values_params is not None:

View File

@ -51,9 +51,6 @@ class DynSymLinkOption(object):
def impl_get_display_name(self):
return self._opt.impl_get_display_name(dyn_name=self.impl_getname())
def impl_getopt(self):
return self._opt
def impl_getsuffix(self):
return self._suffix

View File

@ -106,7 +106,7 @@ class Option(OnlyOption):
validator_params,
'validator',
add_value=True)
if validator_params == {}:
if not validator_params:
val_call = (validator,)
else:
val_call = (validator, validator_params)
@ -165,7 +165,7 @@ class Option(OnlyOption):
def _validate(self,
*args,
**kwargs):
**kwargs): # pragma: no cover
pass
def impl_is_unique(self):
@ -174,9 +174,9 @@ class Option(OnlyOption):
def impl_get_validator(self):
val = getattr(self, '_val_call', (None,))[0]
if val is None:
ret_val = (None, {})
ret_val = (None, None)
elif len(val) == 1:
ret_val = (val[0], {})
ret_val = (val[0], None)
else:
ret_val = val
return ret_val
@ -188,12 +188,8 @@ class Option(OnlyOption):
check_error=True):
"""
"""
if option_bag:
config_bag = option_bag.config_bag
force_index = option_bag.index
else:
config_bag = undefined
force_index = None
config_bag = option_bag.config_bag
force_index = option_bag.index
is_warnings_only = getattr(self, '_warnings_only', False)
if check_error and config_bag is not undefined and \
@ -364,9 +360,9 @@ class Option(OnlyOption):
for opt in other_opts:
if isinstance(opt, weakref.ReferenceType):
opt = opt()
if opt.impl_is_submulti():
if opt.impl_is_submulti(): # pragma: no cover
raise ConfigError(_('cannot add consistency with submulti option'))
if not isinstance(opt, Option):
if not isinstance(opt, Option): # pragma: no cover
raise ConfigError(_('consistency must be set with an option, not {}').format(opt))
if opt.issubdyn():
if dynod is None:
@ -585,7 +581,6 @@ class Option(OnlyOption):
for opt in opts:
if isinstance(opt, weakref.ReferenceType):
opt = opt()
is_multi = False
try:
opt_value = self._get_consistency_value(option_bag.index,
opt,
@ -612,39 +607,27 @@ class Option(OnlyOption):
raise ValueError(_('unexpected length of "{}" in constency "{}", '
'should be "{}"').format(len(opt_value),
opt.impl_get_display_name(),
length))
else:
length = len_value
is_multi = True
length)) # pragma: no cover
length = len_value
if isinstance(opt_value, list) and func in ALLOWED_CONST_LIST:
for value_ in opt_value:
if opt.impl_is_submulti():
for val in value_:
all_cons_vals.append((False, val))
all_cons_vals.append( val)
all_cons_opts.append(opt)
else:
all_cons_vals.append((False, value_))
all_cons_vals.append(value_)
all_cons_opts.append(opt)
else:
all_cons_vals.append((is_multi, opt_value))
all_cons_vals.append(opt_value)
all_cons_opts.append(opt)
if config_bag is not undefined and not 'validator' in config_bag.properties:
return
all_values = []
if length is None:
all_value = []
for is_multi, values in all_cons_vals:
all_value.append(values)
all_values = [all_value]
else:
for idx in range(length):
all_value = []
for is_multi, values in all_cons_vals:
if not is_multi:
all_value.append(values)
else:
all_value.append(values[idx])
all_values.append(all_value)
all_values = [all_cons_vals]
elif length:
all_values = zip(*all_cons_vals)
try:
for values in all_values:
getattr(self, func)(current_opt,
@ -773,16 +756,10 @@ class Option(OnlyOption):
else:
consistencies.append(cons)
def _del_consistency(self):
self._consistencies.pop(-1)
def get_consistencies(self):
return getattr(self, '_consistencies', STATIC_TUPLE)
def _has_consistencies(self, context):
if context is undefined:
return False
descr = context.cfgimpl_get_description()
if descr._cache_consistencies is None:
return False
@ -796,9 +773,7 @@ class RegexpOption(Option):
value,
*args,
**kwargs):
err = self._impl_valid_string(value)
if err:
return err
self._impl_valid_string(value)
match = self._regexp.search(value)
if not match:
raise ValueError()

View File

@ -106,7 +106,7 @@ rw_remove = set(['permissive', 'everything_frozen', 'mandatory', 'empty'])
FORBIDDEN_SET_PROPERTIES = frozenset(['force_store_value'])
FORBIDDEN_SET_PERMISSIVES = frozenset(['force_default_on_freeze'])
FORBIDDEN_SET_PERMISSIVES = frozenset(['force_default_on_freeze', 'force_default_on_freeze'])
log = getLogger('tiramisu')
@ -154,12 +154,12 @@ class OptionBag:
return self.option
elif key == 'apply_requires':
return True
raise KeyError('unknown key {} for OptionBag'.format(key))
raise KeyError('unknown key {} for OptionBag'.format(key)) # pragma: no cover
def __delattr__(self, key):
if key == 'properties':
return
raise KeyError('unknown key {} for ConfigBag'.format(key))
raise KeyError('unknown key {} for ConfigBag'.format(key)) # pragma: no cover
def copy(self):
kwargs = {}
@ -186,7 +186,7 @@ class ConfigBag:
if key == 'permissives':
self.permissives = self.context.cfgimpl_get_settings().get_context_permissives()
return self.permissives
raise KeyError('unknown key {} for ConfigBag'.format(key))
raise KeyError('unknown key {} for ConfigBag'.format(key)) # pragma: no cover
def remove_validation(self):
self.properties = frozenset(self.properties - {'validator'})
@ -201,7 +201,7 @@ class ConfigBag:
except AttributeError:
pass
return
raise KeyError('unknown key {} for ConfigBag'.format(key))
raise KeyError('unknown key {} for ConfigBag'.format(key)) # pragma: no cover
#def __setattr__(self, key, value):
# super().__setattr__(key, value)
@ -610,10 +610,7 @@ class Settings(object):
#values too because of slave values could have a PropertiesOptionError has value
context.cfgimpl_reset_cache(option_bag)
if option_bag is not None:
try:
del option_bag.properties
except AttributeError:
pass
del option_bag.properties
def set_context_permissives(self,
permissives):
@ -661,7 +658,7 @@ class Settings(object):
opt = None
else:
opt = option_bag.option
if all_properties and option_bag:
if all_properties and option_bag: # pragma: no cover
raise ValueError(_('opt and all_properties must not be set '
'together in reset'))
if opt and opt.impl_is_symlinkoption():

View File

@ -298,5 +298,6 @@ class Values(Cache):
def importation(self, export):
self._values = export
def delete_session(session_id):
raise ValueError(_('cannot delete none persistent session'))

View File

@ -67,10 +67,11 @@ global CONN
CONN = None
class Storage(object):
__slots__ = ('_conn', '_cursor', 'persistent', 'session_id', 'session_name')
__slots__ = ('_conn', '_cursor', 'persistent', 'session_id', 'session_name', 'created')
storage = 'sqlite3'
def __init__(self, session_id, persistent, test=False):
self.created = False
self.persistent = persistent
global CONN
init = False
@ -115,12 +116,13 @@ class Storage(object):
except sqlite3.IntegrityError:
raise ConflictError(_('session "{}" already used').format(session_id))
self.session_id = self._cursor.lastrowid
self.created = True
def commit(self):
self._conn.commit()
def execute(self, sql, params=None, commit=True):
#print(sql, params)
#print(sql, params, commit)
if params is None:
params = tuple()
self._cursor.execute(sql, params)
@ -136,7 +138,7 @@ class Storage(object):
def __del__(self):
self._cursor.close()
if not self.persistent:
if self.created and not self.persistent:
if delete_session is not None:
session_id = getattr(self, 'session_id', None)
delete_session(self.session_name,

View File

@ -57,7 +57,7 @@ class Values(Sqlite3DB):
"""set value for an option
a specified value must be associated to an owner
"""
if DEBUG:
if DEBUG: # pragma: no cover
print('setvalue', path, value, owner, index, commit)
path = self._sqlite_encode_path(path)
if index is not None:
@ -85,7 +85,7 @@ class Values(Sqlite3DB):
"""if opt has a value
return: boolean
"""
if DEBUG:
if DEBUG: # pragma: no cover
print('hasvalue', path, index)
path = self._sqlite_encode_path(path)
return self._sqlite_select(path, index) is not None
@ -108,7 +108,7 @@ class Values(Sqlite3DB):
commit=True):
"""remove value means delete value in storage
"""
if DEBUG:
if DEBUG: # pragma: no cover
print('resetvalue_index', path, index, commit)
path = self._sqlite_encode_path(path)
self._storage.execute("DELETE FROM value WHERE path = ? AND session_id = ? AND idx = ?",
@ -120,7 +120,7 @@ class Values(Sqlite3DB):
commit):
"""remove value means delete value in storage
"""
if DEBUG:
if DEBUG: # pragma: no cover
print('resetvalue', path, commit)
path = self._sqlite_encode_path(path)
self._storage.execute("DELETE FROM value WHERE path = ? AND session_id = ?",
@ -134,7 +134,7 @@ class Values(Sqlite3DB):
index=None):
"""change owner for an option
"""
if DEBUG:
if DEBUG: # pragma: no cover
print('setowner', path, owner, index)
path = self._sqlite_encode_path(path)
if index is None:
@ -152,7 +152,7 @@ class Values(Sqlite3DB):
"""get owner for an option
return: owner object
"""
if DEBUG:
if DEBUG: # pragma: no cover
print('getowner', path, default, index, with_value)
path = self._sqlite_encode_path(path)
request = "SELECT owner, value FROM value WHERE path = ? AND session_id = ?"
@ -188,7 +188,7 @@ class Values(Sqlite3DB):
:param key: information's key (ex: "help", "doc"
:param value: information's value (ex: "the help string")
"""
if DEBUG:
if DEBUG: # pragma: no cover
print('set_information', key, value)
path = self._sqlite_encode_path(path)
self._storage.execute("DELETE FROM information WHERE key = ? AND session_id = ? AND path = ?",
@ -202,7 +202,7 @@ class Values(Sqlite3DB):
:param key: the item string (ex: "help")
"""
if DEBUG:
if DEBUG: # pragma: no cover
print('get_information', key, default)
path = self._sqlite_encode_path(path)
value = self._storage.select("SELECT value FROM information WHERE key = ? AND "
@ -217,7 +217,7 @@ class Values(Sqlite3DB):
return self._sqlite_decode(value[0])
def del_information(self, path, key, raises):
if DEBUG:
if DEBUG: # pragma: no cover
print('del_information', key, raises)
path = self._sqlite_encode_path(path)
if raises and self._storage.select("SELECT value FROM information WHERE key = ? "
@ -232,13 +232,13 @@ class Values(Sqlite3DB):
(self._session_id,))
def exportation(self):
if DEBUG:
if DEBUG: # pragma: no cover
print('exportation')
rows = self._storage.select("SELECT path, value, owner, idx FROM value WHERE "
"session_id = ?;", (self._session_id,), only_one=False)
ret = [[], [], [], []]
for row in rows:
path = row[0]
path = self._sqlite_decode_path(row[0])
value = self._sqlite_decode(row[1])
owner = row[2]
index = row[3]
@ -262,9 +262,10 @@ class Values(Sqlite3DB):
return ret
def importation(self, export):
if DEBUG:
if DEBUG: # pragma: no cover
print('importation')
self._storage.execute("DELETE FROM value WHERE session_id = ?", (self._session_id,),
request = "DELETE FROM value WHERE session_id = ?"
self._storage.execute(request, (self._session_id,),
commit=False)
for idx, path in enumerate(export[0]):
path = self._sqlite_encode_path(path)
@ -288,7 +289,7 @@ class Values(Sqlite3DB):
def get_max_length(self,
path):
if DEBUG:
if DEBUG: # pragma: no cover
print('get_max_length', path)
val_max = self._storage.select("SELECT max(idx) FROM value WHERE path = ? AND session_id = ?",
(path, self._session_id), False)

View File

@ -31,8 +31,7 @@ class Values(object):
'__weakref__')
def __init__(self,
storage,
default_owner=owners.user):
storage):
"""
Initializes the values's dict.
@ -42,11 +41,12 @@ class Values(object):
# store the storage
self._p_ = storage
# set default owner
self._p_.setvalue(None,
None,
default_owner,
None,
True)
if self._p_.getowner(None, None) is None:
self._p_.setvalue(None,
None,
owners.user,
None,
True)
#______________________________________________________________________
# get value