Skip to content

Commit

Permalink
Fix #176: Add cache decorator parameters as attributes.
Browse files Browse the repository at this point in the history
  • Loading branch information
tkem committed Apr 5, 2022
1 parent ab9e8af commit 7c8e231
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 12 deletions.
8 changes: 8 additions & 0 deletions src/cachetools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,10 @@ def wrapper(*args, **kwargs):
except ValueError:
return v # value too large

wrapper.cache = cache
wrapper.cache_key = key
wrapper.cache_lock = lock

return functools.update_wrapper(wrapper, func)

return decorator
Expand Down Expand Up @@ -713,6 +717,10 @@ def wrapper(self, *args, **kwargs):
except ValueError:
return v # value too large

wrapper.cache = cache
wrapper.cache_key = key
wrapper.cache_lock = lock

return functools.update_wrapper(wrapper, method)

return decorator
42 changes: 32 additions & 10 deletions tests/test_wrapper.py → tests/test_cached.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import contextlib
import unittest

import cachetools
Expand All @@ -20,8 +21,6 @@ def test_decorator(self):
wrapper = cachetools.cached(cache)(self.func)

self.assertEqual(len(cache), 0)
self.assertEqual(wrapper.__wrapped__, self.func)

self.assertEqual(wrapper(0), 0)
self.assertEqual(len(cache), 1)
self.assertIn(cachetools.keys.hashkey(0), cache)
Expand Down Expand Up @@ -49,8 +48,6 @@ def test_decorator_typed(self):
wrapper = cachetools.cached(cache, key=key)(self.func)

self.assertEqual(len(cache), 0)
self.assertEqual(wrapper.__wrapped__, self.func)

self.assertEqual(wrapper(0), 0)
self.assertEqual(len(cache), 1)
self.assertIn(cachetools.keys.typedkey(0), cache)
Expand Down Expand Up @@ -90,14 +87,44 @@ def __exit__(self, *exc):
wrapper = cachetools.cached(cache, lock=Lock())(self.func)

self.assertEqual(len(cache), 0)
self.assertEqual(wrapper.__wrapped__, self.func)
self.assertEqual(wrapper(0), 0)
self.assertEqual(Lock.count, 2)
self.assertEqual(wrapper(1), 1)
self.assertEqual(Lock.count, 4)
self.assertEqual(wrapper(1), 1)
self.assertEqual(Lock.count, 5)

def test_decorator_wrapped(self):
cache = self.cache(2)
wrapper = cachetools.cached(cache)(self.func)

self.assertEqual(wrapper.__wrapped__, self.func)

self.assertEqual(len(cache), 0)
self.assertEqual(wrapper.__wrapped__(0), 0)
self.assertEqual(len(cache), 0)
self.assertEqual(wrapper(0), 1)
self.assertEqual(len(cache), 1)
self.assertEqual(wrapper(0), 1)
self.assertEqual(len(cache), 1)

def test_decorator_attributes(self):
cache = self.cache(2)
wrapper = cachetools.cached(cache)(self.func)

self.assertIs(wrapper.cache, cache)
self.assertIs(wrapper.cache_key, cachetools.keys.hashkey)
self.assertIs(wrapper.cache_lock, None)

def test_decorator_attributes_lock(self):
cache = self.cache(2)
lock = contextlib.nullcontext()
wrapper = cachetools.cached(cache, lock=lock)(self.func)

self.assertIs(wrapper.cache, cache)
self.assertIs(wrapper.cache_key, cachetools.keys.hashkey)
self.assertIs(wrapper.cache_lock, lock)


class CacheWrapperTest(unittest.TestCase, DecoratorTestMixin):
def cache(self, minsize):
Expand All @@ -108,8 +135,6 @@ def test_zero_size_cache_decorator(self):
wrapper = cachetools.cached(cache)(self.func)

self.assertEqual(len(cache), 0)
self.assertEqual(wrapper.__wrapped__, self.func)

self.assertEqual(wrapper(0), 0)
self.assertEqual(len(cache), 0)

Expand All @@ -128,8 +153,6 @@ def __exit__(self, *exc):
wrapper = cachetools.cached(cache, lock=Lock())(self.func)

self.assertEqual(len(cache), 0)
self.assertEqual(wrapper.__wrapped__, self.func)

self.assertEqual(wrapper(0), 0)
self.assertEqual(len(cache), 0)
self.assertEqual(Lock.count, 2)
Expand All @@ -146,7 +169,6 @@ def func(self, *args, **kwargs):

def test_decorator(self):
wrapper = cachetools.cached(None)(self.func)
self.assertEqual(wrapper.__wrapped__, self.func)

self.assertEqual(wrapper(0), (0,))
self.assertEqual(wrapper(1), (1,))
Expand Down
32 changes: 30 additions & 2 deletions tests/test_method.py → tests/test_cachedmethod.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import operator
import unittest

from cachetools import LRUCache, cachedmethod, keys
from cachetools import LRUCache, _methodkey, cachedmethod, keys


class Cached:
Expand Down Expand Up @@ -125,7 +125,7 @@ def test_weakref(self):
import fractions
import gc

# in Python 3.4, `int` does not support weak references even
# in Python 3.7, `int` does not support weak references even
# when subclassed, but Fraction apparently does...
class Int(fractions.Fraction):
def __add__(self, other):
Expand Down Expand Up @@ -185,3 +185,31 @@ def test_unhashable(self):

with self.assertRaises(TypeError):
cached.get_hashkey(0)

def test_wrapped(self):
cache = {}
cached = Cached(cache)

self.assertEqual(len(cache), 0)
self.assertEqual(cached.get.__wrapped__(cached, 0), 0)
self.assertEqual(len(cache), 0)
self.assertEqual(cached.get(0), 1)
self.assertEqual(len(cache), 1)
self.assertEqual(cached.get(0), 1)
self.assertEqual(len(cache), 1)

def test_attributes(self):
cache = {}
cached = Cached(cache)

self.assertIs(cached.get.cache(cached), cache)
self.assertIs(cached.get.cache_key, _methodkey)
self.assertIs(cached.get.cache_lock, None)

def test_attributes_lock(self):
cache = {}
cached = Locked(cache)

self.assertIs(cached.get.cache(cached), cache)
self.assertIs(cached.get.cache_key, _methodkey)
self.assertIs(cached.get.cache_lock(cached), cached)

0 comments on commit 7c8e231

Please sign in to comment.