Code Monkey home page Code Monkey logo

flask-cache's People

Contributors

alanhamlett avatar bcambel avatar carreau avatar charlax avatar dag avatar dahlia avatar dmitryon avatar gobelinus avatar graycarl avatar iromli avatar iurisilvio avatar jab avatar joeyespo avatar klinkin avatar lnielsen avatar martinfilliau avatar methane avatar mimamu avatar neoecos avatar quonb avatar sean- avatar singingwolfboy avatar streeter avatar svetlyak40wt avatar tehasdf avatar thadeusb avatar thomaswaldmann avatar xsleonard avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flask-cache's Issues

Spread value among multiple keys ?

Hi,

I came across the issue that by default, Memcached does not support value > 1M. Which should be configurable, but in PAAS like heroku, you can't always do that.

It's pretty easy to circumvent, so I was wondering is such an option would make sens in flask cache (or does it belong more in werkzeug contrib maybe ?)

I guess it comes with a performance cost of course...

I did it for my app, if you think this is a good idea, I can try to issue a PR if you wish .

Anyway, sorry if I missed anything obvious.

Can't have more then 1 instance of Cache() in latest versions

because _set_cache sets app.extensions['cache'] and uses that for accessing the cache too it's not possible to have multiple instances of Cache() (eg. one local in-memory cache, one redis cache, one memcache cache).

in v0.8.0 this was still possible ...

Trying to setup redis + postgresql cache w/ flask-cache

I am having trouble configuring flask cache to work with redis. If I set CACHE_TYPE='redis' I get "ImportError: redis is not a valid FlaskCache backend"

If I set CACHE_TYPE = 'RedisCache' I get the following

cache = Cache(app, config={
'CACHE_TYPE': 'RedisCache',
'CACHE_KEY_PREFIX': 'fcache',
'CACHE_REDIS_HOST': 'localhost',
'CACHE_REDIS_PORT': '6379',
'CACHE_REDIS_URL': 'redis://localhost:6379'
})

@cache.memoize()
def query(q):
return q.all()

ERROR:flask_cache:Exception possibly due to cache backend.
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/flask_cache/init.py", line 528, in decorated_function
cache_key = decorated_function.make_cache_key(f, _args, *_kwargs)
File "/usr/local/lib/python2.7/dist-packages/flask_cache/init.py", line 381, in make_cache_key
timeout=_timeout)
File "/usr/local/lib/python2.7/dist-packages/flask_cache/init.py", line 350, in _memoize_version
version_data_list = list(self.cache.get_many(*fetch_keys))
File "/usr/local/lib/python2.7/dist-packages/werkzeug/contrib/cache.py", line 521, in get_many
return [self.load_object(x) for x in self._client.mget(keys)]
AttributeError: 'Flask' object has no attribute 'mget'

Not sure what to do -- having trouble finding documentation.

object instances as arguments to memoize() decorated function

When passing an object instance as an argument to a function decorated with memoize, the cache key is calculated from calling id() on that function. Python's id() only returns a unique id for the lifetime of that object. The lifetime of an object is 1 request when in the Flask request context.

exclude certain args from memoize

Is there a possibility to or interest in adding the option to exclude certain arguments from a memoized function? I have a bunch of functions that query a database that accept as the first argument the database session. I'm not interested in using the session as a cache key but I do want to use all further arguments as the key. Something like:

@cache.memoize(key_prefix="size", exclude=("session",))
def get_city_size(session, city_id):
    stmt = SQL_QUERY.format(city_id)
    conn = session.connection()
    df = pandas.read_sql(, conn.connection)
    # ...
    return df

Incompatible with property decorator?

Hi,

Just curious if Flask-Cache should be compatible with the @Property decorator or not. My usage shows that it is not, but this is also the first thing I've tried, so perhaps I'm doing it wrong!

My code:

import random

class User(object):

    @cache.memoize(50)
    def foo_method(self):
        return random.random()

    @property
    @cache.memoize(50)
    def foo_prop(self):
        return random.random()

Usage shows that the instance method can be cached and cleared, but the property can only be cached:

