Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added fix for functions with only *args & **kwargs #141

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
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
4 changes: 3 additions & 1 deletion README
Original file line number Diff line number Diff line change
@@ -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
58 changes: 14 additions & 44 deletions flask_cache/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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), {}

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
21 changes: 20 additions & 1 deletion test_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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():
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down