# -*- coding: utf-8 -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 import ulib.base.i_need_py23 __all__ = ('MultipleStore',) from ulib.base.base import isseq from ulib.base.uio import _s, _u from consts import * from store import AbstractStore class MultipleStore(AbstractStore): _stores = None _cstores = None _last_lsid = 0 def __init__(self, stores=None): AbstractStore.__init__(self) if stores is None: stores = () elif not isseq(stores): stores = (stores,) self._stores = [] for store in stores: self.add_store(store) def add_store(self, store): if store.get_sid() is None: store.set_lsid(self._last_lsid) self._last_lsid = self._last_lsid + 1 self._stores.append(store) self._cstores = None # pour qu'il soit reconstruit def get_name(self): u"""Retourner le nom de ce store. Il s'agit des noms de tous les stores gérés par ce store, séparés par des caractères '+'. @rtype: unicode """ return u"+".join([store.name for store in self.get_stores()]) name = property(get_name) _wstore = None def get_wstore(self): u"""Retourner le store destination, c'est à dire celui dans lequel on ajoute les tâches par défaut. Par défaut, il s'agit du premier store de la liste. @raise IndexError: s'il n'y a aucun stores """ if self._wstore is not None: return self._wstore else: if self._stores: return self._stores[0] raise IndexError("Unable to find destination store") def set_wstore(self, name=None): u"""Choisir le store destination. @param name: Nom du store à sélectionner, ou None pour prendre le premier de la liste. @return: self """ if name is None: self._wstore = None else: for store in self.get_stores(): if store.get_name() == name: self._wstore = store break else: raise ValueError("Invalid store: %s" % name) def get_stores(self, force=False): u"""Retourner la liste des stores gérés par ce store. Si c'est un store simple, la liste de contient qu'un élément. @param force: forcer la reconstruction de la liste. par défaut, utiliser une valeur mise en cache. @rtype: tuple """ if force or self._cstores is None: stores = [] for store in self._stores: stores.extend(store.get_stores()) self._cstores = tuple(stores) return self._cstores def get_store_by_sid(self, sid=None): u"""Obtenir le store dont on donne le sid, ou None si le sid n'existe pas. Si sid==None, retourner le store par défaut. @rtype: AbstractStore """ if sid is None: return self.get_store() sid = _u(sid) for store in self.get_stores(): if _u(store.sid) == sid: return store return None def get_tasks(self): tasks = [] for store in self.get_stores(): tasks.extend(store.tasks) return tasks tasks = property(get_tasks) def remove(self, task): for store in self.get_stores(): if store.remove(task): return True return False def load(self, infdn=None, force=False, force_reload=False, **ignored): if infdn is not None: raise ValueError("infdn is not supported for this store") for store in self.get_stores(): if force_reload or store.should_reload(): store.load(force=force) def should_reload(self): for store in self.get_stores(): if store.should_reload(): return True return False def revert(self): for store in self.get_stores(): store.revert() def save(self, outfdn=None, force=False): if outfdn is not None: raise ValueError("outfdn is not supported for this store") saved = False for store in self.get_stores(): if store.save(force=force): saved = True return saved