Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
D
Django-Redis-Cache
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Shared
Django-Redis-Cache
Commits
238e9b55
Commit
238e9b55
authored
Aug 09, 2011
by
Ales Zoulek
Browse files
Options
Browse Files
Download
Plain Diff
merge
parents
e05a534e
19415eac
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
103 additions
and
22 deletions
+103
-22
AUTHORS.rst
AUTHORS.rst
+2
-0
cache.py
redis_cache/cache.py
+54
-16
setup.py
setup.py
+1
-1
tests.py
tests/testapp/tests.py
+46
-5
No files found.
AUTHORS.rst
View file @
238e9b55
...
...
@@ -6,3 +6,5 @@ Noah Kantrowitz / coderanger <http://github.com/coderanger>
Martin Mahner / bartTC <http://github.com/bartTC>
Timothée Peignier / cyberdelia <https://github.com/cyberdelia>
Lior Sion / liorsion <https://github.com/liorsion>
Ales Zoulek / aleszoulek <https://github.com/aleszoulek>
James Aylett / jaylett <https://github.com/jaylett>
redis_cache/cache.py
View file @
238e9b55
...
...
@@ -15,7 +15,6 @@ except ImportError:
"Redis cache backend requires the 'redis-py' library"
)
class
CacheKey
(
object
):
"""
A stub string class that we can use to check if a key was created already.
...
...
@@ -29,6 +28,9 @@ class CacheKey(object):
def
__str__
(
self
):
return
self
.
__unicode__
()
def
__repr__
(
self
):
return
self
.
__unicode__
()
def
__unicode__
(
self
):
return
smart_str
(
self
.
_key
)
...
...
@@ -38,7 +40,11 @@ class CacheClass(BaseCache):
"""
Connect to Redis, and set up cache backend.
"""
self
.
_init
(
server
,
params
)
def
_init
(
self
,
server
,
params
):
super
(
CacheClass
,
self
)
.
__init__
(
params
)
self
.
_initargs
=
{
'server'
:
server
,
'params'
:
params
}
options
=
params
.
get
(
'OPTIONS'
,
{})
password
=
params
.
get
(
'password'
,
options
.
get
(
'PASSWORD'
,
None
))
db
=
params
.
get
(
'db'
,
options
.
get
(
'DB'
,
1
))
...
...
@@ -55,8 +61,13 @@ class CacheClass(BaseCache):
else
:
host
=
server
or
'localhost'
port
=
6379
self
.
_cache
=
redis
.
Redis
(
host
=
host
,
port
=
port
,
db
=
db
,
password
=
password
)
self
.
_client
=
redis
.
Redis
(
host
=
host
,
port
=
port
,
db
=
db
,
password
=
password
)
def
__getstate__
(
self
):
return
self
.
_initargs
def
__setstate__
(
self
,
state
):
self
.
_init
(
**
state
)
def
make_key
(
self
,
key
,
version
=
None
):
"""
...
...
@@ -74,7 +85,7 @@ class CacheClass(BaseCache):
Returns ``True`` if the object was added, ``False`` if not.
"""
key
=
self
.
make_key
(
key
,
version
=
version
)
if
self
.
_c
ache
.
exists
(
key
):
if
self
.
_c
lient
.
exists
(
key
):
return
False
return
self
.
set
(
key
,
value
,
timeout
)
...
...
@@ -85,23 +96,31 @@ class CacheClass(BaseCache):
Returns unpickled value if key is found, the default if not.
"""
key
=
self
.
make_key
(
key
,
version
=
version
)
value
=
self
.
_c
ache
.
get
(
key
)
value
=
self
.
_c
lient
.
get
(
key
)
if
value
is
None
:
return
default
return
self
.
unpickle
(
value
)
try
:
result
=
int
(
value
)
except
(
ValueError
,
TypeError
):
result
=
self
.
unpickle
(
value
)
return
result
def
set
(
self
,
key
,
value
,
timeout
=
None
,
version
=
None
,
client
=
None
):
"""
Persist a value to the cache, and set an optional expiration time.
"""
if
not
client
:
client
=
self
.
_c
ache
client
=
self
.
_c
lient
key
=
self
.
make_key
(
key
,
version
=
version
)
# get timout
if
not
timeout
:
timeout
=
self
.
default_timeout
# store the pickled value
result
=
client
.
setex
(
key
,
pickle
.
dumps
(
value
),
int
(
timeout
))
try
:
value
=
int
(
value
)
except
(
ValueError
,
TypeError
):
result
=
client
.
setex
(
key
,
pickle
.
dumps
(
value
),
int
(
timeout
))
else
:
result
=
client
.
setex
(
key
,
value
,
int
(
timeout
))
# result is a boolean
return
result
...
...
@@ -109,7 +128,7 @@ class CacheClass(BaseCache):
"""
Remove a key from the cache.
"""
self
.
_c
ache
.
delete
(
self
.
make_key
(
key
,
version
=
version
))
self
.
_c
lient
.
delete
(
self
.
make_key
(
key
,
version
=
version
))
def
delete_many
(
self
,
keys
,
version
=
None
):
"""
...
...
@@ -117,14 +136,14 @@ class CacheClass(BaseCache):
"""
if
keys
:
keys
=
map
(
lambda
key
:
self
.
make_key
(
key
,
version
=
version
),
keys
)
self
.
_c
ache
.
delete
(
*
keys
)
self
.
_c
lient
.
delete
(
*
keys
)
def
clear
(
self
):
"""
Flush all cache keys.
"""
# TODO : potential data loss here, should we only delete keys based on the correct version ?
self
.
_c
ache
.
flushdb
()
self
.
_c
lient
.
flushdb
()
def
unpickle
(
self
,
value
):
"""
...
...
@@ -142,11 +161,14 @@ class CacheClass(BaseCache):
recovered_data
=
SortedDict
()
new_keys
=
map
(
lambda
key
:
self
.
make_key
(
key
,
version
=
version
),
keys
)
map_keys
=
dict
(
zip
(
new_keys
,
keys
))
results
=
self
.
_c
ache
.
mget
(
new_keys
)
results
=
self
.
_c
lient
.
mget
(
new_keys
)
for
key
,
value
in
zip
(
new_keys
,
results
):
if
value
is
None
:
continue
value
=
self
.
unpickle
(
value
)
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
...
...
@@ -160,11 +182,27 @@ class CacheClass(BaseCache):
If timeout is given, that timeout will be used for the key; otherwise
the default cache timeout will be used.
"""
pipeline
=
self
.
_c
ache
.
pipeline
()
pipeline
=
self
.
_c
lient
.
pipeline
()
for
key
,
value
in
data
.
iteritems
():
self
.
set
(
key
,
value
,
timeout
,
version
=
version
,
client
=
pipeline
)
pipeline
.
execute
()
def
incr
(
self
,
key
,
delta
=
1
,
version
=
None
):
"""
Add delta to value in the cache. If the key does not exist, raise a
ValueError exception.
"""
key
=
self
.
make_key
(
key
,
version
=
version
)
exists
=
self
.
_client
.
exists
(
key
)
if
not
exists
:
raise
ValueError
(
"Key '
%
s' not found"
%
key
)
try
:
value
=
self
.
_client
.
incr
(
key
,
delta
)
except
redis
.
ResponseError
:
value
=
self
.
get
(
key
)
+
1
self
.
set
(
key
,
value
)
return
value
class
RedisCache
(
CacheClass
):
"""
...
...
@@ -188,7 +226,7 @@ class RedisCache(CacheClass):
version
=
self
.
version
old_key
=
self
.
make_key
(
key
,
version
)
value
=
self
.
get
(
old_key
,
version
=
version
)
ttl
=
self
.
_c
ache
.
ttl
(
old_key
)
ttl
=
self
.
_c
lient
.
ttl
(
old_key
)
if
value
is
None
:
raise
ValueError
(
"Key '
%
s' not found"
%
key
)
new_key
=
self
.
make_key
(
key
,
version
=
version
+
delta
)
...
...
setup.py
View file @
238e9b55
...
...
@@ -5,7 +5,7 @@ setup(
url
=
"http://github.com/sebleier/django-redis-cache/"
,
author
=
"Sean Bleier"
,
author_email
=
"sebleier@gmail.com"
,
version
=
"0.
6.1
"
,
version
=
"0.
8.2
"
,
packages
=
[
"redis_cache"
],
description
=
"Redis Cache Backend for Django"
,
install_requires
=
[
'redis>=2.4.5'
,],
...
...
tests/testapp/tests.py
View file @
238e9b55
...
...
@@ -34,7 +34,7 @@ class RedisCacheTests(TestCase):
def
reset_pool
(
self
):
if
hasattr
(
self
,
'cache'
):
self
.
cache
.
_c
ache
.
connection_pool
.
disconnect
()
self
.
cache
.
_c
lient
.
connection_pool
.
disconnect
()
def
get_cache
(
self
,
backend
=
None
):
if
VERSION
[
0
]
==
1
and
VERSION
[
1
]
<
3
:
...
...
@@ -52,9 +52,9 @@ class RedisCacheTests(TestCase):
def
test_default_initialization
(
self
):
self
.
reset_pool
()
self
.
cache
=
self
.
get_cache
(
'redis_cache.cache://127.0.0.1'
)
self
.
assertEqual
(
self
.
cache
.
_c
ache
.
connection_pool
.
connection_kwargs
[
'host'
],
'127.0.0.1'
)
self
.
assertEqual
(
self
.
cache
.
_c
ache
.
connection_pool
.
connection_kwargs
[
'db'
],
1
)
self
.
assertEqual
(
self
.
cache
.
_c
ache
.
connection_pool
.
connection_kwargs
[
'port'
],
6379
)
self
.
assertEqual
(
self
.
cache
.
_c
lient
.
connection_pool
.
connection_kwargs
[
'host'
],
'127.0.0.1'
)
self
.
assertEqual
(
self
.
cache
.
_c
lient
.
connection_pool
.
connection_kwargs
[
'db'
],
1
)
self
.
assertEqual
(
self
.
cache
.
_c
lient
.
connection_pool
.
connection_kwargs
[
'port'
],
6379
)
def
test_simple
(
self
):
# Simple cache set/get works
...
...
@@ -83,6 +83,20 @@ class RedisCacheTests(TestCase):
self
.
assertEqual
(
self
.
cache
.
get_many
([
'a'
,
'c'
,
'd'
]),
{
'a'
:
'a'
,
'c'
:
'c'
,
'd'
:
'd'
})
self
.
assertEqual
(
self
.
cache
.
get_many
([
'a'
,
'b'
,
'e'
]),
{
'a'
:
'a'
,
'b'
:
'b'
})
def
test_get_many_with_manual_integer_insertion
(
self
):
keys
=
[
'a'
,
'b'
,
'c'
,
'd'
]
cache_keys
=
map
(
self
.
cache
.
make_key
,
keys
)
# manually set integers and then get_many
for
i
,
key
in
enumerate
(
cache_keys
):
self
.
cache
.
_client
.
set
(
key
,
i
)
self
.
assertEqual
(
self
.
cache
.
get_many
(
keys
),
{
'a'
:
0
,
'b'
:
1
,
'c'
:
2
,
'd'
:
3
})
def
test_get_many_with_automatic_integer_insertion
(
self
):
keys
=
[
'a'
,
'b'
,
'c'
,
'd'
]
for
i
,
key
in
enumerate
(
keys
):
self
.
cache
.
set
(
key
,
i
)
self
.
assertEqual
(
self
.
cache
.
get_many
(
keys
),
{
'a'
:
0
,
'b'
:
1
,
'c'
:
2
,
'd'
:
3
})
def
test_delete
(
self
):
# Cache keys can be deleted
self
.
cache
.
set
(
"key1"
,
"spam"
)
...
...
@@ -194,7 +208,7 @@ class RedisCacheTests(TestCase):
def
test_set_expiration_timeout_None
(
self
):
key
,
value
=
self
.
cache
.
make_key
(
'key'
),
'value'
self
.
cache
.
set
(
key
,
value
);
self
.
assertTrue
(
self
.
cache
.
_c
ache
.
ttl
(
key
)
>
0
)
self
.
assertTrue
(
self
.
cache
.
_c
lient
.
ttl
(
key
)
>
0
)
def
test_unicode
(
self
):
# Unicode values can be cached
...
...
@@ -277,6 +291,33 @@ class RedisCacheTests(TestCase):
self
.
assertEqual
(
self
.
cache
.
get
(
old_key
),
None
)
self
.
assertEqual
(
self
.
cache
.
get
(
new_key
),
'spam'
)
def
test_incr_with_pickled_integer
(
self
):
"Testing case where there exists a pickled integer and we increment it"
number
=
42
key
=
self
.
cache
.
make_key
(
"key"
)
# manually set value using the redis client
self
.
cache
.
_client
.
set
(
key
,
pickle
.
dumps
(
number
))
new_value
=
self
.
cache
.
incr
(
key
)
self
.
assertEqual
(
new_value
,
number
+
1
)
# Test that the pickled value was converted to an integer
value
=
int
(
self
.
cache
.
_client
.
get
(
key
))
self
.
assertTrue
(
isinstance
(
value
,
int
))
# now that the value is an integer, let's increment it again.
new_value
=
self
.
cache
.
incr
(
key
,
7
)
self
.
assertEqual
(
new_value
,
number
+
8
)
def
test_pickling_cache_object
(
self
):
p
=
pickle
.
dumps
(
self
.
cache
)
cache
=
pickle
.
loads
(
p
)
# Now let's do a simple operation using the unpickled cache object
cache
.
add
(
"addkey1"
,
"value"
)
result
=
cache
.
add
(
"addkey1"
,
"newvalue"
)
self
.
assertEqual
(
result
,
False
)
self
.
assertEqual
(
cache
.
get
(
"addkey1"
),
"value"
)
if
__name__
==
'__main__'
:
unittest
.
main
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment