aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Kemmer <tkemmer@computer.org>2015-06-06 14:24:51 +0200
committerThomas Kemmer <tkemmer@computer.org>2015-06-06 15:20:24 +0200
commitec80673eb18a43f2f0299235e4b625b30322b664 (patch)
tree9bd31d0acffb86cfab013312fa2df2e6ce8352ac
parent7827ec015a551f11c3ac55e3583b8592c4ae88d4 (diff)
downloadcachetools-ec80673eb18a43f2f0299235e4b625b30322b664.tar.gz
Fix #33: Code cleanup for improved PEP 8 conformance.
-rw-r--r--cachetools/__init__.py11
-rw-r--r--cachetools/cache.py6
-rw-r--r--cachetools/decorators.py97
-rw-r--r--cachetools/func.py120
-rw-r--r--cachetools/lfu.py11
-rw-r--r--cachetools/lock.py6
-rw-r--r--cachetools/lru.py11
-rw-r--r--cachetools/method.py42
-rw-r--r--cachetools/rr.py12
-rw-r--r--cachetools/ttl.py11
-rw-r--r--tests/test_cache.py3
-rw-r--r--tests/test_lfu.py3
-rw-r--r--tests/test_lru.py3
-rw-r--r--tests/test_method.py (renamed from tests/test_cachedmethod.py)2
-rw-r--r--tests/test_rr.py5
-rw-r--r--tests/test_ttl.py3
16 files changed, 181 insertions, 165 deletions
diff --git a/cachetools/__init__.py b/cachetools/__init__.py
index 6093731..14a068c 100644
--- a/cachetools/__init__.py
+++ b/cachetools/__init__.py
@@ -1,11 +1,12 @@
"""Extensible memoizing collections and decorators"""
from .cache import Cache
-from .decorators import cachedmethod
-from .lfu import LFUCache, lfu_cache
-from .lru import LRUCache, lru_cache
-from .rr import RRCache, rr_cache
-from .ttl import TTLCache, ttl_cache
+from .func import lfu_cache, lru_cache, rr_cache, ttl_cache
+from .lfu import LFUCache
+from .lru import LRUCache
+from .method import cachedmethod
+from .rr import RRCache
+from .ttl import TTLCache
__all__ = (
'Cache',
diff --git a/cachetools/cache.py b/cachetools/cache.py
index 0c692f9..edb4986 100644
--- a/cachetools/cache.py
+++ b/cachetools/cache.py
@@ -1,10 +1,6 @@
import collections
-def one(value):
- return 1
-
-
class Cache(collections.MutableMapping):
"""Mutable mapping to serve as a simple cache or cache base class."""
@@ -13,7 +9,7 @@ class Cache(collections.MutableMapping):
self.__currsize = 0
self.__maxsize = maxsize
self.__missing = missing
- self.__getsizeof = getsizeof or one
+ self.__getsizeof = getsizeof or (lambda x: 1)
def __repr__(self):
return '%s(%r, maxsize=%d, currsize=%d)' % (
diff --git a/cachetools/decorators.py b/cachetools/decorators.py
deleted file mode 100644
index 7299251..0000000
--- a/cachetools/decorators.py
+++ /dev/null
@@ -1,97 +0,0 @@
-import collections
-import functools
-
-CacheInfo = collections.namedtuple('CacheInfo', 'hits misses maxsize currsize')
-
-
-class NullContext:
- def __enter__(self):
- pass
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- pass
-
-nullcontext = NullContext()
-
-
-def makekey_untyped(args, kwargs):
- return (args, tuple(sorted(kwargs.items())))
-
-
-def makekey_typed(args, kwargs):
- key = makekey_untyped(args, kwargs)
- key += tuple(type(v) for v in args)
- key += tuple(type(v) for _, v in sorted(kwargs.items()))
- return key
-
-
-def cachedfunc(cache, typed=False, lock=None):
- makekey = makekey_typed if typed else makekey_untyped
- context = lock() if lock else nullcontext
-
- def decorator(func):
- stats = [0, 0]
-
- def wrapper(*args, **kwargs):
- key = makekey(args, kwargs)
- with context:
- try:
- result = cache[key]
- stats[0] += 1
- return result
- except KeyError:
- stats[1] += 1
- result = func(*args, **kwargs)
- with context:
- try:
- cache[key] = result
- except ValueError:
- pass # value too large
- return result
-
- def cache_info():
- with context:
- hits, misses = stats
- maxsize = cache.maxsize
- currsize = cache.currsize
- return CacheInfo(hits, misses, maxsize, currsize)
-
- def cache_clear():
- with context:
- cache.clear()
-
- wrapper.cache_info = cache_info
- wrapper.cache_clear = cache_clear
- return functools.update_wrapper(wrapper, func)
-
- return decorator
-
-
-def cachedmethod(cache, typed=False):
- """Decorator to wrap a class or instance method with a memoizing
- callable that saves results in a (possibly shared) cache.
-
- """
- makekey = makekey_typed if typed else makekey_untyped
-
- def decorator(method):
- def wrapper(self, *args, **kwargs):
- mapping = cache(self)
- if mapping is None:
- return method(self, *args, **kwargs)
- key = makekey((method,) + args, kwargs)
- try:
- return mapping[key]
- except KeyError:
- pass
- result = method(self, *args, **kwargs)
- try:
- mapping[key] = result
- except ValueError:
- pass # value too large
- return result
-
- wrapper.cache = cache
- return functools.update_wrapper(wrapper, method)
-
- return decorator
diff --git a/cachetools/func.py b/cachetools/func.py
new file mode 100644
index 0000000..4d88a78
--- /dev/null
+++ b/cachetools/func.py
@@ -0,0 +1,120 @@
+import collections
+import functools
+import random
+import time
+
+from .lfu import LFUCache
+from .lru import LRUCache
+from .rr import RRCache
+from .ttl import TTLCache
+
+try:
+ from threading import RLock
+except ImportError:
+ from dummy_threading import RLock
+
+
+_CacheInfo = collections.namedtuple('CacheInfo', [
+ 'hits', 'misses', 'maxsize', 'currsize'
+])
+
+
+class _NullContext:
+ def __enter__(self):
+ pass
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ pass
+
+
+_nullcontext = _NullContext()
+
+
+def _makekey_untyped(args, kwargs):
+ return (args, tuple(sorted(kwargs.items())))
+
+
+def _makekey_typed(args, kwargs):
+ key = _makekey_untyped(args, kwargs)
+ key += tuple(type(v) for v in args)
+ key += tuple(type(v) for _, v in sorted(kwargs.items()))
+ return key
+
+
+def _cachedfunc(cache, typed=False, lock=None):
+ makekey = _makekey_typed if typed else _makekey_untyped
+ context = lock() if lock else _nullcontext
+
+ def decorator(func):
+ stats = [0, 0]
+
+ def wrapper(*args, **kwargs):
+ key = makekey(args, kwargs)
+ with context:
+ try:
+ result = cache[key]
+ stats[0] += 1
+ return result
+ except KeyError:
+ stats[1] += 1
+ result = func(*args, **kwargs)
+ with context:
+ try:
+ cache[key] = result
+ except ValueError:
+ pass # value too large
+ return result
+
+ def cache_info():
+ with context:
+ hits, misses = stats
+ maxsize = cache.maxsize
+ currsize = cache.currsize
+ return _CacheInfo(hits, misses, maxsize, currsize)
+
+ def cache_clear():
+ with context:
+ cache.clear()
+
+ wrapper.cache_info = cache_info
+ wrapper.cache_clear = cache_clear
+ return functools.update_wrapper(wrapper, func)
+
+ return decorator
+
+
+def lfu_cache(maxsize=128, typed=False, getsizeof=None, lock=RLock):
+ """Decorator to wrap a function with a memoizing callable that saves
+ up to `maxsize` results based on a Least Frequently Used (LFU)
+ algorithm.
+
+ """
+ return _cachedfunc(LFUCache(maxsize, getsizeof), typed, lock)
+
+
+def lru_cache(maxsize=128, typed=False, getsizeof=None, lock=RLock):
+ """Decorator to wrap a function with a memoizing callable that saves
+ up to `maxsize` results based on a Least Recently Used (LRU)
+ algorithm.
+
+ """
+ return _cachedfunc(LRUCache(maxsize, getsizeof), typed, lock)
+
+
+def rr_cache(maxsize=128, choice=random.choice, typed=False, getsizeof=None,
+ lock=RLock):
+ """Decorator to wrap a function with a memoizing callable that saves
+ up to `maxsize` results based on a Random Replacement (RR)
+ algorithm.
+
+ """
+ return _cachedfunc(RRCache(maxsize, choice, getsizeof), typed, lock)
+
+
+def ttl_cache(maxsize=128, ttl=600, timer=time.time, typed=False,
+ getsizeof=None, lock=RLock):
+ """Decorator to wrap a function with a memoizing callable that saves
+ up to `maxsize` results based on a Least Recently Used (LRU)
+ algorithm with a per-item time-to-live (TTL) value.
+ """
+ return _cachedfunc(TTLCache(maxsize, ttl, timer, getsizeof), typed, lock)
diff --git a/cachetools/lfu.py b/cachetools/lfu.py
index 0afa9c9..d163cba 100644
--- a/cachetools/lfu.py
+++ b/cachetools/lfu.py
@@ -2,8 +2,6 @@ import collections
import operator
from .cache import Cache
-from .decorators import cachedfunc
-from .lock import RLock
class LFUCache(Cache):
@@ -33,12 +31,3 @@ class LFUCache(Cache):
except ValueError:
raise KeyError('cache is empty')
return key, self.pop(key)
-
-
-def lfu_cache(maxsize=128, typed=False, getsizeof=None, lock=RLock):
- """Decorator to wrap a function with a memoizing callable that saves
- up to `maxsize` results based on a Least Frequently Used (LFU)
- algorithm.
-
- """
- return cachedfunc(LFUCache(maxsize, getsizeof), typed, lock)
diff --git a/cachetools/lock.py b/cachetools/lock.py
deleted file mode 100644
index 33c7c89..0000000
--- a/cachetools/lock.py
+++ /dev/null
@@ -1,6 +0,0 @@
-# flake8: noqa
-
-try:
- from threading import RLock
-except ImportError:
- from dummy_threading import RLock
diff --git a/cachetools/lru.py b/cachetools/lru.py
index dbc9786..67ac797 100644
--- a/cachetools/lru.py
+++ b/cachetools/lru.py
@@ -1,6 +1,4 @@
from .cache import Cache
-from .decorators import cachedfunc
-from .lock import RLock
class Link(object):
@@ -85,12 +83,3 @@ class LRUCache(Cache):
Cache.__delitem__(self, key)
link.unlink()
return (key, link.value)
-
-
-def lru_cache(maxsize=128, typed=False, getsizeof=None, lock=RLock):
- """Decorator to wrap a function with a memoizing callable that saves
- up to `maxsize` results based on a Least Recently Used (LRU)
- algorithm.
-
- """
- return cachedfunc(LRUCache(maxsize, getsizeof), typed, lock)
diff --git a/cachetools/method.py b/cachetools/method.py
new file mode 100644
index 0000000..2d04f44
--- /dev/null
+++ b/cachetools/method.py
@@ -0,0 +1,42 @@
+import functools
+
+
+def _makekey_untyped(method, args, kwargs):
+ return (method, args, tuple(sorted(kwargs.items())))
+
+
+def _makekey_typed(method, args, kwargs):
+ key = _makekey_untyped(method, args, kwargs)
+ key += tuple(type(v) for v in args)
+ key += tuple(type(v) for _, v in sorted(kwargs.items()))
+ return key
+
+
+def cachedmethod(cache, typed=False):
+ """Decorator to wrap a class or instance method with a memoizing
+ callable that saves results in a (possibly shared) cache.
+
+ """
+ makekey = _makekey_typed if typed else _makekey_untyped
+
+ def decorator(method):
+ def wrapper(self, *args, **kwargs):
+ mapping = cache(self)
+ if mapping is None:
+ return method(self, *args, **kwargs)
+ key = makekey(method, args, kwargs)
+ try:
+ return mapping[key]
+ except KeyError:
+ pass
+ result = method(self, *args, **kwargs)
+ try:
+ mapping[key] = result
+ except ValueError:
+ pass # value too large
+ return result
+
+ wrapper.cache = cache
+ return functools.update_wrapper(wrapper, method)
+
+ return decorator
diff --git a/cachetools/rr.py b/cachetools/rr.py
index 5119c48..143223b 100644
--- a/cachetools/rr.py
+++ b/cachetools/rr.py
@@ -1,8 +1,6 @@
import random
from .cache import Cache
-from .decorators import cachedfunc
-from .lock import RLock
class RRCache(Cache):
@@ -25,13 +23,3 @@ class RRCache(Cache):
def choice(self):
"""The `choice` function used by the cache."""
return self.__choice
-
-
-def rr_cache(maxsize=128, choice=random.choice, typed=False, getsizeof=None,
- lock=RLock):
- """Decorator to wrap a function with a memoizing callable that saves
- up to `maxsize` results based on a Random Replacement (RR)
- algorithm.
-
- """
- return cachedfunc(RRCache(maxsize, choice, getsizeof), typed, lock)
diff --git a/cachetools/ttl.py b/cachetools/ttl.py
index db35aa3..73c545a 100644
--- a/cachetools/ttl.py
+++ b/cachetools/ttl.py
@@ -2,8 +2,6 @@ import functools
import time
from .cache import Cache
-from .decorators import cachedfunc
-from .lock import RLock
class Link(object):
@@ -225,12 +223,3 @@ class TTLCache(Cache):
get = __nested(Cache.get)
pop = __nested(Cache.pop)
setdefault = __nested(Cache.setdefault)
-
-
-def ttl_cache(maxsize=128, ttl=600, timer=time.time, typed=False,
- getsizeof=None, lock=RLock):
- """Decorator to wrap a function with a memoizing callable that saves
- up to `maxsize` results based on a Least Recently Used (LRU)
- algorithm with a per-item time-to-live (TTL) value.
- """
- return cachedfunc(TTLCache(maxsize, ttl, timer, getsizeof), typed, lock)
diff --git a/tests/test_cache.py b/tests/test_cache.py
index 433a733..3b78515 100644
--- a/tests/test_cache.py
+++ b/tests/test_cache.py
@@ -1,8 +1,9 @@
import unittest
-from . import CacheTestMixin
from cachetools import Cache
+from . import CacheTestMixin
+
class CacheTest(unittest.TestCase, CacheTestMixin):
diff --git a/tests/test_lfu.py b/tests/test_lfu.py
index 3b69647..1c4741b 100644
--- a/tests/test_lfu.py
+++ b/tests/test_lfu.py
@@ -1,8 +1,9 @@
import unittest
-from . import CacheTestMixin, DecoratorTestMixin
from cachetools import LFUCache, lfu_cache
+from . import CacheTestMixin, DecoratorTestMixin
+
class LFUCacheTest(unittest.TestCase, CacheTestMixin, DecoratorTestMixin):
diff --git a/tests/test_lru.py b/tests/test_lru.py
index f21170d..5eea036 100644
--- a/tests/test_lru.py
+++ b/tests/test_lru.py
@@ -1,8 +1,9 @@
import unittest
-from . import CacheTestMixin, DecoratorTestMixin
from cachetools import LRUCache, lru_cache
+from . import CacheTestMixin, DecoratorTestMixin
+
class LRUCacheTest(unittest.TestCase, CacheTestMixin, DecoratorTestMixin):
diff --git a/tests/test_cachedmethod.py b/tests/test_method.py
index 1440352..82337e0 100644
--- a/tests/test_cachedmethod.py
+++ b/tests/test_method.py
@@ -1,5 +1,5 @@
-import unittest
import operator
+import unittest
from cachetools import LRUCache, cachedmethod
diff --git a/tests/test_rr.py b/tests/test_rr.py
index 7af9863..b6d2f2c 100644
--- a/tests/test_rr.py
+++ b/tests/test_rr.py
@@ -1,9 +1,10 @@
-import unittest
import random
+import unittest
-from . import CacheTestMixin, DecoratorTestMixin
from cachetools import RRCache, rr_cache
+from . import CacheTestMixin, DecoratorTestMixin
+
class RRCacheTest(unittest.TestCase, CacheTestMixin, DecoratorTestMixin):
diff --git a/tests/test_ttl.py b/tests/test_ttl.py
index d562c1c..c6253c2 100644
--- a/tests/test_ttl.py
+++ b/tests/test_ttl.py
@@ -1,8 +1,9 @@
import unittest
-from . import CacheTestMixin, DecoratorTestMixin
from cachetools import TTLCache, ttl_cache
+from . import CacheTestMixin, DecoratorTestMixin
+
class Timer:
def __init__(self, auto=False):