diff options
author | netocp <netocalderonp@hotmail.es> | 2019-10-07 21:34:50 -0400 |
---|---|---|
committer | Andy McCurdy <andy@andymccurdy.com> | 2020-01-30 13:34:31 -0800 |
commit | a77ad503edb6b511a1cc042607cc318185ea2782 (patch) | |
tree | 96ee3071821aeeaa8a1fa0bdb2870a51c4c82d5e | |
parent | 272d3139e1c82c2d89551f87d12df7c18d938ea2 (diff) | |
download | redis-py-a77ad503edb6b511a1cc042607cc318185ea2782.tar.gz |
add type filter to scan function
Fixed #1220
-rw-r--r-- | CHANGES | 1 | ||||
-rwxr-xr-x | redis/client.py | 25 | ||||
-rw-r--r-- | tests/test_commands.py | 8 |
3 files changed, 29 insertions, 5 deletions
@@ -19,6 +19,7 @@ specified in the SSL cert. By default 'ssl_check_hostname' is False for backwards compatibility. #1196 * Slightly optimized command packing. Thanks @Deneby67. #1255 + * Added support for the TYPE argument to SCAN. Thanks @netocp. #1220 * 3.3.11 * Further fix for the SSLError -> TimeoutError mapping to work on obscure releases of Python 2.7. diff --git a/redis/client.py b/redis/client.py index fba80c9..9d38c50 100755 --- a/redis/client.py +++ b/redis/client.py @@ -2058,34 +2058,49 @@ class Redis(object): return self.execute_command('SORT', *pieces, **options) # SCAN COMMANDS - def scan(self, cursor=0, match=None, count=None): + def scan(self, cursor=0, match=None, count=None, _type=None): """ Incrementally return lists of key names. Also return a cursor indicating the scan position. ``match`` allows for filtering the keys by pattern - ``count`` allows for hint the minimum number of returns + ``count`` provides a hint to Redis about the number of keys to + return per batch. + + ``_type`` filters the returned values by a particular Redis type. + Stock Redis instances allow for the following types: + HASH, LIST, SET, STREAM, STRING, ZSET + Additionally, Redis modules can expose other types as well. """ pieces = [cursor] if match is not None: pieces.extend([b'MATCH', match]) if count is not None: pieces.extend([b'COUNT', count]) + if _type is not None: + pieces.extend([b'TYPE', _type]) return self.execute_command('SCAN', *pieces) - def scan_iter(self, match=None, count=None): + def scan_iter(self, match=None, count=None, _type=None): """ Make an iterator using the SCAN command so that the client doesn't need to remember the cursor position. ``match`` allows for filtering the keys by pattern - ``count`` allows for hint the minimum number of returns + ``count`` provides a hint to Redis about the number of keys to + return per batch. + + ``_type`` filters the returned values by a particular Redis type. + Stock Redis instances allow for the following types: + HASH, LIST, SET, STREAM, STRING, ZSET + Additionally, Redis modules can expose other types as well. """ cursor = '0' while cursor != 0: - cursor, data = self.scan(cursor=cursor, match=match, count=count) + cursor, data = self.scan(cursor=cursor, match=match, + count=count, _type=_type) for item in data: yield item diff --git a/tests/test_commands.py b/tests/test_commands.py index 00752fa..b2bd2da 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -1065,6 +1065,14 @@ class TestRedisCommands(object): _, keys = r.scan(match='a') assert set(keys) == {b'a'} + @skip_if_server_version_lt('5.9.101') + def test_scan_type(self, r): + r.sadd('a-set', 1) + r.hset('a-hash', 'foo', 2) + r.lpush('a-list', 'aux', 3) + _, keys = r.scan(match='a*', _type='SET') + assert set(keys) == {b'a-set'} + @skip_if_server_version_lt('2.8.0') def test_scan_iter(self, r): r.set('a', 1) |