diff --git a/.gitignore b/.gitignore index 3a8691b..a2c6452 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ *.egg-info/* docs/_build/* dist/* +*.swp diff --git a/cache_tools/tests/test_tools.py b/cache_tools/tests/test_tools.py index 7978841..da42bae 100644 --- a/cache_tools/tests/test_tools.py +++ b/cache_tools/tests/test_tools.py @@ -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): @@ -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): @@ -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') \ No newline at end of file + cache_page.assert_called_with(TIME_TO_CACHE, key_prefix='test1') diff --git a/cache_tools/tools.py b/cache_tools/tools.py index 71bb3ce..9180777 100644 --- a/cache_tools/tools.py +++ b/cache_tools/tools.py @@ -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) diff --git a/runtests.py b/runtests.py index 14ab092..cef2ca4 100644 --- a/runtests.py +++ b/runtests.py @@ -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)