Skip to content

Commit

Permalink
Code reorg.
Browse files Browse the repository at this point in the history
  • Loading branch information
coleifer committed Jan 9, 2015
1 parent c8443b9 commit a162852
Show file tree
Hide file tree
Showing 7 changed files with 2,028 additions and 2,001 deletions.
11 changes: 10 additions & 1 deletion walrus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,13 @@
# `-=`` `: | /-/-/`
# `.__/

from walrus.tusk import *
from walrus.cache import Cache
from walrus.containers import Array
from walrus.containers import Container
from walrus.containers import Hash
from walrus.containers import HyperLogLog
from walrus.containers import List
from walrus.containers import Set
from walrus.containers import ZSet
from walrus.database import Database
from walrus.models import *
109 changes: 109 additions & 0 deletions walrus/cache.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
from functools import wraps
import hashlib
import pickle


class Cache(object):
"""
Cache implementation with simple ``get``/``set`` operations,
and a decorator.
"""
def __init__(self, database, name='cache', default_timeout=None):
"""
:param database: :py:class:`Database` instance.
:param name: Namespace for this cache.
:param int default_timeout: Default cache timeout.
"""
self.database = database
self.name = name
self.default_timeout = default_timeout

def make_key(self, s):
return ':'.join((self.name, s))

def get(self, key, default=None):
"""
Retreive a value from the cache. In the event the value
does not exist, return the ``default``.
"""
key = self.make_key(key)
try:
value = self.database[key]
except KeyError:
return default
else:
return pickle.loads(value)

def set(self, key, value, timeout=None):
"""
Cache the given ``value`` in the specified ``key``. If no
timeout is specified, the default timeout will be used.
"""
key = self.make_key(key)
if timeout is None:
timeout = self.default_timeout

pickled_value = pickle.dumps(value)
if timeout:
return self.database.setex(key, pickled_value, int(timeout))
else:
return self.database.set(key, pickled_value)

def delete(self, key):
"""Remove the given key from the cache."""
self.database.delete(self.make_key(key))

def keys(self):
"""
Return all keys for cached values.
"""
return self.database.keys(self.make_key('') + '*')

def flush(self):
"""Remove all cached objects from the database."""
return self.database.delete(*self.keys())

def incr(self, key, delta=1):
return self.database.incr(self.make_key(key), delta)

def _key_fn(a, k):
return hashlib.md5(pickle.dumps((a, k))).hexdigest()

def cached(self, key_fn=_key_fn, timeout=3600):
"""
Decorator that will transparently cache calls to the
wrapped function. By default, the cache key will be made
up of the arguments passed in (like memoize), but you can
override this by specifying a custom ``key_fn``.
Usage::
cache = Cache(my_database)
@cache.cached(timeout=60)
def add_numbers(a, b):
return a + b
print add_numbers(3, 4) # Function is called.
print add_numbers(3, 4) # Not called, value is cached.
add_numbers.bust(3, 4) # Clear cache for (3, 4).
print add_numbers(3, 4) # Function is called.
The decorated function also gains a new attribute named
``bust`` which will clear the cache for the given args.
"""
def decorator(fn):
def bust(*args, **kwargs):
return self.delete(key_fn(args, kwargs))
@wraps(fn)
def inner(*args, **kwargs):
key = key_fn(args, kwargs)
res = self.get(key)
if res is None:
res = fn(*args, **kwargs)
self.set(key, res, timeout)
return res
inner.bust = bust
return inner
return decorator

0 comments on commit a162852

Please sign in to comment.