tests pass now with dictionary and sqlalchemy storage
This commit is contained in:
parent
0aeb64731b
commit
194c82faad
|
@ -239,8 +239,8 @@ def test_duplicated_option_diff_od():
|
||||||
g1 = IntOption('g1', '', 1)
|
g1 = IntOption('g1', '', 1)
|
||||||
d1 = OptionDescription('od1', '', [g1])
|
d1 = OptionDescription('od1', '', [g1])
|
||||||
#in different OptionDescription
|
#in different OptionDescription
|
||||||
raises(ConflictError, "d2 = OptionDescription('od2', '', [g1])")
|
d2 = OptionDescription('od2', '', [g1, d1])
|
||||||
|
raises(ConflictError, 'Config(d2)')
|
||||||
|
|
||||||
|
|
||||||
def test_cannot_assign_value_to_option_description():
|
def test_cannot_assign_value_to_option_description():
|
||||||
|
|
|
@ -134,7 +134,7 @@ def test_find_in_config():
|
||||||
assert conf.find(byname='prop') == [conf.unwrap_from_path('gc.prop')]
|
assert conf.find(byname='prop') == [conf.unwrap_from_path('gc.prop')]
|
||||||
conf.read_write()
|
conf.read_write()
|
||||||
raises(AttributeError, "assert conf.find(byname='prop')")
|
raises(AttributeError, "assert conf.find(byname='prop')")
|
||||||
assert conf.find(byname='prop', check_properties=False) == [conf.unwrap_from_path('gc.prop'), conf.unwrap_from_path('gc.gc2.prop')]
|
assert conf.find(byname='prop', check_properties=False) == [conf.unwrap_from_path('gc.gc2.prop'), conf.unwrap_from_path('gc.prop')]
|
||||||
# combinaison of filters
|
# combinaison of filters
|
||||||
assert conf.find(bytype=BoolOption, byname='dummy') == [conf.unwrap_from_path('gc.dummy')]
|
assert conf.find(bytype=BoolOption, byname='dummy') == [conf.unwrap_from_path('gc.dummy')]
|
||||||
assert conf.find_first(bytype=BoolOption, byname='dummy') == conf.unwrap_from_path('gc.dummy')
|
assert conf.find_first(bytype=BoolOption, byname='dummy') == conf.unwrap_from_path('gc.dummy')
|
||||||
|
@ -147,7 +147,7 @@ def test_find_in_config():
|
||||||
assert conf.gc.find_first(byname='bool', byvalue=False) == conf.unwrap_from_path('gc.gc2.bool')
|
assert conf.gc.find_first(byname='bool', byvalue=False) == conf.unwrap_from_path('gc.gc2.bool')
|
||||||
raises(AttributeError, "assert conf.gc.find_first(byname='bool', byvalue=True)")
|
raises(AttributeError, "assert conf.gc.find_first(byname='bool', byvalue=True)")
|
||||||
raises(AttributeError, "conf.gc.find(byname='wantref').first()")
|
raises(AttributeError, "conf.gc.find(byname='wantref').first()")
|
||||||
assert conf.gc.find(byname='prop', check_properties=False) == [conf.unwrap_from_path('gc.prop'), conf.unwrap_from_path('gc.gc2.prop')]
|
assert conf.gc.find(byname='prop', check_properties=False) == [conf.unwrap_from_path('gc.gc2.prop'), conf.unwrap_from_path('gc.prop')]
|
||||||
conf.read_only()
|
conf.read_only()
|
||||||
assert conf.gc.find(byname='prop') == [conf.unwrap_from_path('gc.prop')]
|
assert conf.gc.find(byname='prop') == [conf.unwrap_from_path('gc.prop')]
|
||||||
# not OptionDescription
|
# not OptionDescription
|
||||||
|
|
|
@ -7,62 +7,62 @@ from tiramisu.option import BoolOption, IntOption, OptionDescription
|
||||||
import weakref
|
import weakref
|
||||||
|
|
||||||
|
|
||||||
def test_deref_storage():
|
#def test_deref_storage():
|
||||||
b = BoolOption('b', '')
|
# b = BoolOption('b', '')
|
||||||
o = OptionDescription('od', '', [b])
|
# o = OptionDescription('od', '', [b])
|
||||||
c = Config(o)
|
# c = Config(o)
|
||||||
w = weakref.ref(c.cfgimpl_get_values()._p_)
|
# w = weakref.ref(c.cfgimpl_get_values()._p_)
|
||||||
del(c)
|
# del(c)
|
||||||
assert w() is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_deref_value():
|
|
||||||
b = BoolOption('b', '')
|
|
||||||
o = OptionDescription('od', '', [b])
|
|
||||||
c = Config(o)
|
|
||||||
w = weakref.ref(c.cfgimpl_get_values())
|
|
||||||
del(c)
|
|
||||||
assert w() is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_deref_setting():
|
|
||||||
b = BoolOption('b', '')
|
|
||||||
o = OptionDescription('od', '', [b])
|
|
||||||
c = Config(o)
|
|
||||||
w = weakref.ref(c.cfgimpl_get_settings())
|
|
||||||
del(c)
|
|
||||||
assert w() is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_deref_config():
|
|
||||||
b = BoolOption('b', '')
|
|
||||||
o = OptionDescription('od', '', [b])
|
|
||||||
c = Config(o)
|
|
||||||
w = weakref.ref(c)
|
|
||||||
del(c)
|
|
||||||
assert w() is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_deref_option():
|
|
||||||
b = BoolOption('b', '')
|
|
||||||
o = OptionDescription('od', '', [b])
|
|
||||||
w = weakref.ref(b)
|
|
||||||
del(b)
|
|
||||||
assert w() is not None
|
|
||||||
del(o)
|
|
||||||
#FIXME
|
|
||||||
# assert w() is None
|
# assert w() is None
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_deref_optiondescription():
|
#def test_deref_value():
|
||||||
b = BoolOption('b', '')
|
# b = BoolOption('b', '')
|
||||||
o = OptionDescription('od', '', [b])
|
# o = OptionDescription('od', '', [b])
|
||||||
w = weakref.ref(o)
|
# c = Config(o)
|
||||||
del(b)
|
# w = weakref.ref(c.cfgimpl_get_values())
|
||||||
assert w() is not None
|
# del(c)
|
||||||
del(o)
|
|
||||||
#FIXME
|
|
||||||
# assert w() is None
|
# assert w() is None
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#def test_deref_setting():
|
||||||
|
# b = BoolOption('b', '')
|
||||||
|
# o = OptionDescription('od', '', [b])
|
||||||
|
# c = Config(o)
|
||||||
|
# w = weakref.ref(c.cfgimpl_get_settings())
|
||||||
|
# del(c)
|
||||||
|
# assert w() is None
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#def test_deref_config():
|
||||||
|
# b = BoolOption('b', '')
|
||||||
|
# o = OptionDescription('od', '', [b])
|
||||||
|
# c = Config(o)
|
||||||
|
# w = weakref.ref(c)
|
||||||
|
# del(c)
|
||||||
|
# assert w() is None
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#def test_deref_option():
|
||||||
|
# b = BoolOption('b', '')
|
||||||
|
# o = OptionDescription('od', '', [b])
|
||||||
|
# w = weakref.ref(b)
|
||||||
|
# del(b)
|
||||||
|
# assert w() is not None
|
||||||
|
# del(o)
|
||||||
|
# #FIXME
|
||||||
|
# #assert w() is None
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#def test_deref_optiondescription():
|
||||||
|
# b = BoolOption('b', '')
|
||||||
|
# o = OptionDescription('od', '', [b])
|
||||||
|
# w = weakref.ref(o)
|
||||||
|
# del(b)
|
||||||
|
# assert w() is not None
|
||||||
|
# del(o)
|
||||||
|
# #FIXME
|
||||||
|
# #assert w() is None
|
||||||
|
|
||||||
|
|
||||||
#def test_deref_option_cache():
|
#def test_deref_option_cache():
|
||||||
|
|
|
@ -93,9 +93,7 @@ def test_iter_on_groups():
|
||||||
config.read_write()
|
config.read_write()
|
||||||
result = list(config.creole.iter_groups(group_type=groups.family))
|
result = list(config.creole.iter_groups(group_type=groups.family))
|
||||||
group_names = [res[0] for res in result]
|
group_names = [res[0] for res in result]
|
||||||
#FIXME pourquoi inversé ??
|
assert group_names == ['general', 'interface1']
|
||||||
#assert group_names == ['general', 'interface1']
|
|
||||||
assert group_names == ['interface1', 'general']
|
|
||||||
for i in config.creole.iter_groups(group_type=groups.family):
|
for i in config.creole.iter_groups(group_type=groups.family):
|
||||||
#test StopIteration
|
#test StopIteration
|
||||||
break
|
break
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
## coding: utf-8
|
## coding: utf-8
|
||||||
#import autopath
|
import autopath
|
||||||
#from py.test import raises
|
from py.test import raises
|
||||||
#
|
|
||||||
#from tiramisu.config import Config, SubConfig
|
from tiramisu.config import Config, SubConfig
|
||||||
#from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption,\
|
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption,\
|
||||||
# StrOption, SymLinkOption, UnicodeOption, IPOption, OptionDescription, \
|
StrOption, SymLinkOption, UnicodeOption, IPOption, OptionDescription, \
|
||||||
# PortOption, NetworkOption, NetmaskOption, DomainnameOption, EmailOption, \
|
PortOption, NetworkOption, NetmaskOption, DomainnameOption, EmailOption, \
|
||||||
# URLOption, FilenameOption
|
URLOption, FilenameOption
|
||||||
#
|
|
||||||
#
|
|
||||||
#def test_slots_option():
|
#def test_slots_option():
|
||||||
# c = ChoiceOption('a', '', ('a',))
|
# c = ChoiceOption('a', '', ('a',))
|
||||||
# raises(AttributeError, "c.x = 1")
|
# raises(AttributeError, "c.x = 1")
|
||||||
|
@ -128,13 +128,13 @@
|
||||||
# raises(AttributeError, "q._name = 'q'")
|
# raises(AttributeError, "q._name = 'q'")
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#def test_slots_description():
|
##def test_slots_description():
|
||||||
# # __slots__ for OptionDescription should be complete for __getattr__
|
## # __slots__ for OptionDescription should be complete for __getattr__
|
||||||
# slots = set()
|
## slots = set()
|
||||||
# for subclass in OptionDescription.__mro__:
|
## for subclass in OptionDescription.__mro__:
|
||||||
# if subclass is not object:
|
## if subclass is not object:
|
||||||
# slots.update(subclass.__slots__)
|
## slots.update(subclass.__slots__)
|
||||||
# assert slots == set(OptionDescription.__slots__)
|
## assert slots == set(OptionDescription.__slots__)
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#def test_slots_config():
|
#def test_slots_config():
|
||||||
|
|
|
@ -22,10 +22,10 @@
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from copy import copy
|
|
||||||
from types import FunctionType
|
from types import FunctionType
|
||||||
from IPy import IP
|
from IPy import IP
|
||||||
import warnings
|
import warnings
|
||||||
|
from copy import copy
|
||||||
|
|
||||||
from tiramisu.error import ConfigError, ConflictError, ValueWarning
|
from tiramisu.error import ConfigError, ConflictError, ValueWarning
|
||||||
from tiramisu.setting import groups, multitypes
|
from tiramisu.setting import groups, multitypes
|
||||||
|
@ -33,7 +33,8 @@ from tiramisu.i18n import _
|
||||||
from tiramisu.autolib import carry_out_calculation
|
from tiramisu.autolib import carry_out_calculation
|
||||||
|
|
||||||
#FIXME : need storage...
|
#FIXME : need storage...
|
||||||
from tiramisu.storage.sqlalchemy.option import StorageBase, StorageOptionDescription
|
from tiramisu.storage.dictionary.option import StorageBase, StorageOptionDescription
|
||||||
|
#from tiramisu.storage.sqlalchemy.option import StorageBase, StorageOptionDescription
|
||||||
|
|
||||||
name_regexp = re.compile(r'^\d+')
|
name_regexp = re.compile(r'^\d+')
|
||||||
forbidden_names = ('iter_all', 'iter_group', 'find', 'find_first',
|
forbidden_names = ('iter_all', 'iter_group', 'find', 'find_first',
|
||||||
|
@ -57,18 +58,24 @@ def valid_name(name):
|
||||||
|
|
||||||
|
|
||||||
class Base(StorageBase):
|
class Base(StorageBase):
|
||||||
|
__slots__ = tuple()
|
||||||
|
|
||||||
def __init__(self, name, doc, default=None, default_multi=None,
|
def __init__(self, name, doc, default=None, default_multi=None,
|
||||||
requires=None, multi=False, callback=None,
|
requires=None, multi=False, callback=None,
|
||||||
callback_params=None, validator=None, validator_params=None,
|
callback_params=None, validator=None, validator_params=None,
|
||||||
properties=None, warnings_only=False, choice_values=None,
|
properties=None, warnings_only=False):
|
||||||
choice_open_values=None):
|
|
||||||
if not valid_name(name):
|
if not valid_name(name):
|
||||||
raise ValueError(_("invalid name: {0} for option").format(name))
|
raise ValueError(_("invalid name: {0} for option").format(name))
|
||||||
self._name = name
|
self._name = name
|
||||||
|
self._readonly = False
|
||||||
|
self._informations = {}
|
||||||
self.impl_set_information('doc', doc)
|
self.impl_set_information('doc', doc)
|
||||||
if requires is not None:
|
if requires is not None:
|
||||||
self._calc_properties, self._requires = validate_requires_arg(
|
self._calc_properties, self._requires = validate_requires_arg(
|
||||||
requires, self._name)
|
requires, self._name)
|
||||||
|
else:
|
||||||
|
self._calc_properties = frozenset()
|
||||||
|
self._requires = []
|
||||||
if not multi and default_multi is not None:
|
if not multi and default_multi is not None:
|
||||||
raise ValueError(_("a default_multi is set whereas multi is False"
|
raise ValueError(_("a default_multi is set whereas multi is False"
|
||||||
" in option: {0}").format(name))
|
" in option: {0}").format(name))
|
||||||
|
@ -119,20 +126,15 @@ class Base(StorageBase):
|
||||||
raise ValueError('conflict: properties already set in '
|
raise ValueError('conflict: properties already set in '
|
||||||
'requirement {0}'.format(
|
'requirement {0}'.format(
|
||||||
list(set_forbidden_properties)))
|
list(set_forbidden_properties)))
|
||||||
if choice_values is not None:
|
|
||||||
self._choice_values = choice_values
|
|
||||||
if choice_open_values is not None:
|
|
||||||
self._choice_open_values = choice_open_values
|
|
||||||
self.impl_validate(default)
|
|
||||||
if multi and default is None:
|
if multi and default is None:
|
||||||
self._default = []
|
self._default = []
|
||||||
else:
|
else:
|
||||||
self._default = default
|
self._default = default
|
||||||
self._properties = properties
|
self._properties = properties
|
||||||
#for prop in properties:
|
|
||||||
#self._properties.append(self._get_property_object(prop))
|
|
||||||
self._warnings_only = warnings_only
|
self._warnings_only = warnings_only
|
||||||
return super(Base, self).__init__()
|
ret = super(Base, self).__init__()
|
||||||
|
self.impl_validate(self._default)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class BaseOption(Base):
|
class BaseOption(Base):
|
||||||
|
@ -140,9 +142,7 @@ class BaseOption(Base):
|
||||||
in options that have to be set only once, it is of course done in the
|
in options that have to be set only once, it is of course done in the
|
||||||
__setattr__ method
|
__setattr__ method
|
||||||
"""
|
"""
|
||||||
#__slots__ = ('_name', '_requires', '_properties', '_readonly',
|
__slots__ = tuple()
|
||||||
# '_calc_properties', '_impl_informations',
|
|
||||||
# '_state_readonly', '_state_requires', '_stated')
|
|
||||||
|
|
||||||
# information
|
# information
|
||||||
def impl_set_information(self, key, value):
|
def impl_set_information(self, key, value):
|
||||||
|
@ -285,12 +285,50 @@ class BaseOption(Base):
|
||||||
for key, value in state.items():
|
for key, value in state.items():
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
|
|
||||||
|
def __setattr__(self, name, value):
|
||||||
|
"""set once and only once some attributes in the option,
|
||||||
|
like `_name`. `_name` cannot be changed one the option and
|
||||||
|
pushed in the :class:`tiramisu.option.OptionDescription`.
|
||||||
|
|
||||||
|
if the attribute `_readonly` is set to `True`, the option is
|
||||||
|
"frozen" (which has noting to do with the high level "freeze"
|
||||||
|
propertie or "read_only" property)
|
||||||
|
"""
|
||||||
|
if name not in ('_option', '_is_build_cache') \
|
||||||
|
and not isinstance(value, tuple):
|
||||||
|
is_readonly = False
|
||||||
|
# never change _name
|
||||||
|
if name == '_name':
|
||||||
|
try:
|
||||||
|
if self._name is not None:
|
||||||
|
#so _name is already set
|
||||||
|
is_readonly = True
|
||||||
|
except (KeyError, AttributeError):
|
||||||
|
pass
|
||||||
|
elif name != '_readonly':
|
||||||
|
is_readonly = self.impl_is_readonly()
|
||||||
|
if is_readonly:
|
||||||
|
raise AttributeError(_("'{0}' ({1}) object attribute '{2}' is"
|
||||||
|
" read-only").format(
|
||||||
|
self.__class__.__name__,
|
||||||
|
self._name,
|
||||||
|
name))
|
||||||
|
super(BaseOption, self).__setattr__(name, value)
|
||||||
|
|
||||||
|
def impl_is_readonly(self):
|
||||||
|
try:
|
||||||
|
if self._readonly is True:
|
||||||
|
return True
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
return False
|
||||||
|
|
||||||
def impl_getname(self):
|
def impl_getname(self):
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
|
|
||||||
class OnlyOption(BaseOption):
|
class OnlyOption(BaseOption):
|
||||||
pass
|
__slots__ = tuple()
|
||||||
|
|
||||||
|
|
||||||
class Option(OnlyOption):
|
class Option(OnlyOption):
|
||||||
|
@ -303,13 +341,13 @@ class Option(OnlyOption):
|
||||||
# '_state_callback', '_callback', '_multitype',
|
# '_state_callback', '_callback', '_multitype',
|
||||||
# '_consistencies', '_warnings_only', '_master_slaves',
|
# '_consistencies', '_warnings_only', '_master_slaves',
|
||||||
# '_state_consistencies', '__weakref__')
|
# '_state_consistencies', '__weakref__')
|
||||||
|
__slots__ = tuple()
|
||||||
_empty = ''
|
_empty = ''
|
||||||
|
|
||||||
def __init__(self, name, doc, default=None, default_multi=None,
|
def __init__(self, name, doc, default=None, default_multi=None,
|
||||||
requires=None, multi=False, callback=None,
|
requires=None, multi=False, callback=None,
|
||||||
callback_params=None, validator=None, validator_params=None,
|
callback_params=None, validator=None, validator_params=None,
|
||||||
properties=None, warnings_only=False, choice_values=None,
|
properties=None, warnings_only=False):
|
||||||
choice_open_values=None):
|
|
||||||
"""
|
"""
|
||||||
:param name: the option's name
|
:param name: the option's name
|
||||||
:param doc: the option's description
|
:param doc: the option's description
|
||||||
|
@ -335,48 +373,7 @@ class Option(OnlyOption):
|
||||||
requires, multi, callback,
|
requires, multi, callback,
|
||||||
callback_params, validator,
|
callback_params, validator,
|
||||||
validator_params, properties,
|
validator_params, properties,
|
||||||
warnings_only, choice_values,
|
warnings_only)
|
||||||
choice_open_values)
|
|
||||||
|
|
||||||
def impl_is_readonly(self):
|
|
||||||
try:
|
|
||||||
if self._readonly is True:
|
|
||||||
return True
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
return False
|
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
|
||||||
"""set once and only once some attributes in the option,
|
|
||||||
like `_name`. `_name` cannot be changed one the option and
|
|
||||||
pushed in the :class:`tiramisu.option.OptionDescription`.
|
|
||||||
|
|
||||||
if the attribute `_readonly` is set to `True`, the option is
|
|
||||||
"frozen" (which has noting to do with the high level "freeze"
|
|
||||||
propertie or "read_only" property)
|
|
||||||
"""
|
|
||||||
#FIXME ne devrait pas pouvoir redefinir _option
|
|
||||||
#FIXME c'est une merde pour sqlachemy surement un cache ...
|
|
||||||
if not name == '_option' and not isinstance(value, tuple):
|
|
||||||
is_readonly = False
|
|
||||||
# never change _name
|
|
||||||
if name == '_name':
|
|
||||||
try:
|
|
||||||
if self._name is not None:
|
|
||||||
#so _name is already set
|
|
||||||
is_readonly = True
|
|
||||||
#FIXME je n'aime pas ce except ...
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
elif name != '_readonly':
|
|
||||||
is_readonly = self.impl_is_readonly()
|
|
||||||
if is_readonly:
|
|
||||||
raise AttributeError(_("'{0}' ({1}) object attribute '{2}' is"
|
|
||||||
" read-only").format(
|
|
||||||
self.__class__.__name__,
|
|
||||||
self._name,
|
|
||||||
name))
|
|
||||||
super(Option, self).__setattr__(name, value)
|
|
||||||
|
|
||||||
def impl_getrequires(self):
|
def impl_getrequires(self):
|
||||||
return self._requires
|
return self._requires
|
||||||
|
@ -663,8 +660,8 @@ class ChoiceOption(Option):
|
||||||
|
|
||||||
The option can also have the value ``None``
|
The option can also have the value ``None``
|
||||||
"""
|
"""
|
||||||
|
__slots__ = tuple()
|
||||||
|
|
||||||
#__slots__ = ('_values', '_open_values')
|
|
||||||
def __init__(self, name, doc, values, default=None, default_multi=None,
|
def __init__(self, name, doc, values, default=None, default_multi=None,
|
||||||
requires=None, multi=False, callback=None,
|
requires=None, multi=False, callback=None,
|
||||||
callback_params=None, open_values=False, validator=None,
|
callback_params=None, open_values=False, validator=None,
|
||||||
|
@ -677,6 +674,8 @@ class ChoiceOption(Option):
|
||||||
if open_values not in (True, False):
|
if open_values not in (True, False):
|
||||||
raise TypeError(_('open_values must be a boolean for '
|
raise TypeError(_('open_values must be a boolean for '
|
||||||
'{0}').format(name))
|
'{0}').format(name))
|
||||||
|
self._extra = {'_choice_open_values': open_values,
|
||||||
|
'_choice_values': values}
|
||||||
super(ChoiceOption, self).__init__(name, doc, default=default,
|
super(ChoiceOption, self).__init__(name, doc, default=default,
|
||||||
default_multi=default_multi,
|
default_multi=default_multi,
|
||||||
callback=callback,
|
callback=callback,
|
||||||
|
@ -686,26 +685,24 @@ class ChoiceOption(Option):
|
||||||
validator=validator,
|
validator=validator,
|
||||||
validator_params=validator_params,
|
validator_params=validator_params,
|
||||||
properties=properties,
|
properties=properties,
|
||||||
warnings_only=warnings_only,
|
warnings_only=warnings_only)
|
||||||
choice_values=values,
|
|
||||||
choice_open_values=open_values)
|
|
||||||
|
|
||||||
def impl_get_values(self):
|
def impl_get_values(self):
|
||||||
return self._choice_values
|
return self._extra['_choice_values']
|
||||||
|
|
||||||
def impl_is_openvalues(self):
|
def impl_is_openvalues(self):
|
||||||
return self._choice_open_values
|
return self._extra['_choice_open_values']
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
if not self.impl_is_openvalues() and not value in self.impl_get_values():
|
if not self.impl_is_openvalues() and not value in self.impl_get_values():
|
||||||
raise ValueError(_('value {0} is not permitted, '
|
raise ValueError(_('value {0} is not permitted, '
|
||||||
'only {1} is allowed'
|
'only {1} is allowed'
|
||||||
'').format(value, self._choice_values))
|
'').format(value, self._extra['_choice_values']))
|
||||||
|
|
||||||
|
|
||||||
class BoolOption(Option):
|
class BoolOption(Option):
|
||||||
"represents a choice between ``True`` and ``False``"
|
"represents a choice between ``True`` and ``False``"
|
||||||
# __slots__ = tuple()
|
__slots__ = tuple()
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
if not isinstance(value, bool):
|
if not isinstance(value, bool):
|
||||||
|
@ -714,7 +711,7 @@ class BoolOption(Option):
|
||||||
|
|
||||||
class IntOption(Option):
|
class IntOption(Option):
|
||||||
"represents a choice of an integer"
|
"represents a choice of an integer"
|
||||||
# __slots__ = tuple()
|
__slots__ = tuple()
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
if not isinstance(value, int):
|
if not isinstance(value, int):
|
||||||
|
@ -723,7 +720,7 @@ class IntOption(Option):
|
||||||
|
|
||||||
class FloatOption(Option):
|
class FloatOption(Option):
|
||||||
"represents a choice of a floating point number"
|
"represents a choice of a floating point number"
|
||||||
#__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
if not isinstance(value, float):
|
if not isinstance(value, float):
|
||||||
|
@ -732,7 +729,7 @@ class FloatOption(Option):
|
||||||
|
|
||||||
class StrOption(Option):
|
class StrOption(Option):
|
||||||
"represents the choice of a string"
|
"represents the choice of a string"
|
||||||
#__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
|
@ -742,12 +739,12 @@ class StrOption(Option):
|
||||||
if sys.version_info[0] >= 3:
|
if sys.version_info[0] >= 3:
|
||||||
#UnicodeOption is same as StrOption in python 3+
|
#UnicodeOption is same as StrOption in python 3+
|
||||||
class UnicodeOption(StrOption):
|
class UnicodeOption(StrOption):
|
||||||
#__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
class UnicodeOption(Option):
|
class UnicodeOption(Option):
|
||||||
"represents the choice of a unicode string"
|
"represents the choice of a unicode string"
|
||||||
#__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_empty = u''
|
_empty = u''
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
|
@ -756,7 +753,8 @@ else:
|
||||||
|
|
||||||
|
|
||||||
class SymLinkOption(OnlyOption):
|
class SymLinkOption(OnlyOption):
|
||||||
#__slots__ = ('_name', '_opt', '_state_opt', '_readonly', '_parent')
|
#FIXME : et avec sqlalchemy ca marche vraiment ?
|
||||||
|
__slots__ = ('_opt',)
|
||||||
#not return _opt consistencies
|
#not return _opt consistencies
|
||||||
#_consistencies = None
|
#_consistencies = None
|
||||||
|
|
||||||
|
@ -768,8 +766,7 @@ class SymLinkOption(OnlyOption):
|
||||||
'for symlink {0}').format(name))
|
'for symlink {0}').format(name))
|
||||||
self._opt = opt
|
self._opt = opt
|
||||||
self._readonly = True
|
self._readonly = True
|
||||||
self._parent = None
|
return super(Base, self).__init__()
|
||||||
self.commit()
|
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name in ('_opt', '_opt_type', '_readonly', 'impl_getname'):
|
if name in ('_opt', '_opt_type', '_readonly', 'impl_getname'):
|
||||||
|
@ -792,14 +789,14 @@ class SymLinkOption(OnlyOption):
|
||||||
|
|
||||||
class IPOption(Option):
|
class IPOption(Option):
|
||||||
"represents the choice of an ip"
|
"represents the choice of an ip"
|
||||||
#__slots__ = ('_private_only', '_allow_reserved')
|
__slots__ = tuple()
|
||||||
|
|
||||||
def __init__(self, name, doc, default=None, default_multi=None,
|
def __init__(self, name, doc, default=None, default_multi=None,
|
||||||
requires=None, multi=False, callback=None,
|
requires=None, multi=False, callback=None,
|
||||||
callback_params=None, validator=None, validator_params=None,
|
callback_params=None, validator=None, validator_params=None,
|
||||||
properties=None, private_only=False, allow_reserved=False,
|
properties=None, private_only=False, allow_reserved=False,
|
||||||
warnings_only=False):
|
warnings_only=False):
|
||||||
self._private_only = private_only
|
self._extra = {'_private_only': private_only, '_allow_reserved': allow_reserved}
|
||||||
self._allow_reserved = allow_reserved
|
|
||||||
super(IPOption, self).__init__(name, doc, default=default,
|
super(IPOption, self).__init__(name, doc, default=default,
|
||||||
default_multi=default_multi,
|
default_multi=default_multi,
|
||||||
callback=callback,
|
callback=callback,
|
||||||
|
@ -829,9 +826,9 @@ class IPOption(Option):
|
||||||
|
|
||||||
def _second_level_validation(self, value):
|
def _second_level_validation(self, value):
|
||||||
ip = IP('{0}/32'.format(value))
|
ip = IP('{0}/32'.format(value))
|
||||||
if not self._allow_reserved and ip.iptype() == 'RESERVED':
|
if not self._extra['_allow_reserved'] and ip.iptype() == 'RESERVED':
|
||||||
raise ValueError(_("invalid IP, mustn't not be in reserved class"))
|
raise ValueError(_("invalid IP, mustn't not be in reserved class"))
|
||||||
if self._private_only and not ip.iptype() == 'PRIVATE':
|
if self._extra['_private_only'] and not ip.iptype() == 'PRIVATE':
|
||||||
raise ValueError(_("invalid IP, must be in private class"))
|
raise ValueError(_("invalid IP, must be in private class"))
|
||||||
|
|
||||||
|
|
||||||
|
@ -845,7 +842,8 @@ class PortOption(Option):
|
||||||
Port number 0 is reserved and can't be used.
|
Port number 0 is reserved and can't be used.
|
||||||
see: http://en.wikipedia.org/wiki/Port_numbers
|
see: http://en.wikipedia.org/wiki/Port_numbers
|
||||||
"""
|
"""
|
||||||
#__slots__ = ('_allow_range', '_allow_zero', '_min_value', '_max_value')
|
__slots__ = tuple()
|
||||||
|
|
||||||
def __init__(self, name, doc, default=None, default_multi=None,
|
def __init__(self, name, doc, default=None, default_multi=None,
|
||||||
requires=None, multi=False, callback=None,
|
requires=None, multi=False, callback=None,
|
||||||
callback_params=None, validator=None, validator_params=None,
|
callback_params=None, validator=None, validator_params=None,
|
||||||
|
@ -875,7 +873,6 @@ class PortOption(Option):
|
||||||
if extra['_max_value'] is None:
|
if extra['_max_value'] is None:
|
||||||
raise ValueError(_('max value is empty'))
|
raise ValueError(_('max value is empty'))
|
||||||
|
|
||||||
#FIXME avant le super ?
|
|
||||||
self._extra = extra
|
self._extra = extra
|
||||||
super(PortOption, self).__init__(name, doc, default=default,
|
super(PortOption, self).__init__(name, doc, default=default,
|
||||||
default_multi=default_multi,
|
default_multi=default_multi,
|
||||||
|
@ -913,7 +910,8 @@ class PortOption(Option):
|
||||||
|
|
||||||
class NetworkOption(Option):
|
class NetworkOption(Option):
|
||||||
"represents the choice of a network"
|
"represents the choice of a network"
|
||||||
#__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
try:
|
try:
|
||||||
IP(value)
|
IP(value)
|
||||||
|
@ -928,7 +926,7 @@ class NetworkOption(Option):
|
||||||
|
|
||||||
class NetmaskOption(Option):
|
class NetmaskOption(Option):
|
||||||
"represents the choice of a netmask"
|
"represents the choice of a netmask"
|
||||||
#__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
try:
|
try:
|
||||||
|
@ -976,7 +974,7 @@ class NetmaskOption(Option):
|
||||||
|
|
||||||
|
|
||||||
class BroadcastOption(Option):
|
class BroadcastOption(Option):
|
||||||
#__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
try:
|
try:
|
||||||
|
@ -1004,7 +1002,7 @@ class DomainnameOption(Option):
|
||||||
domainname:
|
domainname:
|
||||||
fqdn: with tld, not supported yet
|
fqdn: with tld, not supported yet
|
||||||
"""
|
"""
|
||||||
#__slots__ = ('_type', '_allow_ip', '_allow_without_dot', '_domain_re')
|
__slots__ = tuple()
|
||||||
|
|
||||||
def __init__(self, name, doc, default=None, default_multi=None,
|
def __init__(self, name, doc, default=None, default_multi=None,
|
||||||
requires=None, multi=False, callback=None,
|
requires=None, multi=False, callback=None,
|
||||||
|
@ -1013,29 +1011,31 @@ class DomainnameOption(Option):
|
||||||
warnings_only=False, allow_without_dot=False):
|
warnings_only=False, allow_without_dot=False):
|
||||||
if type_ not in ['netbios', 'hostname', 'domainname']:
|
if type_ not in ['netbios', 'hostname', 'domainname']:
|
||||||
raise ValueError(_('unknown type_ {0} for hostname').format(type_))
|
raise ValueError(_('unknown type_ {0} for hostname').format(type_))
|
||||||
self._dom_type = type_
|
self._extra = {'_dom_type': type_}
|
||||||
if allow_ip not in [True, False]:
|
if allow_ip not in [True, False]:
|
||||||
raise ValueError(_('allow_ip must be a boolean'))
|
raise ValueError(_('allow_ip must be a boolean'))
|
||||||
if allow_without_dot not in [True, False]:
|
if allow_without_dot not in [True, False]:
|
||||||
raise ValueError(_('allow_without_dot must be a boolean'))
|
raise ValueError(_('allow_without_dot must be a boolean'))
|
||||||
self._allow_ip = allow_ip
|
self._extra['_allow_ip'] = allow_ip
|
||||||
self._allow_without_dot = allow_without_dot
|
self._extra['_allow_without_dot'] = allow_without_dot
|
||||||
end = ''
|
end = ''
|
||||||
extrachar = ''
|
extrachar = ''
|
||||||
extrachar_mandatory = ''
|
extrachar_mandatory = ''
|
||||||
if self._dom_type == 'netbios':
|
if self._extra['_dom_type'] == 'netbios':
|
||||||
length = 14
|
length = 14
|
||||||
elif self._dom_type == 'hostname':
|
elif self._extra['_dom_type'] == 'hostname':
|
||||||
length = 62
|
length = 62
|
||||||
elif self._dom_type == 'domainname':
|
elif self._extra['_dom_type'] == 'domainname':
|
||||||
length = 62
|
length = 62
|
||||||
if allow_without_dot is False:
|
if allow_without_dot is False:
|
||||||
extrachar_mandatory = '\.'
|
extrachar_mandatory = '\.'
|
||||||
else:
|
else:
|
||||||
extrachar = '\.'
|
extrachar = '\.'
|
||||||
end = '+[a-z]*'
|
end = '+[a-z]*'
|
||||||
self._domain_re = re.compile(r'^(?:[a-z][a-z\d\-{0}]{{,{1}}}{2}){3}$'
|
self._extra['_domain_re'] = re.compile(r'^(?:[a-z][a-z\d\-{0}]{{,{1}}}{2}){3}$'
|
||||||
''.format(extrachar, length, extrachar_mandatory, end))
|
''.format(extrachar, length,
|
||||||
|
extrachar_mandatory,
|
||||||
|
end))
|
||||||
super(DomainnameOption, self).__init__(name, doc, default=default,
|
super(DomainnameOption, self).__init__(name, doc, default=default,
|
||||||
default_multi=default_multi,
|
default_multi=default_multi,
|
||||||
callback=callback,
|
callback=callback,
|
||||||
|
@ -1048,25 +1048,25 @@ class DomainnameOption(Option):
|
||||||
warnings_only=warnings_only)
|
warnings_only=warnings_only)
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
if self._allow_ip is True:
|
if self._extra['_allow_ip'] is True:
|
||||||
try:
|
try:
|
||||||
IP('{0}/32'.format(value))
|
IP('{0}/32'.format(value))
|
||||||
return
|
return
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
if self._dom_type == 'domainname' and not self._allow_without_dot and \
|
if self._extra['_dom_type'] == 'domainname' and not self._extra['_allow_without_dot'] and \
|
||||||
'.' not in value:
|
'.' not in value:
|
||||||
raise ValueError(_("invalid domainname, must have dot"))
|
raise ValueError(_("invalid domainname, must have dot"))
|
||||||
if len(value) > 255:
|
if len(value) > 255:
|
||||||
raise ValueError(_("invalid domainname's length (max 255)"))
|
raise ValueError(_("invalid domainname's length (max 255)"))
|
||||||
if len(value) < 2:
|
if len(value) < 2:
|
||||||
raise ValueError(_("invalid domainname's length (min 2)"))
|
raise ValueError(_("invalid domainname's length (min 2)"))
|
||||||
if not self._domain_re.search(value):
|
if not self._extra['_domain_re'].search(value):
|
||||||
raise ValueError(_('invalid domainname'))
|
raise ValueError(_('invalid domainname'))
|
||||||
|
|
||||||
|
|
||||||
class EmailOption(DomainnameOption):
|
class EmailOption(DomainnameOption):
|
||||||
#__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
username_re = re.compile(r"^[\w!#$%&'*+\-/=?^`{|}~.]+$")
|
username_re = re.compile(r"^[\w!#$%&'*+\-/=?^`{|}~.]+$")
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
|
@ -1082,7 +1082,7 @@ class EmailOption(DomainnameOption):
|
||||||
|
|
||||||
|
|
||||||
class URLOption(DomainnameOption):
|
class URLOption(DomainnameOption):
|
||||||
#__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
proto_re = re.compile(r'(http|https)://')
|
proto_re = re.compile(r'(http|https)://')
|
||||||
path_re = re.compile(r"^[a-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
|
path_re = re.compile(r"^[a-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
|
||||||
|
|
||||||
|
@ -1118,7 +1118,7 @@ class URLOption(DomainnameOption):
|
||||||
|
|
||||||
|
|
||||||
class FilenameOption(Option):
|
class FilenameOption(Option):
|
||||||
#__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
path_re = re.compile(r"^[a-zA-Z0-9\-\._~/+]+$")
|
path_re = re.compile(r"^[a-zA-Z0-9\-\._~/+]+$")
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
|
@ -1131,11 +1131,7 @@ class OptionDescription(BaseOption, StorageOptionDescription):
|
||||||
"""Config's schema (organisation, group) and container of Options
|
"""Config's schema (organisation, group) and container of Options
|
||||||
The `OptionsDescription` objects lives in the `tiramisu.config.Config`.
|
The `OptionsDescription` objects lives in the `tiramisu.config.Config`.
|
||||||
"""
|
"""
|
||||||
#_slots = ('_name', '_requires', '_cache_paths', '_group_type',
|
__slots__ = tuple()
|
||||||
# '_state_group_type', '_properties', '_children',
|
|
||||||
# '_cache_consistencies', '_calc_properties', '__weakref__',
|
|
||||||
# '_readonly', '_impl_informations', '_state_requires',
|
|
||||||
# '_stated', '_state_readonly')
|
|
||||||
|
|
||||||
def __init__(self, name, doc, children, requires=None, properties=None):
|
def __init__(self, name, doc, children, requires=None, properties=None):
|
||||||
"""
|
"""
|
||||||
|
@ -1153,16 +1149,12 @@ class OptionDescription(BaseOption, StorageOptionDescription):
|
||||||
raise ConflictError(_('duplicate option name: '
|
raise ConflictError(_('duplicate option name: '
|
||||||
'{0}').format(child))
|
'{0}').format(child))
|
||||||
old = child
|
old = child
|
||||||
for child in children:
|
self._add_children(child_names, children)
|
||||||
if child._parent is not None:
|
self._cache_paths = None
|
||||||
raise ConflictError(_('duplicate option: '
|
|
||||||
'{0}').format(child))
|
|
||||||
self._children.append(child) # = (tuple(child_names), tuple(children))
|
|
||||||
#FIXME pour dico !
|
|
||||||
#self._cache_paths = None
|
|
||||||
self._cache_consistencies = None
|
self._cache_consistencies = None
|
||||||
# the group_type is useful for filtering OptionDescriptions in a config
|
# the group_type is useful for filtering OptionDescriptions in a config
|
||||||
self._group_type = groups.default
|
self._group_type = groups.default
|
||||||
|
self._is_build_cache = False
|
||||||
|
|
||||||
def impl_getrequires(self):
|
def impl_getrequires(self):
|
||||||
return self._requires
|
return self._requires
|
||||||
|
@ -1192,12 +1184,6 @@ class OptionDescription(BaseOption, StorageOptionDescription):
|
||||||
paths.append('.'.join(_currpath + [attr]))
|
paths.append('.'.join(_currpath + [attr]))
|
||||||
return paths
|
return paths
|
||||||
|
|
||||||
def impl_getchildren(self):
|
|
||||||
#FIXME dans la base ??
|
|
||||||
return self._children
|
|
||||||
#for child in self._children:
|
|
||||||
# yield(session.query(child._type).filter_by(id=child.id).first())
|
|
||||||
|
|
||||||
def impl_build_cache_consistency(self, _consistencies=None, cache_option=None):
|
def impl_build_cache_consistency(self, _consistencies=None, cache_option=None):
|
||||||
#FIXME cache_option !
|
#FIXME cache_option !
|
||||||
if _consistencies is None:
|
if _consistencies is None:
|
||||||
|
@ -1207,11 +1193,9 @@ class OptionDescription(BaseOption, StorageOptionDescription):
|
||||||
else:
|
else:
|
||||||
init = False
|
init = False
|
||||||
for option in self.impl_getchildren():
|
for option in self.impl_getchildren():
|
||||||
cache_option.append(option.id)
|
cache_option.append(option._get_id())
|
||||||
if not isinstance(option, OptionDescription):
|
if not isinstance(option, OptionDescription):
|
||||||
for consistency in option._consistencies:
|
for func, all_cons_opts in option._get_consistencies():
|
||||||
func = consistency.func
|
|
||||||
all_cons_opts = consistency.options
|
|
||||||
for opt in all_cons_opts:
|
for opt in all_cons_opts:
|
||||||
_consistencies.setdefault(opt,
|
_consistencies.setdefault(opt,
|
||||||
[]).append((func,
|
[]).append((func,
|
||||||
|
@ -1222,7 +1206,7 @@ class OptionDescription(BaseOption, StorageOptionDescription):
|
||||||
self._cache_consistencies = {}
|
self._cache_consistencies = {}
|
||||||
for opt, cons in _consistencies.items():
|
for opt, cons in _consistencies.items():
|
||||||
#FIXME dans le cache ...
|
#FIXME dans le cache ...
|
||||||
if opt.id not in cache_option:
|
if opt._get_id() not in cache_option:
|
||||||
raise ConfigError(_('consistency with option {0} '
|
raise ConfigError(_('consistency with option {0} '
|
||||||
'which is not in Config').format(
|
'which is not in Config').format(
|
||||||
opt.impl_getname()))
|
opt.impl_getname()))
|
||||||
|
@ -1239,12 +1223,12 @@ class OptionDescription(BaseOption, StorageOptionDescription):
|
||||||
for option in self.impl_getchildren():
|
for option in self.impl_getchildren():
|
||||||
#FIXME specifique id for sqlalchemy?
|
#FIXME specifique id for sqlalchemy?
|
||||||
#FIXME avec sqlalchemy ca marche le multi parent ? (dans des configs différentes)
|
#FIXME avec sqlalchemy ca marche le multi parent ? (dans des configs différentes)
|
||||||
if option.id is None:
|
#if option.id is None:
|
||||||
raise SystemError(_("an option's id should not be None "
|
# raise SystemError(_("an option's id should not be None "
|
||||||
"for {0}").format(option.impl_getname()))
|
# "for {0}").format(option.impl_getname()))
|
||||||
if option.id in cache_option:
|
if option._get_id() in cache_option:
|
||||||
raise ConflictError(_('duplicate option: {0}').format(option))
|
raise ConflictError(_('duplicate option: {0}').format(option))
|
||||||
cache_option.append(option.id)
|
cache_option.append(option._get_id())
|
||||||
option._readonly = True
|
option._readonly = True
|
||||||
if isinstance(option, OptionDescription):
|
if isinstance(option, OptionDescription):
|
||||||
option.impl_validate_options(cache_option)
|
option.impl_validate_options(cache_option)
|
||||||
|
|
|
@ -220,6 +220,19 @@ class _Consistency(SqlAlchemyBase):
|
||||||
option._consistencies.append(self)
|
option._consistencies.append(self)
|
||||||
|
|
||||||
|
|
||||||
|
class _Parent(SqlAlchemyBase):
|
||||||
|
__tablename__ = 'parent'
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
child_id = Column(Integer)
|
||||||
|
child_name = Column(String)
|
||||||
|
parent_id = Column(Integer)
|
||||||
|
|
||||||
|
def __init__(self, parent, child):
|
||||||
|
self.parent_id = parent.id
|
||||||
|
self.child_id = child.id
|
||||||
|
self.child_name = child._name
|
||||||
|
|
||||||
|
|
||||||
#____________________________________________________________
|
#____________________________________________________________
|
||||||
#
|
#
|
||||||
# Base
|
# Base
|
||||||
|
@ -252,8 +265,6 @@ class _Base(SqlAlchemyBase):
|
||||||
_validator_params = association_proxy("_call_params", "params",
|
_validator_params = association_proxy("_call_params", "params",
|
||||||
getset_factory=load_callback_parm)
|
getset_factory=load_callback_parm)
|
||||||
######
|
######
|
||||||
_parent = Column(Integer, ForeignKey('baseoption.id'))
|
|
||||||
_children = relationship('BaseOption', enable_typechecks=False)
|
|
||||||
#FIXME pas 2 fois la meme properties dans la base ...
|
#FIXME pas 2 fois la meme properties dans la base ...
|
||||||
#FIXME not autoload
|
#FIXME not autoload
|
||||||
#FIXME normalement tuple ... transforme en set !
|
#FIXME normalement tuple ... transforme en set !
|
||||||
|
@ -266,8 +277,6 @@ class _Base(SqlAlchemyBase):
|
||||||
_readonly = Column(Boolean, default=False)
|
_readonly = Column(Boolean, default=False)
|
||||||
_consistencies = relationship('_Consistency', secondary=consistency_table,
|
_consistencies = relationship('_Consistency', secondary=consistency_table,
|
||||||
backref=backref('options', enable_typechecks=False))
|
backref=backref('options', enable_typechecks=False))
|
||||||
_choice_values = Column(PickleType)
|
|
||||||
_choice_open_values = Column(Boolean)
|
|
||||||
_type = Column(String(50))
|
_type = Column(String(50))
|
||||||
__mapper_args__ = {
|
__mapper_args__ = {
|
||||||
'polymorphic_identity': 'option',
|
'polymorphic_identity': 'option',
|
||||||
|
@ -285,44 +294,45 @@ class _Base(SqlAlchemyBase):
|
||||||
session.add(self)
|
session.add(self)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
def _get_property_object(self, propname):
|
|
||||||
prop_obj = session.query(_PropertyOption).filter(_PropertyOption.name == propname).first()
|
|
||||||
if prop_obj is None:
|
|
||||||
prop_obj = _PropertyOption(propname)
|
|
||||||
return prop_obj
|
|
||||||
|
|
||||||
def _add_consistency(self, func, all_cons_opts):
|
def _add_consistency(self, func, all_cons_opts):
|
||||||
_Consistency(func, all_cons_opts)
|
_Consistency(func, all_cons_opts)
|
||||||
|
|
||||||
|
def _get_consistencies(self):
|
||||||
|
return [(consistency.func, consistency.options) for consistency in self._consistencies]
|
||||||
|
|
||||||
|
def _get_id(self):
|
||||||
|
return self.id
|
||||||
|
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
# information
|
# information
|
||||||
def impl_set_information(self, key, value):
|
#def impl_set_information(self, key, value):
|
||||||
"""updates the information's attribute
|
# """updates the information's attribute
|
||||||
(which is a dictionary)
|
# (which is a dictionary)
|
||||||
|
|
||||||
:param key: information's key (ex: "help", "doc"
|
# :param key: information's key (ex: "help", "doc"
|
||||||
:param value: information's value (ex: "the help string")
|
# :param value: information's value (ex: "the help string")
|
||||||
"""
|
# """
|
||||||
info = session.query(_Information).filter_by(option=self.id, key=key).first()
|
# info = session.query(_Information).filter_by(option=self.id, key=key).first()
|
||||||
#FIXME pas append ! remplacer !
|
# #FIXME pas append ! remplacer !
|
||||||
if info is None:
|
# if info is None:
|
||||||
self._informations.append(_Information(key, value))
|
# self._informations.append(_Information(key, value))
|
||||||
else:
|
# else:
|
||||||
info.value = value
|
# info.value = value
|
||||||
|
|
||||||
def impl_get_information(self, key, default=None):
|
#def impl_get_information(self, key, default=None):
|
||||||
"""retrieves one information's item
|
# """retrieves one information's item
|
||||||
|
|
||||||
:param key: the item string (ex: "help")
|
# :param key: the item string (ex: "help")
|
||||||
"""
|
# """
|
||||||
info = session.query(_Information).filter_by(option=self.id, key=key).first()
|
# info = session.query(_Information).filter_by(option=self.id, key=key).first()
|
||||||
if info is not None:
|
# if info is not None:
|
||||||
return info.value
|
# return info.value
|
||||||
elif default is not None:
|
# return self._informations[key]
|
||||||
return default
|
# elif default is not None:
|
||||||
else:
|
# return default
|
||||||
raise ValueError(_("information's item not found: {0}").format(
|
# else:
|
||||||
key))
|
# raise ValueError(_("information's item not found: {0}").format(
|
||||||
|
# key))
|
||||||
|
|
||||||
|
|
||||||
class Cache(SqlAlchemyBase):
|
class Cache(SqlAlchemyBase):
|
||||||
|
@ -413,15 +423,24 @@ class StorageOptionDescription(object):
|
||||||
ret.append((opt.path, option))
|
ret.append((opt.path, option))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def _add_children(self, child_names, children):
|
||||||
|
for child in children:
|
||||||
|
session.add(_Parent(self, child))
|
||||||
|
|
||||||
|
def impl_getchildren(self):
|
||||||
|
for child in session.query(_Parent).filter_by(parent_id=self.id).all():
|
||||||
|
yield(session.query(_Base).filter_by(id=child.child_id).first())
|
||||||
|
#return
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name.startswith('_') or name.startswith('impl_'):
|
if name.startswith('_') or name.startswith('impl_'):
|
||||||
return object.__getattribute__(self, name)
|
return object.__getattribute__(self, name)
|
||||||
ret = session.query(_Base).filter_by(_parent=self.id, _name=name).first()
|
child = session.query(_Parent).filter_by(parent_id=self.id, child_name=name).first()
|
||||||
if ret is None:
|
if child is None:
|
||||||
raise AttributeError(_('unknown Option {0} '
|
raise AttributeError(_('unknown Option {0} '
|
||||||
'in OptionDescription {1}'
|
'in OptionDescription {1}'
|
||||||
'').format(name, self.impl_getname()))
|
'').format(name, self.impl_getname()))
|
||||||
return ret
|
return session.query(_Base).filter_by(id=child.child_id).first()
|
||||||
|
|
||||||
|
|
||||||
class StorageBase(_Base):
|
class StorageBase(_Base):
|
||||||
|
|
Loading…
Reference in New Issue