diff --git a/test/test_dereference.py b/test/test_dereference.py index eed4b72..e24e1e8 100644 --- a/test/test_dereference.py +++ b/test/test_dereference.py @@ -68,7 +68,7 @@ def test_deref_optiondescription(): def test_deref_option_cache(): b = BoolOption('b', '') o = OptionDescription('od', '', [b]) - o.impl_build_cache() + o.impl_build_cache_option() w = weakref.ref(b) del(b) assert w() is not None @@ -81,7 +81,7 @@ def test_deref_option_cache(): def test_deref_optiondescription_cache(): b = BoolOption('b', '') o = OptionDescription('od', '', [b]) - o.impl_build_cache() + o.impl_build_cache_option() w = weakref.ref(o) del(b) assert w() is not None @@ -103,6 +103,7 @@ def test_deref_option_config(): #FIXME meme chose #assert w() is None + #FIXME rien a voir mais si je fais un config.impl_get_path_by_opt() ca me retourne la methode ! def test_deref_optiondescription_config(): b = BoolOption('b', '') diff --git a/tiramisu/config.py b/tiramisu/config.py index c9553f2..95a7685 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -475,8 +475,11 @@ class CommonConfig(SubConfig): "abstract base class for the Config and the MetaConfig" __slots__ = ('_impl_values', '_impl_settings', '_impl_meta') - def _impl_build_all_paths(self): - self.cfgimpl_get_description().impl_build_cache() + def _impl_build_all_caches(self): + if not self.cfgimpl_get_description().impl_already_build_caches(): + self.cfgimpl_get_description().impl_build_cache_consistency() + self.cfgimpl_get_description().impl_validate_options() + self.cfgimpl_get_description().impl_build_cache_option() def read_only(self): "read only is a global config's setting, see `settings.py`" @@ -553,7 +556,7 @@ class Config(CommonConfig): self._impl_settings = Settings(self, settings) self._impl_values = Values(self, values) super(Config, self).__init__(descr, weakref.ref(self)) - self._impl_build_all_paths() + self._impl_build_all_caches() self._impl_meta = None #undocumented option used only in test script self._impl_test = False diff --git a/tiramisu/option.py b/tiramisu/option.py index a295737..014be90 100644 --- a/tiramisu/option.py +++ b/tiramisu/option.py @@ -1223,64 +1223,82 @@ class OptionDescription(BaseOption, StorageOptionDescription): #for child in self._children: # yield(session.query(child._type).filter_by(id=child.id).first()) - def impl_build_cache(self, - cache_path=None, - cache_option=None, - _currpath=None, - _consistencies=None, - force_no_consistencies=False): - if _currpath is None and self._cache_paths is not None: - # cache already set - return - if _currpath is None: - save = True - _currpath = [] - if not force_no_consistencies: - _consistencies = {} + def impl_build_cache_consistency(self, _consistencies=None): + #FIXME cache_option ! + if _consistencies is None: + init = True + _consistencies = {} else: - save = False - if cache_path is None: - cache_path = [] - cache_option = [] + init = False for option in self.impl_getchildren(): - attr = option.impl_getname() + if not isinstance(option, OptionDescription): + for consistency in option._consistencies: + func = consistency.func + all_cons_opts = consistency.options + for opt in all_cons_opts: + _consistencies.setdefault(opt, + []).append((func, + all_cons_opts)) + else: + option.impl_build_cache_consistency(_consistencies) + if init and _consistencies != {}: + self._cache_consistencies = {} + for opt, cons in _consistencies.items(): + #FIXME dans le cache ... + #if opt.id not in cache_option: + # raise ConfigError(_('consistency with option {0} ' + # 'which is not in Config').format( + # opt.impl_getname())) + self._cache_consistencies[opt] = tuple(cons) + + def impl_validate_options(self, cache_option=None): + """validate duplicate option and set option has readonly option + """ + if cache_option is None: + init = True + cache_option = [] + else: + init = False + for option in self.impl_getchildren(): + #FIXME specifique id for sqlalchemy? + #FIXME avec sqlalchemy ca marche le multi parent ? (dans des configs différentes) if option.id is None: raise SystemError(_("an option's id should not be None " "for {0}").format(option.impl_getname())) if option.id in cache_option: raise ConflictError(_('duplicate option: {0}').format(option)) cache_option.append(option.id) - if not force_no_consistencies: - option._readonly = True + option._readonly = True + if isinstance(option, OptionDescription): + option.impl_validate_options(cache_option) + if init: + self._readonly = True + + def impl_already_build_caches(self): + return self._cache_paths is not None + + def impl_build_cache_option(self, cache_path=None, cache_option=None, + _currpath=None): + if _currpath is None: + save = True + _currpath = [] + cache_path = [] + cache_option = [] + else: + save = False + for option in self.impl_getchildren(): + attr = option.impl_getname() + #FIXME specifique sqlachemy... + cache_option.append(option.id) cache_path.append(str('.'.join(_currpath + [attr]))) - if not isinstance(option, OptionDescription): - if not force_no_consistencies and \ - option._consistencies is not []: - for consistency in option._consistencies: - func = consistency.func - all_cons_opts = consistency.options - for opt in all_cons_opts: - _consistencies.setdefault(opt, - []).append((func, - all_cons_opts)) - else: + if isinstance(option, OptionDescription): _currpath.append(attr) - option.impl_build_cache(cache_path, - cache_option, - _currpath, - _consistencies, - force_no_consistencies) + option.impl_build_cache_option(cache_path, + cache_option, + _currpath) _currpath.pop() if save: self._cache_paths = (tuple(cache_option), tuple(cache_path)) - if not force_no_consistencies: - if _consistencies != {}: - self._cache_consistencies = {} - for opt, cons in _consistencies.items(): - if opt.id not in cache_option: - raise ConfigError(_('consistency with option {0} which is not in Config').format(opt.impl_getname())) - self._cache_consistencies[opt] = tuple(cons) - self._readonly = True # ____________________________________________________________ def impl_set_group_type(self, group_type): diff --git a/tiramisu/storage/sqlalchemy/option.py b/tiramisu/storage/sqlalchemy/option.py index 9d56607..b3a9042 100644 --- a/tiramisu/storage/sqlalchemy/option.py +++ b/tiramisu/storage/sqlalchemy/option.py @@ -29,6 +29,10 @@ from sqlalchemy.orm import sessionmaker #FIXME engine = create_engine('sqlite:///:memory:') SqlAlchemyBase = declarative_base() +#FIXME a voir: +# # Organization.members will be a Query object - no loading +# # of the entire collection occurs unless requested +# lazy="dynamic", #____________________________________________________________ # # require @@ -51,7 +55,8 @@ class _RequireExpected(SqlAlchemyBase): class _RequireOption(SqlAlchemyBase): __tablename__ = 'requireoption' id = Column(Integer, primary_key=True) - r_opt = Column(Integer) + option = relationship('_Base', lazy='joined', cascade="all, delete-orphan") + #option = relationship('_Base') expected = relationship("_RequireExpected") action = Column(String, nullable=False) inverse = Column(Boolean, default=False) @@ -60,7 +65,8 @@ class _RequireOption(SqlAlchemyBase): def __init__(self, option, expected, action, inverse, transitive, same_action): - self.r_opt = option.id + #self.r_opt = option.id + self.option = option for expect in expected: self.expected.append(_RequireExpected(expect)) self.action = action @@ -175,7 +181,7 @@ class _Base(SqlAlchemyBase): _default = Column(PickleType) _default_multi = Column(PickleType) _requires = relationship('_RequireOption', secondary=require_table, - backref=backref('option', enable_typechecks=False)) + backref=backref('self_option', enable_typechecks=False)) _multi = Column(Boolean) _multitype = Column(String) _callback = Column(PickleType) @@ -193,6 +199,7 @@ class _Base(SqlAlchemyBase): _choice_values = Column(PickleType) _choice_open_values = Column(Boolean) _type = Column(String(50)) + _r_option = Column(Integer, ForeignKey('requireoption.id')) __mapper_args__ = { 'polymorphic_identity': 'option', 'polymorphic_on': _type @@ -268,7 +275,8 @@ class StorageOptionDescription(object): def impl_get_path_by_opt(self, opt): try: - return self._cache_paths[1][self._cache_paths[0].index(opt)] + print opt, type(opt) + return self._cache_paths[1][self._cache_paths[0].index(opt.id)] except ValueError: raise AttributeError(_('no option {0} found').format(opt))