# -*- coding: utf-8 -*- import os import re import tempfile from time import time from .basecache import BaseCache from .posixemulation import rename, _items try: import cPickle as pickle except ImportError: import pickle try: from hashlib import md5 except ImportError: from md5 import new as md5 class MemCache(BaseCache): """Simple memory cache for single process environments. This class exists mainly for the development server and is not 100% thread safe. It tries to use as many atomic operations as possible and no locks for simplicity but it could happen under heavy load that keys are added multiple times. :param threshold: the maximum number of items the cache stores before it starts deleting some. :param default_timeout: the default timeout that is used if no timeout is specified on :meth:`~BaseCache.set`. """ def __init__(self, threshold=500, default_timeout=300): BaseCache.__init__(self, default_timeout) self._cache = {} self.clear = self._cache.clear self._threshold = threshold def _prune(self): if len(self._cache) > self._threshold: now = time() for idx, (key, (expires, _)) in enumerate(self._cache.items()): if expires <= now or idx % 3 == 0: self._cache.pop(key, None) def get(self, key): now = time() expires, value = self._cache.get(key, (0, None)) if expires > time(): return pickle.loads(value) def set(self, key, value, timeout=None): if timeout is None: timeout = self.default_timeout self._prune() self._cache[key] = (time() + timeout, pickle.dumps(value, pickle.HIGHEST_PROTOCOL)) def add(self, key, value, timeout=None): if timeout is None: timeout = self.default_timeout if len(self._cache) > self._threshold: self._prune() item = (time() + timeout, pickle.dumps(value, pickle.HIGHEST_PROTOCOL)) self._cache.setdefault(key, item) def delete(self, key): self._cache.pop(key, None)