Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
*.egg-info/*
docs/_build/*
dist/*
*.swp
33 changes: 28 additions & 5 deletions cache_tools/tests/test_tools.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
from functools import partial
from django.test import TestCase
from mock import Mock, MagicMock, patch
from django.test.client import RequestFactory
from cache_tools.tools import cache_page_in_group, get_group_key, expire_cache_group, TIME_TO_CACHE

class CachingTest(TestCase):
"""
# This gets overwritten by the function below it. Why's it here?
# Also, if it gets run, it fails
def test_get_group_key(self):
key = get_group_key('test')
assert key == 'test2'
"""

@patch('cache_tools.tools.cache.get')
def test_get_group_key(self, cache_get):
cache_get.return_value = 15

key = get_group_key('test')
assert key == 'test15'

@patch('cache_tools.tools.cache_page')
def test_get_group_key(self, cache_page):
cache_page.return_value = 'success'


@patch('cache_tools.tools.cache.get')
@patch('cache_tools.tools.cache.set')
def test_expire_cache_group(self, cache_set, cache_get):
Expand All @@ -25,13 +36,25 @@ def test_expire_cache_group(self, cache_set, cache_get):
@patch('cache_tools.tools.cache.get')
@patch('cache_tools.tools.cache_page')
def test_cache_group(self, cache_page, cache_get):
dict_group = {'some_id': 4, 'some key': 'hello',
'another key': 'world'}
tuple_group = ('some key', 'some_id', 'another key')
callable_group = lambda **kwargs: dict_group
groups = ('test', dict_group, tuple_group, callable_group)

cache_get.return_value = 15
view = Mock()
decorated_view = cache_page_in_group('test')(view)
request = RequestFactory().get('/test/')
response = decorated_view(request)

cache_page.assert_called_with(TIME_TO_CACHE, key_prefix='test15')
for group in groups:
decorated_view = cache_page_in_group(group)(view)
request = RequestFactory().get('/test/')
response = decorated_view(request, **dict_group)

expected_prefix = '366791489260553153815'
if isinstance(group, basestring):
expected_prefix = 'test15'
cache_page.assert_called_with(TIME_TO_CACHE,
key_prefix=expected_prefix)

@patch('cache_tools.tools.cache_page')
def test_cache_group_initial(self, cache_page):
Expand All @@ -40,4 +63,4 @@ def test_cache_group_initial(self, cache_page):
request = RequestFactory().get('/test/')
response = decorated_view(request)

cache_page.assert_called_with(TIME_TO_CACHE, key_prefix='test1')
cache_page.assert_called_with(TIME_TO_CACHE, key_prefix='test1')
43 changes: 42 additions & 1 deletion cache_tools/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,56 @@ def expire_page(path):
if key and cache.has_key(key):
cache.delete(key)

def compute_group_label(group, *args, **kwargs):
""" Returns a label for the group.
"""

if callable(group):
group = group(*args, **kwargs)

if isinstance(group, basestring):
return group
elif isinstance(group, (tuple, list)):
try:
to_hash = frozenset((key, kwargs[key]) for key in group)
except KeyError:
raise ValueError("If group is a list or tuple, all "
"the items must be valid keys in the view's kwargs.")
elif isinstance(group, dict):
to_hash = frozenset((key, val) for key, val in group.items())

return hash(to_hash)

def cache_page_in_group(group):

def decorator(view_func):
@wraps(view_func, assigned=available_attrs(view_func))
def _wrapped_view(request, *args, **kwargs):
key_prefix = get_group_key(group)
key_prefix = get_group_key(compute_group_label(group, *args, **kwargs))
return cache_page(TIME_TO_CACHE, key_prefix=key_prefix)(view_func)(request, *args, **kwargs)
return _wrapped_view
return decorator

def conditional_cache_page_in_group(condition, group):
""" Caches a page only if the condition (a callable) evaluates to True
"""

def decorator(view_func):
@wraps(view_func, assigned=available_attrs(view_func))
def _wrapped_view(request, *args, **kwargs):
print('in wrapped view')
if condition(group, *args, **kwargs):
key_prefix = get_group_key(compute_group_label(
group, *args, **kwargs))
res = cache_page(TIME_TO_CACHE, key_prefix=key_prefix)(
view_func)(request, *args, **kwargs)
print('cache\n' + unicode(cache.get(key_prefix)))
return res
else:
return view_func(request, *args, **kwargs)
return _wrapped_view
return decorator

def get_group_key(group):
key = cache.get("cache_group_" + str(group), 1)
return str(group) + str(key)
Expand Down
2 changes: 1 addition & 1 deletion runtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

def runtests():
TestRunner = get_runner(settings)
test_runner = TestRunner(verbosity=1, interactive=True, failfast=False)
test_runner = TestRunner(verbosity=3, interactive=True, failfast=False)
failures = test_runner.run_tests(['cache_tools', ])
sys.exit(failures)

Expand Down