summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandy <andy@whiskeymedia.com>2011-07-11 01:20:48 -0700
committerandy <andy@whiskeymedia.com>2011-07-11 01:20:48 -0700
commit37fb01edf06673cd56421497128daee3fafbd2d9 (patch)
tree44cb0f77cd61fdefc3f9323e2d7dd0e6661059cc
parent53c928d44acd3d1fbcb3896cadad0bde4671987a (diff)
parentbe1e7498ff195681f1cf760b764d657161715968 (diff)
downloadredis-py-37fb01edf06673cd56421497128daee3fafbd2d9.tar.gz
Merge branch 'master' into watch
Conflicts: CHANGES
-rw-r--r--CHANGES11
-rw-r--r--redis/client.py42
-rw-r--r--tests/server_commands.py6
3 files changed, 38 insertions, 21 deletions
diff --git a/CHANGES b/CHANGES
index 24fb67e..72f1444 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,8 +1,15 @@
* 2.4.6 (in development)
* Variadic arguments for SADD, SREM, ZREN, HDEL, LPUSH, and RPUSH. Thanks
Raphaƫl Vinot.
- * Fixed a bug in the Hiredis Parser causing pooled connections to get
- corrupted occasionally.
+ * Fixed an error in the Hiredis parser that occasionally caused the
+ socket connection to become corrupted and unusable. This became noticeable
+ once connection pools started to be used.
+ * ZRANGE, ZREVRANGE, ZRANGEBYSCORE, and ZREVRANGEBYSCORE now take an
+ additional optional argument, score_cast_func, which is a callable used
+ to cast the score value in the return type. The default is float.
+ * Removed the PUBLISH method from the PubSub class. Connections that are
+ [P]SUBSCRIBEd cannot issue PUBLISH commands, so it doesn't make to have
+ it here.
* Pipelines now contain WATCH and UNWATCH. Calling WATCH or UNWATCH from
the base client class will result in a deprecation warning.
* 2.4.5
diff --git a/redis/client.py b/redis/client.py
index 8b8e7a8..a055f22 100644
--- a/redis/client.py
+++ b/redis/client.py
@@ -81,8 +81,9 @@ def zset_score_pairs(response, **options):
"""
if not response or not options['withscores']:
return response
+ score_cast_func = options.get('score_cast_func', float)
it = iter(response)
- return zip(it, imap(float, it))
+ return zip(it, imap(score_cast_func, it))
def int_or_none(response):
if response is None:
@@ -821,27 +822,31 @@ class Redis(object):
"""
return self._zaggregate('ZINTERSTORE', dest, keys, aggregate)
- def zrange(self, name, start, end, desc=False, withscores=False):
+ def zrange(self, name, start, end, desc=False, withscores=False,
+ score_cast_func=float):
"""
Return a range of values from sorted set ``name`` between
``start`` and ``end`` sorted in ascending order.
``start`` and ``end`` can be negative, indicating the end of the range.
- ``desc`` indicates to sort in descending order.
+ ``desc`` a boolean indicating whether to sort the results descendingly
``withscores`` indicates to return the scores along with the values.
The return type is a list of (value, score) pairs
+
+ ``score_cast_func`` a callable used to cast the score return value
"""
if desc:
return self.zrevrange(name, start, end, withscores)
pieces = ['ZRANGE', name, start, end]
if withscores:
pieces.append('withscores')
- return self.execute_command(*pieces, **{'withscores': withscores})
+ options = {'withscores': withscores, 'score_cast_func': score_cast_func}
+ return self.execute_command(*pieces, **options)
def zrangebyscore(self, name, min, max,
- start=None, num=None, withscores=False):
+ start=None, num=None, withscores=False, score_cast_func=float):
"""
Return a range of values from the sorted set ``name`` with scores
between ``min`` and ``max``.
@@ -851,6 +856,8 @@ class Redis(object):
``withscores`` indicates to return the scores along with the values.
The return type is a list of (value, score) pairs
+
+ `score_cast_func`` a callable used to cast the score return value
"""
if (start is not None and num is None) or \
(num is not None and start is None):
@@ -860,7 +867,8 @@ class Redis(object):
pieces.extend(['LIMIT', start, num])
if withscores:
pieces.append('withscores')
- return self.execute_command(*pieces, **{'withscores': withscores})
+ options = {'withscores': withscores, 'score_cast_func': score_cast_func}
+ return self.execute_command(*pieces, **options)
def zrank(self, name, value):
"""
@@ -889,7 +897,8 @@ class Redis(object):
"""
return self.execute_command('ZREMRANGEBYSCORE', name, min, max)
- def zrevrange(self, name, start, num, withscores=False):
+ def zrevrange(self, name, start, num, withscores=False,
+ score_cast_func=float):
"""
Return a range of values from sorted set ``name`` between
``start`` and ``num`` sorted in descending order.
@@ -898,14 +907,17 @@ class Redis(object):
``withscores`` indicates to return the scores along with the values
The return type is a list of (value, score) pairs
+
+ ``score_cast_func`` a callable used to cast the score return value
"""
pieces = ['ZREVRANGE', name, start, num]
if withscores:
pieces.append('withscores')
- return self.execute_command(*pieces, **{'withscores': withscores})
+ options = {'withscores': withscores, 'score_cast_func': score_cast_func}
+ return self.execute_command(*pieces, **options)
def zrevrangebyscore(self, name, max, min,
- start=None, num=None, withscores=False):
+ start=None, num=None, withscores=False, score_cast_func=float):
"""
Return a range of values from the sorted set ``name`` with scores
between ``min`` and ``max`` in descending order.
@@ -915,6 +927,8 @@ class Redis(object):
``withscores`` indicates to return the scores along with the values.
The return type is a list of (value, score) pairs
+
+ ``score_cast_func`` a callable used to cast the score return value
"""
if (start is not None and num is None) or \
(num is not None and start is None):
@@ -924,7 +938,8 @@ class Redis(object):
pieces.extend(['LIMIT', start, num])
if withscores:
pieces.append('withscores')
- return self.execute_command(*pieces, **{'withscores': withscores})
+ options = {'withscores': withscores, 'score_cast_func': score_cast_func}
+ return self.execute_command(*pieces, **options)
def zrevrank(self, name, value):
"""
@@ -1128,13 +1143,6 @@ class PubSub(object):
pass
return self.execute_command('UNSUBSCRIBE', *channels)
- def publish(self, channel, message):
- """
- Publish ``message`` on ``channel``.
- Returns the number of subscribers the message was delivered to.
- """
- return self.execute_command('PUBLISH', channel, message)
-
def listen(self):
"Listen for messages on channels this client has been subscribed to"
while self.subscription_count:
diff --git a/tests/server_commands.py b/tests/server_commands.py
index b106126..9e3375d 100644
--- a/tests/server_commands.py
+++ b/tests/server_commands.py
@@ -770,7 +770,6 @@ class ServerCommandsTestCase(unittest.TestCase):
[('a3', 20), ('a1', 23)]
)
-
def test_zrange(self):
# key is not a zset
self.client['a'] = 'a'
@@ -784,10 +783,13 @@ class ServerCommandsTestCase(unittest.TestCase):
[('a1', 1.0), ('a2', 2.0)])
self.assertEquals(self.client.zrange('a', 1, 2, withscores=True),
[('a2', 2.0), ('a3', 3.0)])
+ # test a custom score casting function returns the correct value
+ self.assertEquals(
+ self.client.zrange('a', 0, 1, withscores=True, score_cast_func=int),
+ [('a1', 1), ('a2', 2)])
# a non existant key should return empty list
self.assertEquals(self.client.zrange('b', 0, 1, withscores=True), [])
-
def test_zrangebyscore(self):
# key is not a zset
self.client['a'] = 'a'