def __new__(cls, id=None, *args, **kwargs): """ Create a new object, handle caching if enabled """ # No caching when turned of or class does not support it if (config.get_cache_level() < config.CACHE_OBJECTS or getattr(cls, "_cache", None) is None): return super(TCMS, cls).__new__(cls) # Look up cached object by id (or other arguments in kwargs) try: # If found, we get instance and key by which it was found instance, key = cls._cache_lookup(id, **kwargs) if isinstance(key, int): log.cache("Using cached {0} ID#{1}".format(cls.__name__, key)) else: log.cache("Using cached {0} '{1}'".format(cls.__name__, key)) return instance # Object not cached yet, create a new one and cache it except KeyError: new = super(TCMS, cls).__new__(cls) if isinstance(id, int): log.cache("Caching {0} ID#{1}".format(cls.__name__, id)) cls._cache[id] = new elif isinstance(id, str) or "name" in kwargs: log.cache("Caching {0} '{1}'".format( cls.__name__, (id or kwargs.get("name")))) return new
def _index(self, *keys): """ Index self into the class cache if caching enabled """ # Skip indexing completely when caching off if config.get_cache_level() < config.CACHE_OBJECTS: return # Index by ID if self._id is not TCMSNone: self.__class__._cache[self._id] = self # Index each given key for key in keys: self.__class__._cache[key] = self
def setter(self, value): # Initialize the attribute unless already done if getattr(self, "_" + field) is TCMSNone: self._fetch() # Update only if changed if getattr(self, "_" + field) != value: setattr(self, "_" + field, value) log.info("Updating {0}'s {1} to '{2}'".format( self.identifier, field, value)) # Remember modified state if caching if config.get_cache_level() != config.CACHE_NONE: self._modified = True # Save the changes immediately otherwise else: self._update()
def _fetch(self, inset=None): """ Save cache timestamp and initialize from inset if given """ TCMS._fetch(self) # Create copies of the initial set (if given) if inset is not None: log.debug("Initializing {0} for {1} from the inset".format( self.__class__.__name__, self._identifier)) log.debug(pretty(inset)) self._current = set(inset) self._original = set(inset) # cache into container class if config.get_cache_level() >= config.CACHE_OBJECTS: self.__class__._cache[self._id] = self # Return True if the data are already initialized return inset is not None
def remove(self, items): """ Remove an item or a list of items from the container """ # Convert to set representation if isinstance(items, list): items = set(items) else: items = set([items]) # If there are any items to be removed remove_items = items.intersection(self._items) if remove_items: log.info("Removing {0} from {1}'s {2}".format( listed([item.identifier for item in remove_items], self._class.__name__, max=10), self._object.identifier, self.__class__.__name__)) self._items.difference_update(items) if config.get_cache_level() != config.CACHE_NONE: self._modified = True else: self._update()
def add(self, items): """ Add an item or a list of items to the container """ # Convert to set representation if isinstance(items, list): items = set(items) else: items = set([items]) # If there are any new items add_items = items - self._items if add_items: log.info("Adding {0} to {1}'s {2}".format( listed([item.identifier for item in add_items], self._class.__name__, max=10), self._object.identifier, self.__class__.__name__)) self._items.update(items) if config.get_cache_level() != config.CACHE_NONE: self._modified = True else: self._update()