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

Update and Refactoring #191

Open
wants to merge 3 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
11 changes: 11 additions & 0 deletions .idea/flask-cache.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions .idea/inspectionProfiles/profiles_settings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 25 additions & 20 deletions flask_cache/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,24 @@
if PY2:
null_control = (None, delchars)
else:
null_control = (dict((k,None) for k in delchars),)
null_control = (dict((k, None) for k in delchars),)


def function_namespace(f, args=None):
"""
Attempts to returns unique namespace for function
"""
m_args = inspect.getargspec(f)[0]
m_args = inspect.getfullargspec(f)[0]
instance_token = None

instance_self = getattr(f, '__self__', None)

if instance_self \
and not inspect.isclass(instance_self):
and not inspect.isclass(instance_self):
instance_token = repr(f.__self__)
elif m_args \
and m_args[0] == 'self' \
and args:
and m_args[0] == 'self' \
and args:
instance_token = repr(args[0])

module = f.__module__
Expand All @@ -63,7 +64,7 @@ def function_namespace(f, args=None):
klass = getattr(f, '__self__', None)

if klass \
and not inspect.isclass(klass):
and not inspect.isclass(klass):
klass = klass.__class__

if not klass:
Expand Down Expand Up @@ -92,6 +93,7 @@ def function_namespace(f, args=None):

return ns, ins


def make_template_fragment_key(fragment_name, vary_on=[]):
"""
Make a cache key for a specific fragment name
Expand Down Expand Up @@ -169,7 +171,7 @@ def _set_cache(self, app, config):
cache_obj = getattr(backends, import_me)
except AttributeError:
raise ImportError("%s is not a valid FlaskCache backend" % (
import_me))
import_me))
else:
cache_obj = import_string(import_me)

Expand All @@ -184,7 +186,7 @@ def _set_cache(self, app, config):

app.extensions.setdefault('cache', {})
app.extensions['cache'][self] = cache_obj(
app, config, cache_args, cache_options)
app, config, cache_args, cache_options)

@property
def cache(self):
Expand Down Expand Up @@ -297,7 +299,7 @@ def decorated_function(*args, **kwargs):
rv = f(*args, **kwargs)
try:
self.cache.set(cache_key, rv,
timeout=decorated_function.cache_timeout)
timeout=decorated_function.cache_timeout)
except Exception:
if current_app.debug:
raise
Expand All @@ -320,6 +322,7 @@ def make_cache_key(*args, **kwargs):
decorated_function.make_cache_key = make_cache_key

return decorated_function

return decorator

def _memvname(self, funcname):
Expand Down Expand Up @@ -375,6 +378,7 @@ def _memoize_make_cache_key(self, make_name=None, timeout=None):
"""
Function used to create the cache_key for memoized functions.
"""

def make_cache_key(f, *args, **kwargs):
_timeout = getattr(timeout, 'cache_timeout', timeout)
fname, version_data = self._memoize_version(f, args=args,
Expand All @@ -389,8 +393,8 @@ def make_cache_key(f, *args, **kwargs):

if callable(f):
keyargs, keykwargs = self._memoize_kwargs_to_args(f,
*args,
**kwargs)
*args,
**kwargs)
else:
keyargs, keykwargs = args, kwargs

Expand All @@ -406,6 +410,7 @@ def make_cache_key(f, *args, **kwargs):
cache_key += version_data

return cache_key

return make_cache_key

def _memoize_kwargs_to_args(self, f, *args, **kwargs):
Expand All @@ -431,8 +436,8 @@ def _memoize_kwargs_to_args(self, f, *args, **kwargs):
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]
elif abs(i - args_len) <= len(argspec.defaults):
arg = argspec.defaults[i - args_len]
arg_num += 1
else:
arg = None
Expand Down Expand Up @@ -527,7 +532,7 @@ def decorated_function(*args, **kwargs):
try:
cache_key = decorated_function.make_cache_key(f, *args, **kwargs)
rv = self.cache.get(cache_key)
except Exception:
except (Exception,):
if current_app.debug:
raise
logger.exception("Exception possibly due to cache backend.")
Expand All @@ -537,8 +542,8 @@ def decorated_function(*args, **kwargs):
rv = f(*args, **kwargs)
try:
self.cache.set(cache_key, rv,
timeout=decorated_function.cache_timeout)
except Exception:
timeout=decorated_function.cache_timeout)
except (Exception,):
if current_app.debug:
raise
logger.exception("Exception possibly due to cache backend.")
Expand All @@ -547,10 +552,11 @@ def decorated_function(*args, **kwargs):
decorated_function.uncached = f
decorated_function.cache_timeout = timeout
decorated_function.make_cache_key = self._memoize_make_cache_key(
make_name, decorated_function)
make_name, decorated_function)
decorated_function.delete_memoized = lambda: self.delete_memoized(f)

return decorated_function

return memoize

def delete_memoized(self, f, *args, **kwargs):
Expand Down Expand Up @@ -656,8 +662,7 @@ def add(self, b):
"""
if not callable(f):
raise DeprecationWarning("Deleting messages by relative name is no longer"
" reliable, please switch to a function reference")

" reliable, please switch to a function reference")

