Skip to content

Commit 68c0bd1

Browse files
committed
Add support for BZMPOP (redis#1851)
* add bzmpop * add comment * fix pr comment * fix linters * fix pr comments
1 parent 3c217a8 commit 68c0bd1

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

redis/commands/core.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import hashlib
33
import time
44
import warnings
5+
from typing import List, Optional
56

67
from redis.exceptions import ConnectionError, DataError, NoScriptError, RedisError
78

@@ -3237,6 +3238,38 @@ def bzpopmin(self, keys, timeout=0):
32373238
keys.append(timeout)
32383239
return self.execute_command("BZPOPMIN", *keys)
32393240

3241+
def bzmpop(
3242+
self,
3243+
timeout: float,
3244+
numkeys: int,
3245+
keys: List[str],
3246+
min: Optional[bool] = False,
3247+
max: Optional[bool] = False,
3248+
count: Optional[int] = 1,
3249+
) -> Optional[list]:
3250+
"""
3251+
Pop ``count`` values (default 1) off of the first non-empty sorted set
3252+
named in the ``keys`` list.
3253+
3254+
If none of the sorted sets in ``keys`` has a value to pop,
3255+
then block for ``timeout`` seconds, or until a member gets added
3256+
to one of the sorted sets.
3257+
3258+
If timeout is 0, then block indefinitely.
3259+
3260+
For more information check https://redis.io/commands/bzmpop
3261+
"""
3262+
args = [timeout, numkeys, *keys]
3263+
if (min and max) or (not min and not max):
3264+
raise DataError("Either min or max, but not both must be set")
3265+
elif min:
3266+
args.append("MIN")
3267+
else:
3268+
args.append("MAX")
3269+
args.extend(["COUNT", count])
3270+
3271+
return self.execute_command("BZMPOP", *args)
3272+
32403273
def _zrange(
32413274
self,
32423275
command,

tests/test_commands.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2058,6 +2058,19 @@ def test_bzpopmin(self, r):
20582058
r.zadd("c", {"c1": 100})
20592059
assert r.bzpopmin("c", timeout=1) == (b"c", b"c1", 100)
20602060

2061+
@pytest.mark.onlynoncluster
2062+
# @skip_if_server_version_lt("7.0.0") turn on after redis 7 release
2063+
def test_bzmpop(self, unstable_r):
2064+
unstable_r.zadd("a", {"a1": 1, "a2": 2, "a3": 3})
2065+
res = [b"a", [[b"a1", b"1"], [b"a2", b"2"]]]
2066+
assert unstable_r.bzmpop(1, "2", ["b", "a"], min=True, count=2) == res
2067+
with pytest.raises(redis.DataError):
2068+
unstable_r.bzmpop(1, "2", ["b", "a"], count=2)
2069+
unstable_r.zadd("b", {"b1": 10, "ab": 9, "b3": 8})
2070+
res = [b"b", [[b"b1", b"10"]]]
2071+
assert unstable_r.bzmpop(0, "2", ["b", "a"], max=True) == res
2072+
assert unstable_r.bzmpop(1, "2", ["foo", "bar"], max=True) is None
2073+
20612074
def test_zrange(self, r):
20622075
r.zadd("a", {"a1": 1, "a2": 2, "a3": 3})
20632076
assert r.zrange("a", 0, 1) == [b"a1", b"a2"]

0 commit comments

Comments
 (0)