Skip to main content

Simple yet capable caching decorator for python

Project description

Simple yet capable caching decorator for python Source code: https://github.com/lonetwin/supycache

What is supycache ?

supycache is a decorator that enables caching of return values of time-consuming functions, either in memory or on a cache server such as memcached or redis.

The cache keys can either be indedependent or dependent (completely or partially) of the arguments passed to the function.

This is different from other similar caching decorators, for instance, functools.lru_cache which is dependent on all the arguments passed to the function and requires the arguments to be hashable.

Here’s an example of how you might use supycache

import time
import supycache

@supycache.supycache(cache_key='result')
def execute_expensive():
    time.sleep(15)
    return 42

print execute_expensive()  # This will take 15 seconds to execute ...
42
print execute_expensive()  # ...not this tho', because the value is cached ...
42
print supycache.default_backend.get('result') # ..keyed as `result`
42

However, you might want to be aware of the arguments that are passed to the function:

@supycache(cache_key='sum_of_{0}_and_{1}')   # Cache the sum of x and y creating a
def cached_sum(x, y):                        # key based on the arguments passed
    return x + y

You can also create the key based on partial arguments or on the attributes/items within the arguments.

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

@supycache(cache_key='{user_obj.name}')   # build the cache key dependent on *just*
def get_username(user_obj):               # the `.name` attribute
    time.sleep(15)
    return user_obj.name

a = User(name='steve', session_key='0123456789')
b = User(name='steve', session_key='9876543210') # same name, different session

print get_username(user_obj=a)   # This will take 15 seconds to execute ...
steve
print get_username(user_obj=a)   # ...not this tho'...
steve
print get_username(user_obj=b)   # ...and neither will this !
steve


@supycache(cache_key='{choices[0]}_{menu[lunch]}')         # build the cache
def supersized_lunch(ignored, choices=None, menu=None):    # key dependent on
    time.sleep(15)                                         # partial arguments
    return 'You get a %s %s' % (choices[-1], menu['lunch'])

menu = {'breakfast' : 'eggs',
        'lunch'     : 'pizza',
        'dinner'    : 'steak'}

sizes = ['small', 'medium', 'large', 'supersize']

print supersized_lunch('ignored', choices=sizes, menu=menu)
You get a supersize pizza       # This will take 15 seconds to execute ...

print supersized_lunch('changed', choices=sizes, menu=menu)
You get a supersize pizza       # ...not this tho'...

If that format specification for the cache_key looks familiar, you’ve discovered the secret of supycache !

@supycache(backend=memcached_backend, cache_key='{0}_{kw[foo]}_{obj.x}')
def custom_key_built_from_args(positional, kw=None, obj=None):
    # now, supycache will build the `cache_key` from the arguments passed and
    # use the memcached_backend instance to `set` the key with the return value
    # of this function
    return 'cached'

The secret of supycache is quite simple – it calls .format() on the cache_key/expire_key with the passed args and kwargs to build the actual key. Additionaly the backend interface is abstarcted out neatly so that backends can be swapped out without too much hassle …and yeah, the decorator accepts more than just cache_key.

Right now though, this project has only the code and tests, no docs (barring a couple of docstrings !). I’ll be adding them soon. If interested take a look at the tests to see the typical usage and try it out. Feedback, bug reports and pull requests would be great !

Help required

I would really appreciate any help you could offer in validating the packaging and distribution of this module via pypi since I’ve not distributed any packages before.

Besides that I plan on adding a few more things:

  • Ability to specify a max_age for the cache key.

  • I’m not sure not the packaging for the dependency would work, but I’d like to automatically include the support for memcached or redis backends if the python memcached or redis modules are installed.

  • logging support

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

supycache-0.1.tar.gz (5.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

supycache-0.1-py2.py3-none-any.whl (8.1 kB view details)

Uploaded Python 2Python 3

File details

Details for the file supycache-0.1.tar.gz.

File metadata

  • Download URL: supycache-0.1.tar.gz
  • Upload date:
  • Size: 5.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for supycache-0.1.tar.gz
Algorithm Hash digest
SHA256 421db954a1cfb08825df4258427cc8c977065f61fb839e9c2f322c6bc9f18500
MD5 3635609f792ba19138ae42648a82b2a4
BLAKE2b-256 5a94f116bdb63dc778f0ae2c1c86c42ce926ce07963cc8f2c12817a5c72c453d

See more details on using hashes here.

File details

Details for the file supycache-0.1-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for supycache-0.1-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 7cc69043d7e581823299b9923112cd4ed65eef285c17d94e5e103567e2505a1c
MD5 6b40d0327834ba5446ffb858f76bfe23
BLAKE2b-256 3f2a7b37050d04620882d8a072fd84db2478f6e87871b248b8c7646978df8401

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page