diff options
author | andy <andy@whiskeymedia.com> | 2013-04-22 21:28:54 -0700 |
---|---|---|
committer | andy <andy@whiskeymedia.com> | 2013-04-22 21:28:54 -0700 |
commit | b16d00993d61aa53304342256f8280bdae6ca21b (patch) | |
tree | 6753d6f86e541a0e4df39f8dd83c8d88e36bfc6a | |
parent | 69b84010fbd495e210887df75fb8b56bcba41a57 (diff) | |
parent | 400aad001fb66c3eb2566c9ee89f5af630ca6fe9 (diff) | |
download | redis-py-b16d00993d61aa53304342256f8280bdae6ca21b.tar.gz |
Merge branch 'mapleoin-master'
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | redis/client.py | 28 | ||||
-rw-r--r-- | tests/server_commands.py | 49 |
3 files changed, 79 insertions, 2 deletions
@@ -28,6 +28,10 @@ * Added PSETEX. Thanks YAMAMOTO Takashi. * Added a BlockingConnectionPool to limit the number of connections that can be created. Thanks James Arthur. + * SORT now accepts a `groups` option that if specified, will return + tuples of n-length, where n is the number of keys specified in the GET + argument. This allows for convenient row-based iteration. Thanks + Ionuț Arțăriși. * 2.7.2 * Parse errors are now *always* raised on multi/exec pipelines, regardless of the `raise_on_error` flag. See diff --git a/redis/client.py b/redis/client.py index d9506e6..ea8b5cf 100644 --- a/redis/client.py +++ b/redis/client.py @@ -127,6 +127,16 @@ def zset_score_pairs(response, **options): return list(izip(it, imap(score_cast_func, it))) +def sort_return_tuples(response, **options): + """ + If ``groups`` is specified, return the response as a list of + n-element tuples with n being the value found in options['groups'] + """ + if not response or not options['groups']: + return response + n = options['groups'] + return list(izip(*[response[i::n] for i in range(n)])) + def int_or_none(response): if response is None: return None @@ -198,6 +208,7 @@ class StrictRedis(object): 'LPUSH RPUSH', lambda r: isinstance(r, long) and r or nativestr(r) == 'OK' ), + string_keys_to_dict('SORT', sort_return_tuples), string_keys_to_dict('ZSCORE ZINCRBY', float_or_none), string_keys_to_dict( 'FLUSHALL FLUSHDB LSET LTRIM MSET RENAME ' @@ -912,7 +923,7 @@ class StrictRedis(object): return self.execute_command('RPUSHX', name, value) def sort(self, name, start=None, num=None, by=None, get=None, - desc=False, alpha=False, store=None): + desc=False, alpha=False, store=None, groups=False): """ Sort and return the list, set or sorted set at ``name``. @@ -931,6 +942,11 @@ class StrictRedis(object): ``store`` allows for storing the result of the sort into the key ``store`` + + ``groups`` if set to True and if ``get`` contains at least two + elements, sort will return a list of tuples, each containing the + values fetched from the arguments to ``get``. + """ if (start is not None and num is None) or \ (num is not None and start is None): @@ -963,7 +979,15 @@ class StrictRedis(object): if store is not None: pieces.append('STORE') pieces.append(store) - return self.execute_command('SORT', *pieces) + + if groups: + if not get or isinstance(get, basestring) or len(get) < 2: + raise DataError('when using "groups" the "get" argument ' + 'must be specified and contain at least ' + 'two keys') + + options = {'groups': len(get) if groups else None} + return self.execute_command('SORT', *pieces, **options) #### SET COMMANDS #### def sadd(self, name, *values): diff --git a/tests/server_commands.py b/tests/server_commands.py index 17adcf8..0225242 100644 --- a/tests/server_commands.py +++ b/tests/server_commands.py @@ -1513,6 +1513,55 @@ class ServerCommandsTestCase(unittest.TestCase): self.client.sort('a', get=('user:*', '#')), [b('u1'), b('1'), b('u2'), b('2'), b('u3'), b('3')]) + def test_sort_get_groups_two(self): + self.client['user:1'] = 'u1' + self.client['user:2'] = 'u2' + self.client['user:3'] = 'u3' + self.make_list('a', '231') + self.assertEquals( + self.client.sort('a', get=('user:*', '#'), groups=True), + [(b('u1'), b('1')), (b('u2'), b('2')), (b('u3'), b('3'))]) + + def test_sort_groups_string_get(self): + self.client['user:1'] = 'u1' + self.client['user:2'] = 'u2' + self.client['user:3'] = 'u3' + self.make_list('a', '231') + self.assertRaises(redis.DataError, self.client.sort, 'a', + get='user:*', groups=True) + + def test_sort_groups_just_one_get(self): + self.client['user:1'] = 'u1' + self.client['user:2'] = 'u2' + self.client['user:3'] = 'u3' + self.make_list('a', '231') + self.assertRaises(redis.DataError, self.client.sort, 'a', + get=['user:*'], groups=True) + + def test_sort_groups_no_get(self): + self.client['user:1'] = 'u1' + self.client['user:2'] = 'u2' + self.client['user:3'] = 'u3' + self.make_list('a', '231') + self.assertRaises(redis.DataError, self.client.sort, 'a', groups=True) + + def test_sort_groups_three_gets(self): + self.client['user:1'] = 'u1' + self.client['user:2'] = 'u2' + self.client['user:3'] = 'u3' + self.client['door:1'] = 'd1' + self.client['door:2'] = 'd2' + self.client['door:3'] = 'd3' + self.make_list('a', '231') + self.assertEquals( + self.client.sort('a', get=('user:*', 'door:*', '#'), groups=True), + [ + (b('u1'), b('d1'), b('1')), + (b('u2'), b('d2'), b('2')), + (b('u3'), b('d3'), b('3')) + ] + ) + def test_sort_desc(self): self.make_list('a', '231') self.assertEquals( |