try:
if not args and not kwargs:
Expand All @@ -684,7 +689,7 @@ def delete_memoized_verhash(self, f, *args):
"""
if not callable(f):
raise DeprecationWarning("Deleting messages by relative name is no longer"
" reliable, please use a function reference")
" reliable, please use a function reference")

try:
self._memoize_version(f, delete=True)
Expand Down
32 changes: 18 additions & 14 deletions flask_cache/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,37 @@ def __init__(self, servers=None, default_timeout=300, key_prefix=None,
def null(app, config, args, kwargs):
return NullCache()


def simple(app, config, args, kwargs):
kwargs.update(dict(threshold=config['CACHE_THRESHOLD']))
return SimpleCache(*args, **kwargs)


def memcached(app, config, args, kwargs):
args.append(config['CACHE_MEMCACHED_SERVERS'])
kwargs.update(dict(key_prefix=config['CACHE_KEY_PREFIX']))
return MemcachedCache(*args, **kwargs)


def saslmemcached(app, config, args, kwargs):
args.append(config['CACHE_MEMCACHED_SERVERS'])
kwargs.update(dict(username=config['CACHE_MEMCACHED_USERNAME'],
password=config['CACHE_MEMCACHED_PASSWORD'],
key_prefix=config['CACHE_KEY_PREFIX']))
return SASLMemcachedCache(*args, **kwargs)


def gaememcached(app, config, args, kwargs):
kwargs.update(dict(key_prefix=config['CACHE_KEY_PREFIX']))
return GAEMemcachedCache(*args, **kwargs)


def filesystem(app, config, args, kwargs):
args.insert(0, config['CACHE_DIR'])
kwargs.update(dict(threshold=config['CACHE_THRESHOLD']))
return FileSystemCache(*args, **kwargs)


# RedisCache is supported since Werkzeug 0.7.
try:
from werkzeug.contrib.cache import RedisCache
Expand Down Expand Up @@ -77,9 +83,9 @@ def redis(app, config, args, kwargs):
redis_url = config.get('CACHE_REDIS_URL')
if redis_url:
kwargs['host'] = redis_from_url(
redis_url,
db=kwargs.pop('db', None),
)
redis_url,
db=kwargs.pop('db', None),
)

return RedisCache(*args, **kwargs)

Expand All @@ -93,8 +99,7 @@ class SpreadSASLMemcachedCache(SASLMemcachedCache):
impact the performances.
"""


def __init__(self, *args, **kwargs):
def __init__(self, *args, **kwargs):
"""
chunksize : (int) max size in bytes of chunk stored in memcached
"""
Expand All @@ -106,7 +111,6 @@ def delete(self, key):
for skey in self._genkeys(key):
super(SpreadSASLMemcachedCache, self).delete(skey)


def set(self, key, value, timeout=None, chunk=True):
"""set a value in cache, potentially spreding it across multiple key.

Expand All @@ -130,37 +134,37 @@ def _set(self, key, value, timeout=None):
len_ser = len(serialized)
chks = range_type(0, len_ser, self.chunksize)
if len(chks) > self.maxchunk:
raise ValueError('Cannot store value in less than %s keys'%(self.maxchunk))
raise ValueError('Cannot store value in less than %s keys' % (self.maxchunk))
for i in chks:
values['%s.%s' % (key, i//self.chunksize)] = serialized[i : i+self.chunksize]
values['%s.%s' % (key, i // self.chunksize)] = serialized[i: i + self.chunksize]
super(SpreadSASLMemcachedCache, self).set_many(values, timeout)

def get(self, key, chunk=True):
"""get a value in cache, potentially spreded it across multiple key.

chunk : (Bool) if set to false, get a value set with set(..., chunk=False)
"""
if chunk :
if chunk:
return self._get(key)
else :
else:
return super(SpreadSASLMemcachedCache, self).get(key)

def _genkeys(self, key):
return ['%s.%s' % (key, i) for i in range_type(self.maxchunk)]

def _get(self, key):
to_get = ['%s.%s' % (key, i) for i in range_type(self.maxchunk)]
result = super(SpreadSASLMemcachedCache, self).get_many( *to_get)
result = super(SpreadSASLMemcachedCache, self).get_many(*to_get)
serialized = ''.join([v for v in result if v is not None])
if not serialized:
return None
return pickle.loads(serialized)

def spreadsaslmemcachedcache(app, config, args, kwargs):

def spreadsaslmemcachedcache(app, config, args, kwargs):
args.append(config['CACHE_MEMCACHED_SERVERS'])
kwargs.update(dict(username=config.get('CACHE_MEMCACHED_USERNAME'),
password=config.get('CACHE_MEMCACHED_PASSWORD'),
key_prefix=config.get('CACHE_KEY_PREFIX')
))
key_prefix=config.get('CACHE_KEY_PREFIX')
))
return SpreadSASLMemcachedCache(*args, **kwargs)
4 changes: 2 additions & 2 deletions flask_cache/jinja2ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@

from jinja2 import nodes
from jinja2.ext import Extension
from flask.ext.cache import make_template_fragment_key
from flask_cache import make_template_fragment_key

JINJA_CACHE_ATTR_NAME = '_template_fragment_cache'


class CacheExtension(Extension):
tags = set(['cache'])
tags = {'cache'}

def parse(self, parser):
lineno = next(parser.stream).lineno
Expand Down
2 changes: 1 addition & 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