Skip to content
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
24 changes: 24 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
language: python
python:
- "2.6"
- "2.7"
env:
- DJANGO_VERSION=1.2 REDIS_VERSION=2.2
- DJANGO_VERSION=1.2 REDIS_VERSION=2.4
- DJANGO_VERSION=1.2 REDIS_VERSION=2.6
- DJANGO_VERSION=1.3 REDIS_VERSION=2.2
- DJANGO_VERSION=1.3 REDIS_VERSION=2.4
- DJANGO_VERSION=1.3 REDIS_VERSION=2.6
- DJANGO_VERSION=1.4 REDIS_VERSION=2.2
- DJANGO_VERSION=1.4 REDIS_VERSION=2.4
- DJANGO_VERSION=1.4 REDIS_VERSION=2.6
install:
- pip install Django==$DJANGO_VERSION
- pip install -e git://github.com/sebleier/redis-py.git#egg=redis-py
- pip install hiredis
- ./install_redis.sh
branches:
only:
- master
- experimental
script: ./travis_run_all_tests.sh
9 changes: 9 additions & 0 deletions install_redis.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
if [ -z $REDIS_VERSION ]; then
echo "This script is used to install redis for Travis-CI"
else
cd ..
git clone https://github.com/antirez/redis.git
cd redis
git checkout $REDIS_VERSION
make
fi
134 changes: 134 additions & 0 deletions redis_cache/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,23 @@ def get(self, key, default=None, version=None):
result = self.unpickle(value)
return result

def hget(self, name, key, default=None, version=None):
"""
Retrieve a value from the cache as hash.

Returns unpickled value if key is found, the default if not.
"""
name = self.make_key(name, version=version)
key = self.make_key(key, version=version)
value = self._client.hget(name, key)
if value is None:
return default
try:
result = int(value)
except (ValueError, TypeError):
result = self.unpickle(value)
return result

def _set(self, key, value, timeout, client):
if timeout == 0:
return client.set(key, value)
Expand All @@ -196,6 +213,15 @@ def _set(self, key, value, timeout, client):
else:
return False

def _hset(self, name, key, value, timeout, client):
"""Set value in hash"""
# Redis call
status = client.hset( name, key, value)
if timeout > 0:
# Set expire time
client.expire(name, timeout)
return status

def set(self, key, value, timeout=None, version=None, client=None):
"""
Persist a value to the cache, and set an optional expiration time.
Expand All @@ -217,6 +243,30 @@ def set(self, key, value, timeout=None, version=None, client=None):
# result is a boolean
return result

def hset(self, name, key, value, timeout=None, version=None, client=None):
"""
Sets field in the hash stored at key to value
and set an optional expiration time.
"""
if not client:
client = self._client
name = self.make_key(name, version=version)
key = self.make_key(key, version=version)
if timeout is None:
# To store it persistently
timeout = 0
try:
value = float(value)
# If you lose precision from the typecast to str, then pickle value
if int(value) != value:
raise TypeError
except (ValueError, TypeError):
result = self._hset(name, key, pickle.dumps(value), int(timeout), client)
else:
result = self._hset(name, key, int(value), int(timeout), client)
# result is a boolean
return result

def delete(self, key, version=None):
"""
Remove a key from the cache.
Expand Down Expand Up @@ -267,6 +317,31 @@ def get_many(self, keys, version=None):
recovered_data[map_keys[key]] = value
return recovered_data

def hget_many(self, name, keys, version=None):
"""
Retrieve many keys from hash.
Keys is the list of the key in the hash.
Result is returned as key value pair dict.
"""
recovered_data = SortedDict()
new_keys = map(lambda key: self.make_key(key, version=version), keys)
map_keys = dict(zip(new_keys, keys))
name = self.make_key(name, version=version)
# Redis call
results = self._client.hmget(name, new_keys)
# Iterate to convert the result into proper format.
for key, value in zip(new_keys, results):
if value is None:
continue
try:
value = int(value)
except (ValueError, TypeError):
value = self.unpickle(value)
if isinstance(value, basestring):
value = smart_unicode(value)
recovered_data[map_keys[key]] = value
return recovered_data

def set_many(self, data, timeout=None, version=None):
"""
Set a bunch of values in the cache at once from a dict of key/value
Expand All @@ -280,6 +355,38 @@ def set_many(self, data, timeout=None, version=None):
self.set(key, value, timeout, version=version, client=pipeline)
pipeline.execute()


def hset_many(self, name, mapping_dict, timeout=None, version=None):
"""
Set a bunch of values in the cache at once from a dict of key/value
pairs. This is much more efficient than calling hset() multiple times.

