diff options
author | andy <andy@whiskeymedia.com> | 2011-07-11 01:20:48 -0700 |
---|---|---|
committer | andy <andy@whiskeymedia.com> | 2011-07-11 01:20:48 -0700 |
commit | 37fb01edf06673cd56421497128daee3fafbd2d9 (patch) | |
tree | 44cb0f77cd61fdefc3f9323e2d7dd0e6661059cc | |
parent | 53c928d44acd3d1fbcb3896cadad0bde4671987a (diff) | |
parent | be1e7498ff195681f1cf760b764d657161715968 (diff) | |
download | redis-py-37fb01edf06673cd56421497128daee3fafbd2d9.tar.gz |
Merge branch 'master' into watch
Conflicts:
CHANGES
-rw-r--r-- | CHANGES | 11 | ||||
-rw-r--r-- | redis/client.py | 42 | ||||
-rw-r--r-- | tests/server_commands.py | 6 |
3 files changed, 38 insertions, 21 deletions
@@ -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' |