>>> user.foo_method()
0.0014228338392391349

>>> user.foo_method()
0.0014228338392391349

>>> user.foo_prop
0.55235451242909

>>> user.foo_prop
0.55235451242909

>>> cache.delete_memoized(user.foo_method)
>>> user.foo_method()
0.07564953227490745

>>> cache.delete_memoized(user.foo_prop)
---------------------------------------------------------------------------
DeprecationWarning                        Traceback (most recent call last)
    ----> 1 cache.delete_memoized(user.foo_prop)

/home/scott/code/mypkg/venv/lib/python2.7/site-packages/flask_cache/__init__.pyc in delete_memoized(self, f, *args, **kwargs)
    656         """
    657         if not callable(f):
--> 658             raise DeprecationWarning("Deleting messages by relative name is no longer"
    659                           " reliable, please switch to a function reference")
    660

DeprecationWarning: Deleting messages by relative name is no longer reliable, please switch to a function reference

>>> user.foo_prop
0.55235451242909

FileSystemCache throws exception

When using the file system cache, an exception occurs because werkzeug.contrib.cache.FileSystemCache init method expects the cache dir as its first argument and receives the Flask app object. The remaing args also do not match.

Don't know if this is an issue because of the werkzeug and Flask-Cache versions I use:

Flask-Cache==0.12
Werkzeug==0.9.4

Stack Trace

Traceback (most recent call last):
  File "app.py", line 10, in <module>
    cache = Cache(app)
  File "/home/r/.virtualenvs/flask/local/lib/python2.7/site-packages/flask_cache/__init__.py", line 77, in __init__
    self.init_app(app, config)
  File "/home/r/.virtualenvs/flask/local/lib/python2.7/site-packages/flask_cache/__init__.py", line 109, in init_app
    self._set_cache(app, config)
  File "/home/r/.virtualenvs/flask/local/lib/python2.7/site-packages/flask_cache/__init__.py", line 138, in _set_cache
    app, config, cache_args, cache_options)
  File "/home/r/.virtualenvs/flask/local/lib/python2.7/site-packages/werkzeug/contrib/cache.py", line 593, in __init__
    if not os.path.exists(self._path):
  File "/home/r/.virtualenvs/flask/lib/python2.7/genericpath.py", line 18, in exists
    os.stat(path)
TypeError: coercing to Unicode: need string or buffer, Flask found

UnboundLocalError: local variable 'arg' referenced before assignment

Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1701, in call
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1689, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1687, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1360, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1358, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1344, in dispatch_request
return self.view_functionsrule.endpoint
File "/home/andrew/workspace/aiw/src/lib/util/decorators.py", line 16, in wrapper
response = func(_args, *_kwargs)
File "/home/andrew/workspace/aiw/src/aiw/controllers/util.py", line 26, in summary
for category in get_categories():
File "/usr/local/lib/python2.7/dist-packages/flask_cache/init.py", line 381, in decorated_function
cache_key = decorated_function.make_cache_key(f, _args, *_kwargs)
File "/usr/local/lib/python2.7/dist-packages/flask_cache/init.py", line 259, in make_cache_key
args, kwargs = self.memoize_kwargs_to_args(f, _args, *_kwargs)
File "/usr/local/lib/python2.7/dist-packages/flask_cache/init.py", line 314, in memoize_kwargs_to_args
new_args.append(arg)
UnboundLocalError: local variable 'arg' referenced before assignment

My code:

@cache.memoize(timeout=DAY)
def get_categories(kind=None):
    kind = kind if kind else get_default_kind()

    return Category.query.filter(
        Category.kind==kind,
    ).all()

SASLMemcachedCache + pylibmc + libmemcached Errors

Hi all,

I'm trying to get Flask-Cache working on Heroku with one of their addon providers, memcachier. Since memcachier only supports SASL authentication, I figured I'd use the following configuration:

CACHE_TYPE = 'saslmemcached'
CACHE_MEMCACHED_SERVERS = '...'
CACHE_MEMCACHED_USERNAME = '...'
CACHE_MEMCACHED_PASSWORD = '...'

I've also got pylibmc installed locally (pylibmc==1.2.3).

What happens, however, when I attempt to run app, is that I get:

  File "/home/rdegges/.virtualenvs/tnapi-storage/local/lib/python2.7/site-packages/Flask_Cache-0.11.1-py2.7.egg/flask_cache/__init__.py", line 66, in __init__
    self.init_app(app, config)
  File "/home/rdegges/.virtualenvs/tnapi-storage/local/lib/python2.7/site-packages/Flask_Cache-0.11.1-py2.7.egg/flask_cache/__init__.py", line 97, in init_app
    self._set_cache(app, config)
  File "/home/rdegges/.virtualenvs/tnapi-storage/local/lib/python2.7/site-packages/Flask_Cache-0.11.1-py2.7.egg/flask_cache/__init__.py", line 123, in _set_cache
    app, config, cache_args, cache_options)
  File "/home/rdegges/.virtualenvs/tnapi-storage/local/lib/python2.7/site-packages/Flask_Cache-0.11.1-py2.7.egg/flask_cache/backends.py", line 40, in saslmemcached
    return SASLMemcachedCache(*args, **kwargs)
  File "/home/rdegges/.virtualenvs/tnapi-storage/local/lib/python2.7/site-packages/Flask_Cache-0.11.1-py2.7.egg/flask_cache/backends.py", line 18, in __init__
    binary=True)
  File "/home/rdegges/.virtualenvs/tnapi-storage/local/lib/python2.7/site-packages/pylibmc/client.py", line 97, in __init__
    password=password)
TypeError: libmemcached does not support SASL

It looks like libmemcached (which pylibmc depends on) is not working properly :o Does anyone else have this issue? I'm using Ubuntu 12.10 as well.

Pip version of Flask-Cache not compatible with python3

I'm not sure if this project is still maintained but when i tried using pip'ed version under python 3.4 it returned error

No module named exceptions

probably related to fact that python 3 doesn't have it, Github version is working OK though.

Memoization of classmethod

How do you memoize @classmethod? I would expect following test to work, but apparently delete_memoize don't clear the cache

def test_delete_memoize_classmethod(self):
        with self.app.test_request_context():
            class Mock(object):
                @classmethod
                @self.cache.memoize(5)
                def big_foo(cls, a, b):
                    return a+b+random.randrange(0, 100000)

            result = Mock.big_foo(5, 2)
            result2 = Mock.big_foo(5, 3)

            time.sleep(1)

            assert Mock.big_foo(5, 2) == result
            assert Mock.big_foo(5, 2) == result
            assert Mock.big_foo(5, 3) != result
            assert Mock.big_foo(5, 3) == result2

            self.cache.delete_memoized(Mock.big_foo)

            assert Mock.big_foo(5, 2) != result
            assert Mock.big_foo(5, 3) != result2

memoize cache key NOT unique

I have a method:

@property
@cache.memoize(10)
def simple_stat(self):
    return dict({'viewed': self.viewed_all,
                         'presented': self.presented,
                         'submitted': self.submitted,
                         'completed': self.completed,
                         'edited': self.edited})

The expectation is that cache.memoize would make a key based on id(self) that is unique, even if the function has no arguments other than self.

Instead it is not -- at this point I get 1 cached simple_stat for all objects that have simple_stat method. If I pull them up in a dictionary or list, they all have the same simple_stat result where they should not. I am having difficulty working out a way to assign a unique key, and I'll be upfront about not 100% understanding the code I looked over here for making cache_keys. Making a callable function that creates a random key seems to serve no purpose(it would create a random key every time?) and I cannot pass in something like 'self.identifier' with the argument list. If it a bug, reported. If there is something I do not understand, let me know.

Multiple caches

This is a wishlist item. In my large application (currently built with other technologies, but I'm considering flask), I cache data to memory (simple), memcached and as a file. it would be great if I could create 3 instances of cache, where each one could handle different scenarios. But it seems like the current version can only handle one instance because it only reads config from the app. This feels like a big limitation in an otherwise nice piece of software.

Thanks

import jinja2ext from flask.ext or flask_jinja2ext instead of flaskext

I am not sure if i am right, since i am pretty new to flask, anyway, here goes...

    File "[...]/flask_cache/__init__.py", line 23, in [module]
    from flaskext.cache.jinja2ext import CacheExtension
    ImportError: No module named flaskext.cache.jinja2ext

looking into the sourcecode of flask itself, i found a notice saying that the flask.ext module provides a abstraction layer for loading flask extensions. It tries first flask_cache and at last flaskext.cache.

Include query string parameters in cache key

A really common use case for caching is that the result of an API call will change depending on query string parameters given.

Right now query parameters are being ignored: https://github.com/thadeusb/flask-cache/blob/master/flask_cache/__init__.py#L308

I hack around this by adding stuff to key_prefix, but it seems like this might be desirable as a default - I can't think of a situation where you'd add a query parameter to a URL and expect a different result.

A counterargument is that some things randomly add query parameters to URLs, like google analytics (utm_source etc), which will cause double caching. So we could solve that by either creating a blacklist (where we may miss things, but is simpler from a developer point of view) or by creating a whitelist (where it's probably more correct, as long as the developer remembers to add the GET params they use).

Is there any interest in this? I can take a shot at implementing it.

Set Timeout at Runtime

It will be nice to allow to set a different timeout, after the function is called.

cache_timeout
    The cache timeout value for this function. 
    For a custom value to take affect, this must be set before the function is called.

make_cache_key doesn't consider Accept header

If your flask app returns different content based on requested format using Accept header, then wrong content format may get cached. For example xml for json, or json for xml.

Here's a fix I make in flask_cache/__init__py which may not be the right fix, but communicates the issue.

        def make_cache_key(*args, **kwargs):
            if callable(key_prefix):
                return key_prefix()
            enc = request.headers['Accept'] + '~'
            if '%s' in key_prefix:
                return enc + (key_prefix % request.path)
            return enc + key_prefix

I realize I can write my own function
@cache.cached(key_prefix=my_own_method)
but in practice this is something you want to do site wide.

Invalid key in memoize

Using memoize (at least with GAEMemcached) gives following error:

File "/home/user/project/x/src/packages/werkzeug/contrib/cache.py", line 313, in get
if _test_memcached_key(key):
TypeError: expected string or buffer

The root cause seems to be the tuple key type, while it expects to get a string.
I patched it locally as follows and it seems work ok:

        def memoize(f):
            @wraps(f)
            def decorated_function(*args, **kwargs):
                cache_key = ('memoize', f.__name__, id(f), args, str(kwargs))

                # PATCH: Create a string presentation of the key
                cache_key = '%s%s%s%s' % (cache_key[0], cache_key[1], cache_key[3], cache_key[4])

Used versions:

  • Werkzeug: 0.6.2
  • Flask-Cache: 0.3.2

Get remaining/elapsed time for memoize

Is it possible to get the remaining time for memoize? Is it also possible to get the elapsed time as well?

I don't see this in the docs, can we add this in?

Get/delete cache entries containing/starting with a substring of the cache key

I'm trying to delete all entries in the cache store that contain (in this case start with) a substring of the cache key, but I don't see any easy way of doing this. If I understand the code correctly, I need to pass the full cache key when calling delete or delete_many. Is this correct?

I'll explain what I'm trying to do in case there is a better way: I need to clear the cache for certain users when they modify their settings. Clearing the cache with clear() will remove the cache entries for all the users, which are some 110K, so I don't want to use that. I am generating key_prefix with the ID of the user, the request's path, and other variables. The cache keys always start with the ID of the authenticated user.

Memoize does not respect the parameter timeout

Hi,

I'm having problems with the timeout parameter for the memoize decorator. It looks like it is never respected, putting in the cache always the default timeout: 300 (unless you modify it in the config file). Interestingly, with cached it works as expected.

I'm using it like this:

@cache.memoize(timeout=999)
def foo(arg1, arg2):
pass

I'm using REDIS as the backend, any ideas?

PicklingError: Can't pickle <class 'flaskext.testing.TestResponse'>

Hi, I have a very simple endpoint like this:

@app.route('zip-codes/<string:zip_code>', methods=["GET"])
@cache.cached(timeout=50)
def zip_codes(zip_code):
    coords = get_coords_for_zip_code(zip_code)
    return success_response(coords)

It hits a DB for a JSON representation of lat/longs for a given zip codes.

I have a test that fails with the error message:

PicklingError: Can't pickle <class 'flaskext.testing.TestResponse'>

when using the 'simple' cache backend.

My failing test looks like this:

@patch('views.get_coords_for_zip_code')
    def test_get_zip_code_polygon(self, get_coords_for_zip_code_mock):
        get_coords_for_zip_code_mock.return_value = {
            "zip_code": '90210',
            "polygons": '[[33,44], [44,33]]'
        }

        response = self.client.get('/zip-codes/90210')
        self.assertEqual(response.status_code, 200)

        self.assertTrue('90210' in response.data)
        self.assertTrue('zip_code' in response.data)
        self.assertTrue('polygons' in response.data)

Full stack trace:

Traceback (most recent call last):
  File "/opt/dealer-portal/tests/blueprints/account/views.py", line 816, in test_get_zip_code_polygon_bad_request
    response = self.client.get('/zip-codes/-1')
  File "/home/kris/.virtualenvs/dp/local/lib/python2.7/site-packages/Werkzeug-0.8.2-py2.7.egg/werkzeug/test.py", line 735, in get
    return self.open(*args, **kw)
  File "/home/kris/.virtualenvs/dp/local/lib/python2.7/site-packages/Flask-0.8-py2.7.egg/flask/testing.py", line 102, in open
    follow_redirects=follow_redirects)
  File "/home/kris/.virtualenvs/dp/local/lib/python2.7/site-packages/Werkzeug-0.8.2-py2.7.egg/werkzeug/test.py", line 675, in open
    rv = run_wsgi_app(self.application, environ, buffered=buffered)
  File "/home/kris/.virtualenvs/dp/local/lib/python2.7/site-packages/Werkzeug-0.8.2-py2.7.egg/werkzeug/test.py", line 818, in run_wsgi_app
    app_iter = app(environ, start_response)
  File "/home/kris/.virtualenvs/dp/local/lib/python2.7/site-packages/Flask-0.8-py2.7.egg/flask/app.py", line 1518, in __call__
    return self.wsgi_app(environ, start_response)
  File "/home/kris/.virtualenvs/dp/local/lib/python2.7/site-packages/Flask-0.8-py2.7.egg/flask/app.py", line 1506, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/home/kris/.virtualenvs/dp/local/lib/python2.7/site-packages/Flask-0.8-py2.7.egg/flask/app.py", line 1504, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/kris/.virtualenvs/dp/local/lib/python2.7/site-packages/Flask-0.8-py2.7.egg/flask/app.py", line 1264, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/kris/.virtualenvs/dp/local/lib/python2.7/site-packages/Flask-0.8-py2.7.egg/flask/app.py", line 1262, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/kris/.virtualenvs/dp/local/lib/python2.7/site-packages/Flask-0.8-py2.7.egg/flask/app.py", line 1248, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/kris/.virtualenvs/dp/local/lib/python2.7/site-packages/Flask_Cache-0.10.1-py2.7.egg/flask_cache/__init__.py", line 218, in decorated_function
    timeout=decorated_function.cache_timeout)
  File "/home/kris/.virtualenvs/dp/local/lib/python2.7/site-packages/Werkzeug-0.8.2-py2.7.egg/werkzeug/contrib/cache.py", line 258, in set
    pickle.HIGHEST_PROTOCOL))
PicklingError: Can't pickle <class 'flaskext.testing.TestResponse'>: attribute lookup flaskext.testing.TestResponse failed

Is this a known limitation or a bug?

Thanks!

Pass decorated functions arguments into unless()

There are times that we only want to memoize in certain circumstances, which I'm assuming is the reason why unless() exists.

It would be nice for unless() to decide whether to memoize depending on the arguments passed into the decorated function. This is especially nice if the decorated function is an object method (since the first *arg is self).

For example, let's say we want to only memoize if self.baz is a certain value.:

class Foo(object):
    def __init__(self, baz):
         self.baz = baz

    @cached.memoize(unless=?)
    def bar(self):
        return "something"

Do you think there would be any interest in passing the decorated function's args/kwargs into unless()?

CacheType remains 'null'

Hello

In my app config I checked Testing = False and CACHE_TYPE = 'simple' (also tested with 'filesystem')

but it doesn't same to cache the cached functions

and when I do repr(cache.cache) I got <werkzeurg.contrib.cache.NullCache object at 0xb6a2cb8c>

and in case of CACHE_TYPE = 'filesystem' the directory is not filled with any file along the functions (and results) are cache.

delete_memoized does not delete all keys associated to the function

Hi,

I'm using memoize to store in cache the result of a static method in memcache. And when using delete_memoized, the cache is not delete as intended.

My object + function looks like this:

class User(UserMixin):
    @staticmethod
    @cache.memoize(30)
    def get(id):
        return 'Some info about the user'

I use it to do something like this:

User.get(user_id)

where user_id is an int.

When I update user's info, I want to delete the memoized info:

def some_action():
    cache.delete_memoized(User.get, current_user.id)

But the cache is never deleted (I'm checking with a memcached-tool dump). I checked it was the same id, same function_namespace.

I think the cache regarding this object should be deleted.

Outdated docs about TESTING flag

Quote from docs:

In addition the standard Flask TESTING configuration option is used. If this is True then Flask-Cache will use NullCache only.

Quote from CHANGES file:

Version 0.6.0 2012-08-12

  • Removed the explicit set of NullCache if the Flask app is set testing=True

The docs are wrong, Flask-Cache does not set NullCache.

Upload py3k compatible version on PyPi

I'd love if you would upload the Python 3 compatible version to PyPi. The version that is there won't install on my system, but the github version will.
If you don't think the package is ready yet, you could always upload it with "Development Status :: 3 - Alpha"

Add a method to force a cache refresh

For example, if you have very expensive methods I want to refresh the cache for them with a cronjob or maybe somewhere else in my code. I want to pre populate the cache to avoid a "thundering herd" or "cache miss storm".

It would be nice to have a convenient method to pre populating the cache.

Conditional caching?

Just wondering, is there a way to conditionally cache a url?

value = None

while True:
   value = get_new_value()
   time.sleep(30)

@cache.cached(timeout=30)
def feed():
    return value or "I'm not ready yet!!"

In this case I don't want to cache unless value is set.

Incorrect return value if create function caches dynamically.

Maybe it isn't intended use case, but if I try to create caches dynamically I get same return value if I pass same argument list. Here is the example code:

In [1]: from flask import Flask
In [2]: from flask.ext.cache import Cache
In [3]: app = Flask('')
In [4]: cache = Cache(app, config={'CACHE_TYPE': 'simple'})
In [5]: def create_cached_function(f):
...:         return cache.memoize(timeout=5)(f)
...: f1 = create_cached_function(lambda x: 1)
...: f2 = create_cached_function(lambda x: 2)
...: 

In [6]: f1('')
Out[6]: 1

In [7]: f2('')
Out[7]: 1

Delete memoized cache without access to the object

The memoization use he key User.f('test'){}, but delete_memoized try to remove the User.f("'test'"){}, because you're always trying to repr the first self parameter. Can you check if it is already a string before you get the repr to provide a feature to delete memoized cache even without access to the object?

class User(object):
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return self.name

    @cache.memoize()
    def f(self):
        # do something
        pass
>>> u = User('test')
>>> u.f()

# delete in a scope without access to the object
>>> cache.delete_memoized(User.f, User('test'))  # match memoized cache
>>> cache.delete_memoized(User.f, 'test')  # do not match memoized cache

Memoized?

I am a little worried with how memoized seems to work here. Say, we're using more persistent cache than simple thread local storage.

Specifically if we use the example here:
@cache.memoize(3600)
def has_membership(role):
return self.groups.filter_by(role=role).count() >= 1

And call has_membership('something') - it is cached.

In following request we call: cache.delete_memoized('has_membership') and what it should do is delete all memoized versions of this function. Well, it won't.

Correct me if I am wrong but you're keeping track of memoized functions by simply storing them in self field and in following requests - it is empty on init. This is not scalable at all and will only work in simplest of cases. Bad design decision, that's for sure.

Catch Error in cache/memoize ?

I saw that you catched get/set error here and here , but if set/get fail there is a big chance that cache_key = decorated_function.make_cache_key(*args, **kwargs) fails 3 line above in each case and also here .

should I move it inside the try/catch too ? and wrap in a try catch for the 3rd case ?

Support GAE

Some import fails when run on GAE's sandbox and ys.path.append(os.path.join(os.path.dirname(__file__), 'venv/lib/python2.7/site-packages')) is used to add all extra modules:

ERROR    2012-11-04 20:36:44,336 cgi.py:121] Traceback (most recent call last):
  File "/Users/cartercharbonneau/dndapp/run.py", line 3, in <module>
    from dndapp import app
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver_import_hook.py", line 719, in Decorate
    return func(self, *args, **kwargs)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver_import_hook.py", line 1928, in load_module
    return self.FindAndLoadModule(submodule, fullname, search_path)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver_import_hook.py", line 719, in Decorate
    return func(self, *args, **kwargs)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver_import_hook.py", line 1792, in FindAndLoadModule
    description)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver_import_hook.py", line 719, in Decorate
    return func(self, *args, **kwargs)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver_import_hook.py", line 1735, in LoadModuleRestricted
    description)
  File "/Users/cartercharbonneau/dndapp/dndapp/__init__.py", line 7, in <module>
    cache = Cache(app, False)
  File "/Users/cartercharbonneau/dndapp/venv/lib/python2.7/site-packages/flask_cache/__init__.py", line 64, in __init__
    self.init_app(app)
  File "/Users/cartercharbonneau/dndapp/venv/lib/python2.7/site-packages/flask_cache/__init__.py", line 98, in init_app
    self._set_cache()
  File "/Users/cartercharbonneau/dndapp/venv/lib/python2.7/site-packages/flask_cache/__init__.py", line 106, in _set_cache
    cache_obj = import_string(import_me)
  File "/Users/cartercharbonneau/dndapp/venv/lib/python2.7/site-packages/werkzeug/utils.py", line 422, in import_string
    __import__(modname)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver_import_hook.py", line 719, in Decorate
    return func(self, *args, **kwargs)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver_import_hook.py", line 1928, in load_module
    return self.FindAndLoadModule(submodule, fullname, search_path)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver_import_hook.py", line 719, in Decorate
    return func(self, *args, **kwargs)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver_import_hook.py", line 1792, in FindAndLoadModule
    description)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver_import_hook.py", line 719, in Decorate
    return func(self, *args, **kwargs)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/dev_appserver_import_hook.py", line 1735, in LoadModuleRestricted
    description)
  File "/Users/cartercharbonneau/dndapp/venv/lib/python2.7/site-packages/flask_cache/backends.py", line 1, in <module>
    from werkzeug.contrib.cache import (NullCache, SimpleCache, MemcachedCache,
  File "/Users/cartercharbonneau/dndapp/venv/lib/python2.7/site-packages/flask/exthook.py", line 86, in load_module
    raise ImportError('No module named %s' % fullname)
ImportStringError: import_string() failed for 'flask.ext.cache.backends.gaememcached'. Possible reasons are:

- missing __init__.py in a package;
- package or module path not included in sys.path;
- duplicated package or module name taking precedence in sys.path;
- missing module, class, function or variable;

Debugged import:

- 'flask' found in '/Users/cartercharbonneau/dndapp/venv/lib/python2.7/site-packages/flask/__init__.pyc'.
- 'flask.ext' found in '/Users/cartercharbonneau/dndapp/venv/lib/python2.7/site-packages/flask/ext/__init__.pyc'.
- 'flask.ext.cache' found in '/Users/cartercharbonneau/dndapp/venv/lib/python2.7/site-packages/flask_cache/__init__.pyc'.
- 'flask.ext.cache.backends' not found.

Original exception:

ImportError: No module named flask.ext.cache.werkzeug

Version 0.7.0 broke setup file.

Last version of your module haves "import version" from flaskext.cache.

Also flaskext.cache haves another imports (like as: flask, werkzeug). Its realy broke installation of Flask-Cache. Because python setuptools try to read "install_requires" and get exception "No module named werkzeug".

In my case, Im have have "requirements.txt" file:

Flask>=0.9
Flask-SQLAlchemy>=0.16
Flask-Cache>=0.6.0

And when I create virtualenv and try to do "pip install -r requirements.txt", its make exception.

Would you like fix that?

delete memoize cache for classmethod is not working

I am trying to use memoize functionality of flask-cache, but I am having problem with delete-memoized functionality. Here is my code.

class SessionsRepository(object):

    @classmethod
    @app.cache.memoize(30)    
    def get_session_by_id(self, session_id, get_attendees=False, timezone = None):
        result = {}
        sessioninfo = None
        sessioninfo = db.session.query(Sessions).filter(Sessions.session_id == int(session_id)).first()

        if timezone is not None:
            sessioninfo = update_session_date_and_time_with_timezone(sessioninfo, timezone)

        if get_attendees is True:
            result['session'] = sessioninfo

            result['students'] = []
            students = db.session.query(models.users.Users, SessionAttendees.attendance_id).filter(SessionAttendees.session_id == session_id, SessionAttendees.user_id == models.users.Users.user_id).all()
            if students is not None:
                for user, attid in students:
                    result['students'].append(user)

            return result
        else:
            return sessioninfo


    @classmethod    
    def update_session_by_id(self, session_id, session, sis_push = True):
         #update Session
         db.session.query(Sessions).filter(Sessions.session_id == session_id).update(session)
         app.cache.delete_memoized(SessionsRepository.get_session_by_id, SessionsRepository, session_id)


session_info = SessionsRepository.get_session_by_id(1)
print session_info
if session_info.status == 0:
    SessionsRepository.update_session_by_id(1,{'status' : 1})

session_info = SessionsRepository.get_session_by_id(1)
print session_info

I also tried with app.cache.delete_memoized(self.get_session_by_id, self, session_id) too.
Can someone help me with this? I tried to print cache_key in package to, and i see diff cache key for cache and delete call.

username/password options

I'm using a memcached server (on Heroku) and configuring username/password options WITHIN flask-cache to interface with a memcached server requiring that username/password be specified is not clear from the documentation.

I'm guessing this would go in CACHE_ARGS or CACHE_OPTIONS, but again how to do this isn't clear. I'm sure it is simple, but a guide for someone not intimately acquainted with this code base would be useful.

I can try a few things, and will gladly contribute, but clearer documentation/examples/saying this is or isn't possible would be appreciated.

Make template tag timeout optional

I have to always make something like: {% cache 7*24*60*60 "key" %}. I want to make timeout optional, even with keys.

{% cache "default" "key" %}

Is it possible to use Flask-Cache unless feature with Jinja?

I'm attempting to use Unless within a flask template. The example bellow is clearly documented as not possible, any options? Or this is not documented?

{% cache 5*60, 'myform', User.id | string, unless=g.cache%}

.. my templte data..

{% endcache %}

Usage inside blueprints

Hi, i would like to get information about the correct way to use Flask-Cache inside flask Blueprints. Thank you,

NullCache for TESTING

Why are you forced "cache.cache = NullCache()" for "TESTING=True"? I want to use "SimpleCache" for my test by example and etc.

It is always possible to setup CACHE_TYPE in test settings for your app (if you can set TESTING=True, you also can set CACHE_TYPE='null' if needed). But now it is useless with flask-cache for testing.

I have to set "TESTING=False" for my tests with your extension and its ugly by my opinion.

I propose to remove this condition.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.