If timeout is given, that timeout will be used for the key; otherwise
stored persistently
"""
# Convert the keys to version format
mapping_dict = dict( (self.make_key(key, version), value) for key, value in mapping_dict.items() )
name = self.make_key(name, version=version)
# Iterate to convert the values to appropriate format.
for key, value in mapping_dict.items():
try:
value = float(value)
# If you lose precision from the typecast to str, then pickle value
if int(value) != value:
raise TypeError
except (ValueError, TypeError):
value = pickle.dumps(value)
else:
value = int(value)
mapping_dict[key] = value

# Redis call
result = self._client.hmset(name, mapping_dict)
if timeout is not None:
# Set timeout of the name
self._client.expire(name, timeout)
return result

def incr(self, key, delta=1, version=None):
"""
Add delta to value in the cache. If the key does not exist, raise a
Expand All @@ -296,6 +403,33 @@ def incr(self, key, delta=1, version=None):
self.set(key, value)
return value

def hincr(self, name, key, delta=1, version=None):
"""
Add delta to value in the cache of the hash.
If the key does not exist, raise a
ValueError exception.
"""
name = self.make_key(name, version=version)
key = self.make_key(key, version=version)
exists = self._client.hexists(name, key)
if not exists:
raise ValueError("Key '%s' not found" % key)
try:
# Redis call
value = self._client.hincrby(name, key, delta)
except redis.ResponseError:
value = self.hget(name, key) + 1
# Redis call
self.hset(name, key, value)
return value

def has_hkey(self, name, key, version=None):
"""
The name and key exist in the hash
"""
name = self.make_key(name, version=version)
key = self.make_key(key, version=version)
return self._client.hexists(name, key)

class RedisCache(CacheClass):
"""
Expand Down
5 changes: 5 additions & 0 deletions run_all_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

./run_tests.py --settings=tests.settings
./run_tests.py --settings=tests.python_parser_settings
./run_tests.py --settings=tests.sockets_settings
90 changes: 90 additions & 0 deletions run_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env python
from __future__ import with_statement
from optparse import OptionParser
import os
from os.path import dirname, abspath, join
import sys
from django.conf import settings
from django.template import Template, Context
from django.utils import importlib
from redis.server import server


def load_settings(module):
try:
mod = importlib.import_module(module)
except (ImportError):
return None

conf = {}
for setting in dir(mod):
if setting == setting.upper():
conf[setting] = getattr(mod, setting)
return conf


class TmpFile(object):
def __init__(self, path, contents):
self.path =path
self.contents = contents

def __enter__(self):
self.file = open(self.path, "w")
self.file.write(self.contents)
self.file.close()

def __exit__(self, exc_type, exc_value, traceback):
os.remove(self.path)


def runtests(options):
os.environ['DJANGO_SETTINGS_MODULE'] = options.settings

conf = load_settings(options.settings)

if conf is None:
sys.stderr.write('Cannot load settings module: %s\n' % options.settings)
return sys.exit(1)

settings.configure(**conf)

redis_conf_path = options.conf or join(dirname(__file__), 'tests', 'redis.conf')

server.configure(options.server_path, redis_conf_path, 0)

try:
redis_conf_template = open(join(dirname(__file__), 'tests' ,'redis.conf.tpl')).read()
except OSError, IOError:
sys.stderr.write('Cannot find template for redis.conf.\n')
context = Context({
'redis_socket': join(dirname(abspath(__file__)), 'tests', 'redis.sock')
})

contents = Template(redis_conf_template).render(context)

with TmpFile(redis_conf_path, contents):
with server:
from django.test.simple import DjangoTestSuiteRunner
runner = DjangoTestSuiteRunner(verbosity=options.verbosity, interactive=True, failfast=False)
failures = runner.run_tests(['testapp'])

sys.exit(failures)


if __name__ == '__main__':
parser = OptionParser()
parser.add_option("-s", "--server", dest="server_path", action="store",
type="string", default=None, help="Path to the redis server executable")
parser.add_option("-c", "--conf", dest="conf", default=None,
help="Path to the redis configuration file.")
parser.add_option("-v", "--verbosity", dest="verbosity", default=1, type="int",
help="Change the verbostiy of the redis-server.")
parser.add_option("--settings", dest="settings", default="tests.settings",
help="Django settings module to use for the tests.")

(options, args) = parser.parse_args()

parent = dirname(abspath(__file__))
sys.path.insert(0, parent)

runtests(options)
45 changes: 0 additions & 45 deletions sockettests.py

This file was deleted.

Loading