diff MoinMoin/support/werkzeug/contrib/cache.py @ 6129:7f12cf241d5e

update werkzeug to 0.12.1, update CHANGES
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Tue, 11 Apr 2017 22:42:23 +0200
parents 9f12f41504fc
children
line wrap: on
line diff
--- a/MoinMoin/support/werkzeug/contrib/cache.py	Tue Nov 01 17:56:32 2016 +0100
+++ b/MoinMoin/support/werkzeug/contrib/cache.py	Tue Apr 11 22:42:23 2017 +0200
@@ -23,7 +23,7 @@
     Otherwise you generate the page and put it into the cache. (Or a fragment
     of the page, you don't have to cache the full thing)
 
-    Here is a simple example of how to cache a sidebar for a template::
+    Here is a simple example of how to cache a sidebar for 5 minutes::
 
         def get_sidebar(user):
             identifier = 'sidebar_for/user%d' % user.id
@@ -60,6 +60,7 @@
 import re
 import errno
 import tempfile
+import platform
 from hashlib import md5
 from time import time
 try:
@@ -93,14 +94,19 @@
     """Baseclass for the cache systems.  All the cache systems implement this
     API or a superset of it.
 
-    :param default_timeout: the default timeout (in seconds) that is used if no
-                            timeout is specified on :meth:`set`. A timeout of 0
-                            indicates that the cache never expires.
+    :param default_timeout: the default timeout (in seconds) that is used if
+                            no timeout is specified on :meth:`set`. A timeout
+                            of 0 indicates that the cache never expires.
     """
 
     def __init__(self, default_timeout=300):
         self.default_timeout = default_timeout
 
+    def _normalize_timeout(self, timeout):
+        if timeout is None:
+            timeout = self.default_timeout
+        return timeout
+
     def get(self, key):
         """Look up key in the cache and return the value for it.
 
@@ -149,9 +155,9 @@
 
         :param key: the key to set
         :param value: the value for the key
-        :param timeout: the cache timeout for the key (if not specified,
-                        it uses the default timeout). A timeout of 0 idicates
-                        that the cache never expires.
+        :param timeout: the cache timeout for the key in seconds (if not
+                        specified, it uses the default timeout). A timeout of
+                        0 idicates that the cache never expires.
         :returns: ``True`` if key has been updated, ``False`` for backend
                   errors. Pickling errors, however, will raise a subclass of
                   ``pickle.PickleError``.
@@ -165,9 +171,9 @@
 
         :param key: the key to set
         :param value: the value for the key
-        :param timeout: the cache timeout for the key or the default
-                        timeout if not specified. A timeout of 0 indicates
-                        that the cache never expires.
+        :param timeout: the cache timeout for the key in seconds (if not
+                        specified, it uses the default timeout). A timeout of
+                        0 idicates that the cache never expires.
         :returns: Same as :meth:`set`, but also ``False`` for already
                   existing keys.
         :rtype: boolean
@@ -178,9 +184,9 @@
         """Sets multiple keys and values from a mapping.
 
         :param mapping: a mapping with the keys/values to set.
-        :param timeout: the cache timeout for the key (if not specified,
-                        it uses the default timeout). A timeout of 0
-                        indicates tht the cache never expires.
+        :param timeout: the cache timeout for the key in seconds (if not
+                        specified, it uses the default timeout). A timeout of
+                        0 idicates that the cache never expires.
         :returns: Whether all given keys have been set.
         :rtype: boolean
         """
@@ -218,6 +224,7 @@
     def clear(self):
         """Clears the cache.  Keep in mind that not all caches support
         completely clearing the cache.
+
         :returns: Whether the cache has been cleared.
         :rtype: boolean
         """
@@ -289,9 +296,8 @@
             for key in toremove:
                 self._cache.pop(key, None)
 
-    def _get_expiration(self, timeout):
-        if timeout is None:
-            timeout = self.default_timeout
+    def _normalize_timeout(self, timeout):
+        timeout = BaseCache._normalize_timeout(self, timeout)
         if timeout > 0:
             timeout = time() + timeout
         return timeout
@@ -305,14 +311,14 @@
             return None
 
     def set(self, key, value, timeout=None):
-        expires = self._get_expiration(timeout)
+        expires = self._normalize_timeout(timeout)
         self._prune()
         self._cache[key] = (expires, pickle.dumps(value,
                                                   pickle.HIGHEST_PROTOCOL))
         return True
 
     def add(self, key, value, timeout=None):
-        expires = self._get_expiration(timeout)
+        expires = self._normalize_timeout(timeout)
         self._prune()
         item = (expires, pickle.dumps(value,
                                       pickle.HIGHEST_PROTOCOL))
@@ -391,8 +397,7 @@
         return key
 
     def _normalize_timeout(self, timeout):
-        if timeout is None:
-            timeout = self.default_timeout
+        timeout = BaseCache._normalize_timeout(self, timeout)
         if timeout > 0:
             timeout = int(time()) + timeout
         return timeout
@@ -561,9 +566,8 @@
             self._client = host
         self.key_prefix = key_prefix or ''
 
-    def _get_expiration(self, timeout):
-        if timeout is None:
-            timeout = self.default_timeout
+    def _normalize_timeout(self, timeout):
+        timeout = BaseCache._normalize_timeout(self, timeout)
         if timeout == 0:
             timeout = -1
         return timeout
@@ -603,7 +607,7 @@
         return [self.load_object(x) for x in self._client.mget(keys)]
 
     def set(self, key, value, timeout=None):
-        timeout = self._get_expiration(timeout)
+        timeout = self._normalize_timeout(timeout)
         dump = self.dump_object(value)
         if timeout == -1:
             result = self._client.set(name=self.key_prefix + key,
@@ -614,7 +618,7 @@
         return result
 
     def add(self, key, value, timeout=None):
-        timeout = self._get_expiration(timeout)
+        timeout = self._normalize_timeout(timeout)
         dump = self.dump_object(value)
         return (
             self._client.setnx(name=self.key_prefix + key, value=dump) and
@@ -622,7 +626,7 @@
         )
 
     def set_many(self, mapping, timeout=None):
-        timeout = self._get_expiration(timeout)
+        timeout = self._normalize_timeout(timeout)
         # Use transaction=False to batch without calling redis MULTI
         # which is not supported by twemproxy
         pipe = self._client.pipeline(transaction=False)
@@ -698,6 +702,12 @@
             if ex.errno != errno.EEXIST:
                 raise
 
+    def _normalize_timeout(self, timeout):
+        timeout = BaseCache._normalize_timeout(self, timeout)
+        if timeout != 0:
+            timeout = time() + timeout
+        return int(timeout)
+
     def _list_dir(self):
         """return a list of (fully qualified) cache filenames
         """
@@ -708,8 +718,8 @@
         entries = self._list_dir()
         if len(entries) > self._threshold:
             now = time()
-            try:
-                for idx, fname in enumerate(entries):
+            for idx, fname in enumerate(entries):
+                try:
                     remove = False
                     with open(fname, 'rb') as f:
                         expires = pickle.load(f)
@@ -717,8 +727,8 @@
 
                     if remove:
                         os.remove(fname)
-            except (IOError, OSError):
-                pass
+                except (IOError, OSError):
+                    pass
 
     def clear(self):
         for fname in self._list_dir():
@@ -754,10 +764,7 @@
         return False
 
     def set(self, key, value, timeout=None):
-        if timeout is None:
-            timeout = int(time() + self.default_timeout)
-        elif timeout != 0:
-            timeout = int(time() + timeout)
+        timeout = self._normalize_timeout(timeout)
         filename = self._get_filename(key)
         self._prune()
         try:
@@ -793,3 +800,59 @@
                     return False
         except (IOError, OSError, pickle.PickleError):
             return False
+
+
+class UWSGICache(BaseCache):
+    """ Implements the cache using uWSGI's caching framework.
+
+    .. note::
+        This class cannot be used when running under PyPy, because the uWSGI
+        API implementation for PyPy is lacking the needed functionality.
+
+    :param default_timeout: The default timeout in seconds.
+    :param cache: The name of the caching instance to connect to, for
+        example: mycache@localhost:3031, defaults to an empty string, which
+        means uWSGI will cache in the local instance. If the cache is in the
+        same instance as the werkzeug app, you only have to provide the name of
+        the cache.
+    """
+    def __init__(self, default_timeout=300, cache=''):
+        BaseCache.__init__(self, default_timeout)
+
+        if platform.python_implementation() == 'PyPy':
+            raise RuntimeError("uWSGI caching does not work under PyPy, see "
+                               "the docs for more details.")
+
+        try:
+            import uwsgi
+            self._uwsgi = uwsgi
+        except ImportError:
+            raise RuntimeError("uWSGI could not be imported, are you "
+                               "running under uWSGI?")
+
+        self.cache = cache
+
+    def get(self, key):
+        rv = self._uwsgi.cache_get(key, self.cache)
+        if rv is None:
+            return
+        return pickle.loads(rv)
+
+    def delete(self, key):
+        return self._uwsgi.cache_del(key, self.cache)
+
+    def set(self, key, value, timeout=None):
+        return self._uwsgi.cache_update(key, pickle.dumps(value),
+                                        self._normalize_timeout(timeout),
+                                        self.cache)
+
+    def add(self, key, value, timeout=None):
+        return self._uwsgi.cache_set(key, pickle.dumps(value),
+                                     self._normalize_timeout(timeout),
+                                     self.cache)
+
+    def clear(self):
+        return self._uwsgi.cache_clear(self.cache)
+
+    def has(self, key):
+        return self._uwsgi.cache_exists(key, self.cache) is not None