diff --git a/README b/README index cc45c70..789847b 100644 --- a/README +++ b/README @@ -1,3 +1,5 @@ Flask-Cache -Adds easy cache support to Flask. +Adds easy cache support to Flask. Fork to support nesting decorators. + +Python3.x only diff --git a/flask_cache/__init__.py b/flask_cache/__init__.py index 85d90e3..2927abb 100644 --- a/flask_cache/__init__.py +++ b/flask_cache/__init__.py @@ -42,7 +42,7 @@ def function_namespace(f, args=None): """ Attempts to returns unique namespace for function """ - m_args = inspect.getargspec(f)[0] + m_args = list(inspect.signature(f).parameters.keys()) instance_token = None instance_self = getattr(f, '__self__', None) @@ -414,50 +414,20 @@ def _memoize_kwargs_to_args(self, f, *args, **kwargs): #: whether the function was called with #: 1, b=2 is equivilant to a=1, b=2, etc. new_args = [] - arg_num = 0 - argspec = inspect.getargspec(f) - - args_len = len(argspec.args) - for i in range(args_len): - if i == 0 and argspec.args[i] in ('self', 'cls'): - #: use the repr of the class instance - #: this supports instance methods for - #: the memoized functions, giving more - #: flexibility to developers - arg = repr(args[0]) - arg_num += 1 - elif argspec.args[i] in kwargs: - arg = kwargs[argspec.args[i]] - elif arg_num < len(args): - arg = args[arg_num] - arg_num += 1 - elif abs(i-args_len) <= len(argspec.defaults): - arg = argspec.defaults[i-args_len] - arg_num += 1 + + signature = inspect.signature(f) + processed_args = 0 + for i, key in enumerate(signature.parameters): + if key in ['self', 'cls'] and i == 0: + new_args.append(repr(args[i])) + processed_args += 1 + elif key in kwargs: + new_args.append(kwargs[key]) + elif processed_args < len(args): + new_args.append(args[processed_args]) + processed_args += 1 else: - arg = None - arg_num += 1 - - #: Attempt to convert all arguments to a - #: hash/id or a representation? - #: Not sure if this is necessary, since - #: using objects as keys gets tricky quickly. - # if hasattr(arg, '__class__'): - # try: - # arg = hash(arg) - # except: - # arg = repr(arg) - - #: Or what about a special __cacherepr__ function - #: on an object, this allows objects to act normal - #: upon inspection, yet they can define a representation - #: that can be used to make the object unique in the - #: cache key. Given that a case comes across that - #: an object "must" be used as a cache key - # if hasattr(arg, '__cacherepr__'): - # arg = arg.__cacherepr__ - - new_args.append(arg) + new_args.append(signature.parameters[key].default) return tuple(new_args), {} diff --git a/setup.py b/setup.py index 7f75223..17928fb 100755 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ setup( name='Flask-Cache', - version='0.13', + version='0.14', url='http://github.com/thadeusb/flask-cache', license='BSD', author='Thadeus Burgess', diff --git a/test_cache.py b/test_cache.py index 9811572..4ec83ff 100644 --- a/test_cache.py +++ b/test_cache.py @@ -7,7 +7,7 @@ import string from flask import Flask, render_template, render_template_string -from flask.ext.cache import Cache, function_namespace, make_template_fragment_key +from flask_cache import Cache, function_namespace, make_template_fragment_key if sys.version_info < (2,7): import unittest2 as unittest @@ -164,6 +164,25 @@ def big_foo(a, b): assert big_foo(5, 2) == result + def test_06b_memoize_func_only_special_args(self): + self.app.config['CACHE_DEFAULT_TIMEOUT'] = 1 + self.cache = Cache(self.app) + + with self.app.test_request_context(): + @self.cache.memoize(10) + def big_foo(*args, **kwargs): + return sum(args) + + res_1 = big_foo(1, 2, 3) + + time.sleep(1) + + res_2 = big_foo(4, 5, 6) + + assert res_1 != res_2 + assert res_1 == 6 + assert res_2 == 15 + def test_07_delete_memoize(self): with self.app.test_request_context(): diff --git a/tox.ini b/tox.ini index f659f43..2569f7e 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ # and then run "tox" from this directory. [tox] -envlist = py26, py27, py33 +envlist = py33,py34,py35 [testenv] deps = -r{toxinidir}/requirements.txt