diff --git a/test/test_option_calculation.py b/test/test_option_calculation.py index 2cacf5e..8c73a5a 100644 --- a/test/test_option_calculation.py +++ b/test/test_option_calculation.py @@ -481,6 +481,7 @@ def test_callback_master_and_slaves_slave_list(): assert cfg.val1.val2 == ['val', 'val'] cfg.val1.val1 = ['val1'] #wrong len + print cfg.val1.val2 raises(SlaveError, 'cfg.val1.val2') diff --git a/tiramisu/autolib.py b/tiramisu/autolib.py index 503bcdd..f61cf18 100644 --- a/tiramisu/autolib.py +++ b/tiramisu/autolib.py @@ -148,7 +148,7 @@ def carry_out_calculation(option, config, callback, callback_params, for callbk in callbacks.params: if callbk.option is not None: # callbk is something link (opt, True|False) - opt = callbk.get_option(config) + opt = callbk.option force_permissive = callbk.force_permissive path = config.cfgimpl_get_description().impl_get_path_by_opt( opt) diff --git a/tiramisu/option.py b/tiramisu/option.py index 7de14a2..b6e01e8 100644 --- a/tiramisu/option.py +++ b/tiramisu/option.py @@ -28,17 +28,15 @@ from IPy import IP import warnings #from pickle import loads, dumps -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy import create_engine, Column, Integer, String, Boolean, \ - PickleType, ForeignKey, Table -from sqlalchemy.orm import relationship, backref -from sqlalchemy.orm import sessionmaker - from tiramisu.error import ConfigError, ConflictError, ValueWarning from tiramisu.setting import groups, multitypes from tiramisu.i18n import _ from tiramisu.autolib import carry_out_calculation +#FIXME : need storage... +from tiramisu.storage.sqlalchemy.option import StorageBase, StorageOptionDescription +from sqlalchemy.ext.declarative import declarative_base, declared_attr + name_regexp = re.compile(r'^\d+') forbidden_names = ('iter_all', 'iter_group', 'find', 'find_first', 'make_dict', 'unwrap_from_path', 'read_only', @@ -58,170 +56,7 @@ def valid_name(name): return False #____________________________________________________________ # - -engine = create_engine('sqlite:///:memory:') -Base = declarative_base() - - -class _RequireExpected(Base): - __tablename__ = 'expected' - id = Column(Integer, primary_key=True) - expected = Column(PickleType) - require = Column(Integer, ForeignKey('require.id')) - - def __init__(self, expected): - self.expected = expected - - -class _RequireOption(Base): - __tablename__ = 'require' - id = Column(Integer, primary_key=True) - option = Column(Integer, ForeignKey('baseoption.id')) - r_opt = Column(Integer) - expected = relationship("_RequireExpected") - action = Column(String, nullable=False) - inverse = Column(Boolean, default=False) - transitive = Column(Boolean, default=True) - same_action = Column(Boolean, default=True) - - def __init__(self, option, expected, action, inverse, transitive, - same_action): - self.r_opt = option.id - for expect in expected: - self.expected.append(_RequireExpected(expect)) - self.action = action - self.inverse = inverse - self.transitive = transitive - self.same_action = same_action - - def get_expected(self): - for expected in self.expected: - yield(expected.expected) - - def get_option(self, config): - return config.cfgimpl_get_description().impl_get_opt_by_id(self.r_opt) - - -property_table = Table('property', Base.metadata, - Column('left_id', Integer, ForeignKey('propertyoption.name')), - Column('right_id', Integer, ForeignKey('baseoption.id')) - ) - - -class _PropertyOption(Base): - __tablename__ = 'propertyoption' - name = Column(String, primary_key=True) - - def __init__(self, name): - self.name = name - - -class _Information(Base): - __tablename__ = 'information' - id = Column(Integer, primary_key=True) - option = Column(Integer, ForeignKey('baseoption.id')) - key = Column(String) - value = Column(PickleType) - - def __init__(self, key, value): - self.key = key - self.value = value - - -class _CallbackParamOption(Base): - __tablename__ = 'callback_param_option' - id = Column(Integer, primary_key=True) - callback_param = Column(Integer, ForeignKey('callback_param.id')) - option = Column(Integer) - force_permissive = Column(Boolean) - value = Column(PickleType) - - def __init__(self, option=None, force_permissive=None, value=None): - if value is not None: - self.value = value - else: - if isinstance(option, SymLinkOption): - option = option._opt - self.option = option.id - self.force_permissive = force_permissive - - def get_option(self, config): - return config.cfgimpl_get_description().impl_get_opt_by_id(self.option) - - -class _CallbackParam(Base): - __tablename__ = 'callback_param' - id = Column(Integer, primary_key=True) - callback = Column(Integer, ForeignKey('baseoption.id')) - name = Column(String) - params = relationship('_CallbackParamOption') - - def __init__(self, name, params): - self.name = name - for param in params: - if isinstance(param, tuple): - self.params.append(_CallbackParamOption(option=param[0], - force_permissive=param[1])) - else: - self.params.append(_CallbackParamOption(value=param)) - - -consistency_table = Table('consistencyopt', Base.metadata, - Column('left_id', Integer, ForeignKey('consistency.id')), - Column('right_id', Integer, ForeignKey('baseoption.id')) - ) - - -class _Consistency(Base): - __tablename__ = 'consistency' - id = Column(Integer, primary_key=True) - func = Column(PickleType) - - def __init__(self, func, all_cons_opts): - self.func = func - for option in all_cons_opts: - option._consistencies.append(self) - - -class BaseOption(Base): - """This abstract base class stands for attribute access - in options that have to be set only once, it is of course done in the - __setattr__ method - """ - __tablename__ = 'baseoption' - id = Column(Integer, primary_key=True) - _name = Column(String) - _informations = relationship('_Information') - _default = Column(PickleType) - _default_multi = Column(PickleType) - _requires = relationship('_RequireOption') - _multi = Column(Boolean) - _multitype = Column(String) - _callback = Column(PickleType) - _callback_params = relationship('_CallbackParam') - _validator = Column(PickleType) - _validator_params = relationship('_CallbackParam') - _parent = Column(Integer, ForeignKey('baseoption.id')) - _children = relationship('BaseOption', enable_typechecks=False) - _properties = relationship('_PropertyOption', secondary=property_table, - backref=backref('options', enable_typechecks=False)) - _warnings_only = Column(Boolean) - _readonly = Column(Boolean, default=False) - _consistencies = relationship('_Consistency', secondary=consistency_table, - backref=backref('options', enable_typechecks=False)) - _choice_values = Column(PickleType) - _choice_open_values = Column(Boolean) - _type = Column(String(50)) - __mapper_args__ = { - 'polymorphic_identity': 'person', - 'polymorphic_on': _type - } - #FIXME devrait etre une table - _optiondescription_group_type = Column(String) - #__slots__ = ('_name', '_requires', '_properties', '_readonly', - # '_calc_properties', '_impl_informations', - # '_state_readonly', '_state_requires', '_stated') - +class Base(StorageBase): def __init__(self, name, doc, default=None, default_multi=None, requires=None, multi=False, callback=None, callback_params=None, validator=None, validator_params=None, @@ -235,7 +70,7 @@ class BaseOption(Base): if requires is not None: for values in requires.values(): for require in values.values(): - self._requires.append(_RequireOption(*require)) + self._add_require(require) if not multi and default_multi is not None: raise ValueError(_("a default_multi is set whereas multi is False" " in option: {0}").format(name)) @@ -271,7 +106,7 @@ class BaseOption(Base): self._validator = validator if validator_params is not None: for key, values in validator_params.items(): - self._validator_params.append(_CallbackParam(key, values)) + self._add_validator(key, values) if callback is None and callback_params is not None: raise ValueError(_("params defined for a callback function but " "no callback defined" @@ -281,7 +116,7 @@ class BaseOption(Base): self._callback = callback if callback_params is not None: for key, values in callback_params.items(): - self._callback_params.append(_CallbackParam(key, values)) + self._add_callback(key, values) if requires is not None and properties is not tuple(): set_forbidden_properties = set(properties) & set(requires.keys()) if set_forbidden_properties != frozenset(): @@ -298,41 +133,19 @@ class BaseOption(Base): else: self._default = default for prop in properties: - prop_obj = session.query(_PropertyOption).filter(_PropertyOption.name == prop).first() - if prop_obj is None: - prop_obj = _PropertyOption(prop) - self._properties.append(prop_obj) + self._properties.append(self._get_property_object(prop)) self._warnings_only = warnings_only + return super(Base, self).__init__() - # ____________________________________________________________ - # information - def impl_set_information(self, key, value): - """updates the information's attribute - (which is a dictionary) - :param key: information's key (ex: "help", "doc" - :param value: information's value (ex: "the help string") - """ - #FIXME pas append ! remplacer ! - info = session.query(_Information).filter_by(option=self.id, key=key).first() - if info is None: - self._informations.append(_Information(key, value)) - else: - info.value = value - - def impl_get_information(self, key, default=None): - """retrieves one information's item - - :param key: the item string (ex: "help") - """ - info = session.query(_Information).filter_by(option=self.id, key=key).first() - if info is not None: - return info.value - elif default is not None: - return default - else: - raise ValueError(_("information's item not found: {0}").format( - key)) +class BaseOption(Base): + """This abstract base class stands for attribute access + in options that have to be set only once, it is of course done in the + __setattr__ method + """ + #__slots__ = ('_name', '_requires', '_properties', '_readonly', + # '_calc_properties', '_impl_informations', + # '_state_readonly', '_state_requires', '_stated') # ____________________________________________________________ # serialize object @@ -500,8 +313,6 @@ class Option(BaseOption): validator_params, properties, warnings_only, choice_values, choice_open_values) - session.add(self) - session.commit() #def __setattr__(self, name, value): # """set once and only once some attributes in the option, @@ -749,7 +560,7 @@ class Option(BaseOption): else: self._launch_consistency(func, self, value, None, None, all_cons_opts) - _Consistency(func, all_cons_opts) + self._add_consistency(func, all_cons_opts) self.impl_validate(self.impl_getdefault()) def _cons_not_equal(self, opts, vals): @@ -856,10 +667,6 @@ class ChoiceOption(Option): """ #__slots__ = ('_values', '_open_values') - __mapper_args__ = { - 'polymorphic_identity': 'choice', - } - def __init__(self, name, doc, values, default=None, default_multi=None, requires=None, multi=False, callback=None, callback_params=None, open_values=False, validator=None, @@ -901,9 +708,6 @@ class ChoiceOption(Option): class BoolOption(Option): "represents a choice between ``True`` and ``False``" # __slots__ = tuple() - __mapper_args__ = { - 'polymorphic_identity': 'bool', - } def _validate(self, value): if not isinstance(value, bool): @@ -913,9 +717,6 @@ class BoolOption(Option): class IntOption(Option): "represents a choice of an integer" # __slots__ = tuple() - __mapper_args__ = { - 'polymorphic_identity': 'int', - } def _validate(self, value): if not isinstance(value, int): @@ -925,9 +726,6 @@ class IntOption(Option): class FloatOption(Option): "represents a choice of a floating point number" #__slots__ = tuple() - __mapper_args__ = { - 'polymorphic_identity': 'float', - } def _validate(self, value): if not isinstance(value, float): @@ -937,9 +735,6 @@ class FloatOption(Option): class StrOption(Option): "represents the choice of a string" #__slots__ = tuple() - __mapper_args__ = { - 'polymorphic_identity': 'string', - } def _validate(self, value): if not isinstance(value, str): @@ -955,9 +750,6 @@ else: class UnicodeOption(Option): "represents the choice of a unicode string" #__slots__ = tuple() - __mapper_args__ = { - 'polymorphic_identity': 'unicode', - } _empty = u'' def _validate(self, value): @@ -967,9 +759,6 @@ else: class SymLinkOption(BaseOption): #__slots__ = ('_name', '_opt', '_state_opt', '_readonly', '_parent') - __mapper_args__ = { - 'polymorphic_identity': 'symlink', - } #not return _opt consistencies #_consistencies = None @@ -982,8 +771,7 @@ class SymLinkOption(BaseOption): self._opt = opt self._readonly = True self._parent = None - session.add(self) - session.commit() + self.commit() def __getattr__(self, name): if name in ('_opt', '_opt_type', '_readonly', 'impl_getname'): @@ -1001,17 +789,13 @@ class SymLinkOption(BaseOption): super(SymLinkOption, self)._impl_setstate(descr) def impl_get_information(self, key, default=None): - #FIXME ne devrait pas etre util si ? + #FIXME ne devrait pas etre utile si ? return self._opt.impl_get_information(key, default) class IPOption(Option): "represents the choice of an ip" #__slots__ = ('_private_only', '_allow_reserved') - __mapper_args__ = { - 'polymorphic_identity': 'ip', - } - def __init__(self, name, doc, default=None, default_multi=None, requires=None, multi=False, callback=None, callback_params=None, validator=None, validator_params=None, @@ -1061,10 +845,6 @@ class PortOption(Option): see: http://en.wikipedia.org/wiki/Port_numbers """ #__slots__ = ('_allow_range', '_allow_zero', '_min_value', '_max_value') - __mapper_args__ = { - 'polymorphic_identity': 'port', - } - def __init__(self, name, doc, default=None, default_multi=None, requires=None, multi=False, callback=None, callback_params=None, validator=None, validator_params=None, @@ -1126,10 +906,6 @@ class PortOption(Option): class NetworkOption(Option): "represents the choice of a network" #__slots__ = tuple() - __mapper_args__ = { - 'polymorphic_identity': 'network', - } - def _validate(self, value): try: IP(value) @@ -1145,9 +921,6 @@ class NetworkOption(Option): class NetmaskOption(Option): "represents the choice of a netmask" #__slots__ = tuple() - __mapper_args__ = { - 'polymorphic_identity': 'netmask', - } def _validate(self, value): try: @@ -1201,9 +974,6 @@ class NetmaskOption(Option): class BroadcastOption(Option): #__slots__ = tuple() - __mapper_args__ = { - 'polymorphic_identity': 'broadcast', - } def _validate(self, value): try: @@ -1232,9 +1002,6 @@ class DomainnameOption(Option): fqdn: with tld, not supported yet """ #__slots__ = ('_dom_type', '_allow_ip', '_allow_without_dot', '_domain_re') - __mapper_args__ = { - 'polymorphic_identity': 'domainname', - } def __init__(self, name, doc, default=None, default_multi=None, requires=None, multi=False, callback=None, @@ -1297,9 +1064,6 @@ class DomainnameOption(Option): class EmailOption(DomainnameOption): #__slots__ = tuple() - __mapper_args__ = { - 'polymorphic_identity': 'email', - } username_re = re.compile(r"^[\w!#$%&'*+\-/=?^`{|}~.]+$") def _validate(self, value): @@ -1316,9 +1080,6 @@ class EmailOption(DomainnameOption): class URLOption(DomainnameOption): #__slots__ = tuple() - __mapper_args__ = { - 'polymorphic_identity': 'url', - } proto_re = re.compile(r'(http|https)://') path_re = re.compile(r"^[a-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$") @@ -1355,9 +1116,6 @@ class URLOption(DomainnameOption): class FilenameOption(Option): #__slots__ = tuple() - __mapper_args__ = { - 'polymorphic_identity': 'file', - } path_re = re.compile(r"^[a-zA-Z0-9\-\._~/+]+$") def _validate(self, value): @@ -1366,7 +1124,7 @@ class FilenameOption(Option): raise ValueError(_('invalid filename')) -class OptionDescription(BaseOption): +class OptionDescription(BaseOption, StorageOptionDescription): """Config's schema (organisation, group) and container of Options The `OptionsDescription` objects lives in the `tiramisu.config.Config`. """ @@ -1375,9 +1133,6 @@ class OptionDescription(BaseOption): # '_cache_consistencies', '_calc_properties', '__weakref__', # '_readonly', '_impl_informations', '_state_requires', # '_stated', '_state_readonly') - __mapper_args__ = { - 'polymorphic_identity': 'optiondescription', - } def __init__(self, name, doc, children, requires=None, properties=None): """ @@ -1385,8 +1140,6 @@ class OptionDescription(BaseOption): """ super(OptionDescription, self).__init__(name, doc=doc, requires=requires, properties=properties) - session.add(self) - session.commit() child_names = [child.impl_getname() for child in children] #better performance like this valid_child = copy(child_names) @@ -1528,28 +1281,6 @@ class OptionDescription(BaseOption): self._cache_consistencies[opt] = tuple(cons) self._readonly = True - def impl_get_opt_by_path(self, path): - try: - #FIXME - idx = self._cache_paths[1].index(path) - opt_id = self._cache_paths[0][idx] - return session.query(BaseOption).filter_by(id=opt_id).first() - except ValueError: - raise AttributeError(_('no option for path {0}').format(path)) - - def impl_get_opt_by_id(self, opt_id): - try: - #FIXME - #idx = self._cache_paths[0].index(opt_id) - return session.query(BaseOption).filter_by(id=opt_id).first() - except ValueError: - raise AttributeError(_('no id {0} found').format(opt_id)) - - def impl_get_path_by_opt(self, opt): - try: - return self._cache_paths[1][self._cache_paths[0].index(opt.id)] - except ValueError: - raise AttributeError(_('no option {0} found').format(opt)) # ____________________________________________________________ def impl_set_group_type(self, group_type): @@ -1800,8 +1531,3 @@ def validate_callback(callback, callback_params, type_): ' not a {0} for second argument' ).format(type_, type( force_permissive))) - -#FIXME -Base.metadata.create_all(engine) -Session = sessionmaker(bind=engine) -session = Session() diff --git a/tiramisu/setting.py b/tiramisu/setting.py index 6a69986..c461d5e 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -588,7 +588,7 @@ class Settings(object): for require in opt.impl_getrequires(): expected = tuple(require.get_expected()) inverse = require.inverse - option = require.get_option(self.context()) + option = require.option reqpath = self._get_path_by_opt(option) if reqpath == path or reqpath.startswith(path + '.'): raise RequirementError(_("malformed requirements " diff --git a/tiramisu/storage/sqlalchemy/__init__.py b/tiramisu/storage/sqlalchemy/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tiramisu/storage/sqlalchemy/option.py b/tiramisu/storage/sqlalchemy/option.py new file mode 100644 index 0000000..b408daa --- /dev/null +++ b/tiramisu/storage/sqlalchemy/option.py @@ -0,0 +1,284 @@ +# -*- coding: utf-8 -*- +"" +# Copyright (C) 2014 Team tiramisu (see AUTHORS for all contributors) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# ____________________________________________________________ +from tiramisu.setting import multitypes + + +from sqlalchemy.ext.declarative import declarative_base, declared_attr +from sqlalchemy import create_engine, Column, Integer, String, Boolean, \ + PickleType, ForeignKey, Table +from sqlalchemy.orm import relationship, backref +from sqlalchemy.orm import sessionmaker + + +#FIXME +engine = create_engine('sqlite:///:memory:') +SqlAlchemyBase = declarative_base() +#____________________________________________________________ +# +# require +require_table = Table('require', SqlAlchemyBase.metadata, + Column('left_id', Integer, ForeignKey('requireoption.id')), + Column('right_id', Integer, ForeignKey('baseoption.id')) + ) + +class _RequireExpected(SqlAlchemyBase): + __tablename__ = 'expected' + id = Column(Integer, primary_key=True) + expected = Column(PickleType) + require = Column(Integer, ForeignKey('requireoption.id')) + + def __init__(self, expected): + self.expected = expected + + +class _RequireOption(SqlAlchemyBase): + __tablename__ = 'requireoption' + id = Column(Integer, primary_key=True) + r_opt = Column(Integer) + expected = relationship("_RequireExpected") + action = Column(String, nullable=False) + inverse = Column(Boolean, default=False) + transitive = Column(Boolean, default=True) + same_action = Column(Boolean, default=True) + + def __init__(self, option, expected, action, inverse, transitive, + same_action): + self.r_opt = option.id + for expect in expected: + self.expected.append(_RequireExpected(expect)) + self.action = action + self.inverse = inverse + self.transitive = transitive + self.same_action = same_action + + def get_expected(self): + for expected in self.expected: + yield(expected.expected) + + #def get_option(self, config): + # return config.cfgimpl_get_description().impl_get_opt_by_id(self.r_opt) + + +#____________________________________________________________ +# +# properties +property_table = Table('property', SqlAlchemyBase.metadata, + Column('left_id', Integer, ForeignKey('propertyoption.name')), + Column('right_id', Integer, ForeignKey('baseoption.id')) + ) + + +class _PropertyOption(SqlAlchemyBase): + __tablename__ = 'propertyoption' + name = Column(String, primary_key=True) + + def __init__(self, name): + self.name = name + + +#____________________________________________________________ +# +# information +class _Information(SqlAlchemyBase): + __tablename__ = 'information' + id = Column(Integer, primary_key=True) + option = Column(Integer, ForeignKey('baseoption.id')) + key = Column(String) + value = Column(PickleType) + + def __init__(self, key, value): + self.key = key + self.value = value + + +#____________________________________________________________ +# +# callback +class _CallbackParamOption(SqlAlchemyBase): + __tablename__ = 'callback_param_option' + id = Column(Integer, primary_key=True) + callback_param = Column(Integer, ForeignKey('callback_param.id')) + option = Column(Integer) + force_permissive = Column(Boolean) + value = Column(PickleType) + + def __init__(self, option=None, force_permissive=None, value=None): + if value is not None: + self.value = value + else: + self.option = option.id + self.force_permissive = force_permissive + + +class _CallbackParam(SqlAlchemyBase): + __tablename__ = 'callback_param' + id = Column(Integer, primary_key=True) + callback = Column(Integer, ForeignKey('baseoption.id')) + name = Column(String) + params = relationship('_CallbackParamOption') + + def __init__(self, name, params): + self.name = name + for param in params: + if isinstance(param, tuple): + self.params.append(_CallbackParamOption(option=param[0], + force_permissive=param[1])) + else: + self.params.append(_CallbackParamOption(value=param)) + + +#____________________________________________________________ +# +# consistency +consistency_table = Table('consistencyopt', SqlAlchemyBase.metadata, + Column('left_id', Integer, ForeignKey('consistency.id')), + Column('right_id', Integer, ForeignKey('baseoption.id')) + ) + + +class _Consistency(SqlAlchemyBase): + __tablename__ = 'consistency' + id = Column(Integer, primary_key=True) + func = Column(PickleType) + + def __init__(self, func, all_cons_opts): + self.func = func + for option in all_cons_opts: + option._consistencies.append(self) + + +#____________________________________________________________ +# +# Base +class _Base(SqlAlchemyBase): + __tablename__ = 'baseoption' + id = Column(Integer, primary_key=True) + _name = Column(String) + _informations = relationship('_Information') + _default = Column(PickleType) + _default_multi = Column(PickleType) + _requires = relationship('_RequireOption', secondary=require_table, + backref=backref('option', enable_typechecks=False)) + _multi = Column(Boolean) + _multitype = Column(String) + _callback = Column(PickleType) + _callback_params = relationship('_CallbackParam') + _validator = Column(PickleType) + _validator_params = relationship('_CallbackParam') + _parent = Column(Integer, ForeignKey('baseoption.id')) + _children = relationship('BaseOption', enable_typechecks=False) + _properties = relationship('_PropertyOption', secondary=property_table, + backref=backref('options', enable_typechecks=False)) + _warnings_only = Column(Boolean) + _readonly = Column(Boolean, default=False) + _consistencies = relationship('_Consistency', secondary=consistency_table, + backref=backref('options', enable_typechecks=False)) + _choice_values = Column(PickleType) + _choice_open_values = Column(Boolean) + _type = Column(String(50)) + __mapper_args__ = { + 'polymorphic_identity': 'option', + 'polymorphic_on': _type + } + #FIXME devrait etre une table + _optiondescription_group_type = Column(String) + + def __init__(self): + self.commit() + + def commit(self): + session.add(self) + 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_require(self, require): + self._requires.append(_RequireOption(*require)) + + def _add_callback(self, key, values): + self._callback_params.append(_CallbackParam(key, values)) + + def _add_validator(self, key, values): + self._validator_params.append(_CallbackParam(key, values)) + + def _add_consistency(self, func, all_cons_opts): + _Consistency(func, all_cons_opts) + # ____________________________________________________________ + # information + def impl_set_information(self, key, value): + """updates the information's attribute + (which is a dictionary) + + :param key: information's key (ex: "help", "doc" + :param value: information's value (ex: "the help string") + """ + info = session.query(_Information).filter_by(option=self.id, key=key).first() + #FIXME pas append ! remplacer ! + if info is None: + self._informations.append(_Information(key, value)) + else: + info.value = value + + def impl_get_information(self, key, default=None): + """retrieves one information's item + + :param key: the item string (ex: "help") + """ + info = session.query(_Information).filter_by(option=self.id, key=key).first() + if info is not None: + return info.value + elif default is not None: + return default + else: + raise ValueError(_("information's item not found: {0}").format( + key)) + + +class StorageOptionDescription(object): + def impl_get_opt_by_path(self, path): + try: + #FIXME + idx = self._cache_paths[1].index(path) + opt_id = self._cache_paths[0][idx] + return session.query(_Base).filter_by(id=opt_id).first() + except ValueError: + raise AttributeError(_('no option for path {0}').format(path)) + + def impl_get_path_by_opt(self, opt): + try: + return self._cache_paths[1][self._cache_paths[0].index(opt)] + except ValueError: + raise AttributeError(_('no option {0} found').format(opt)) + + +class StorageBase(_Base): + @declared_attr + def __mapper_args__(self): + return {'polymorphic_identity': self.__name__.lower()} + + +#FIXME +SqlAlchemyBase.metadata.create_all(engine) +Session = sessionmaker(bind=engine) +session = Session() diff --git a/tiramisu/storage/util.py b/tiramisu/storage/util.py index 68482e6..88cf787 100644 --- a/tiramisu/storage/util.py +++ b/tiramisu/storage/util.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -"default plugin for cache: set it in a simple dictionary" +"utils used by storage" # Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors) # # This program is free software; you can redistribute it and/or modify