summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornetocp <netocalderonp@hotmail.es>2019-10-07 21:34:50 -0400
committerAndy McCurdy <andy@andymccurdy.com>2020-01-30 13:34:31 -0800
commita77ad503edb6b511a1cc042607cc318185ea2782 (patch)
tree96ee3071821aeeaa8a1fa0bdb2870a51c4c82d5e
parent272d3139e1c82c2d89551f87d12df7c18d938ea2 (diff)
downloadredis-py-a77ad503edb6b511a1cc042607cc318185ea2782.tar.gz
add type filter to scan function
Fixed #1220
-rw-r--r--CHANGES1
-rwxr-xr-xredis/client.py25
-rw-r--r--tests/test_commands.py8
3 files changed, 29 insertions, 5 deletions
diff --git a/CHANGES b/CHANGES
index 074fac6..c200eea 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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)