Skip to content

Commit

Permalink
Python: adds ZREMRANGEBYSCORE command (valkey-io#1151)
Browse files Browse the repository at this point in the history
  • Loading branch information
shohamazon authored and cyip10 committed Jun 24, 2024
1 parent fc6a693 commit f1d219c
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 8 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Python: Added JSON.DEL JSON.FORGET commands ([#1146](https:/aws/glide-for-redis/pull/1146))
* Python: Added STRLEN command ([#1230](https:/aws/glide-for-redis/pull/1230))
* Python: Added HKEYS command ([#1228](https:/aws/glide-for-redis/pull/1228))
* Python: Added ZREMRANGEBYSCORE command ([#1151](https:/aws/glide-for-redis/pull/1151))

#### Fixes
* Python: Fix typing error "‘type’ object is not subscriptable" ([#1203](https:/aws/glide-for-redis/pull/1203))
Expand Down Expand Up @@ -84,4 +85,4 @@

Preview release of **GLIDE for Redis** a Polyglot Redis client.

See the [README](README.md) for additional information.
See the [README](README.md) for additional information.
48 changes: 48 additions & 0 deletions python/python/glide/async_commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1802,6 +1802,54 @@ async def zrem(
await self._execute_command(RequestType.Zrem, [key] + members),
)

async def zremrangebyscore(
self,
key: str,
min_score: Union[InfBound, ScoreBoundary],
max_score: Union[InfBound, ScoreBoundary],
) -> int:
"""
Removes all elements in the sorted set stored at `key` with a score between `min_score` and `max_score`.
See https://redis.io/commands/zremrangebyscore/ for more details.
Args:
key (str): The key of the sorted set.
min_score (Union[InfBound, ScoreBoundary]): The minimum score to remove from.
Can be an instance of InfBound representing positive/negative infinity,
or ScoreBoundary representing a specific score and inclusivity.
max_score (Union[InfBound, ScoreBoundary]): The maximum score to remove up to.
Can be an instance of InfBound representing positive/negative infinity,
or ScoreBoundary representing a specific score and inclusivity.
Returns:
int: The number of members that were removed from the sorted set.
If `key` does not exist, it is treated as an empty sorted set, and the command returns 0.
If `min_score` is greater than `max_score`, 0 is returned.
Examples:
>>> await client.zremrangebyscore("my_sorted_set", ScoreBoundary(5.0 , is_inclusive=true) , InfBound.POS_INF)
2 # Indicates that 2 members with scores between 5.0 (not exclusive) and +inf have been removed from the sorted set "my_sorted_set".
>>> await client.zremrangebyscore("non_existing_sorted_set", ScoreBoundary(5.0 , is_inclusive=true) , ScoreBoundary(10.0 , is_inclusive=false))
0 # Indicates that no members were removed as the sorted set "non_existing_sorted_set" does not exist.
"""
score_min = (
min_score.value["score_arg"]
if type(min_score) == InfBound
else min_score.value
)
score_max = (
max_score.value["score_arg"]
if type(max_score) == InfBound
else max_score.value
)

return cast(
int,
await self._execute_command(
RequestType.ZRemRangeByScore, [key, score_min, score_max]
),
)

async def zscore(self, key: str, member: str) -> Optional[float]:
"""
Returns the score of `member` in the sorted set stored at `key`.
Expand Down
39 changes: 39 additions & 0 deletions python/python/glide/async_commands/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -1389,6 +1389,45 @@ def zrem(
"""
return self.append_command(RequestType.Zrem, [key] + members)

def zremrangebyscore(
self: TTransaction,
key: str,
min_score: Union[InfBound, ScoreBoundary],
max_score: Union[InfBound, ScoreBoundary],
) -> TTransaction:
"""
Removes all elements in the sorted set stored at `key` with a score between `min_score` and `max_score`.
See https://redis.io/commands/zremrangebyscore/ for more details.
Args:
key (str): The key of the sorted set.
min_score (Union[InfBound, ScoreBoundary]): The minimum score to remove from.
Can be an instance of InfBound representing positive/negative infinity,
or ScoreBoundary representing a specific score and inclusivity.
max_score (Union[InfBound, ScoreBoundary]): The maximum score to remove up to.
Can be an instance of InfBound representing positive/negative infinity,
or ScoreBoundary representing a specific score and inclusivity.
Commands response:
int: The number of members that were removed from the sorted set.
If `key` does not exist, it is treated as an empty sorted set, and the command returns 0.
If `min_score` is greater than `max_score`, 0 is returned.
"""
score_min = (
min_score.value["score_arg"]
if type(min_score) == InfBound
else min_score.value
)
score_max = (
max_score.value["score_arg"]
if type(max_score) == InfBound
else max_score.value
)
return self.append_command(
RequestType.ZRemRangeByScore, [key, score_min, score_max]
)

def zscore(self: TTransaction, key: str, member: str) -> TTransaction:
"""
Returns the score of `member` in the sorted set stored at `key`.
Expand Down
28 changes: 28 additions & 0 deletions python/python/tests/test_async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,34 @@ async def test_zrem(self, redis_client: TRedisClient):

assert await redis_client.zrem("non_existing_set", ["member"]) == 0

@pytest.mark.parametrize("cluster_mode", [True, False])
@pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3])
async def test_zremrangebyscore(self, redis_client: TRedisClient):
key = get_random_string(10)
members_scores = {"one": 1, "two": 2, "three": 3}
assert await redis_client.zadd(key, members_scores) == 3

assert (
await redis_client.zremrangebyscore(
key, ScoreBoundary(1, False), ScoreBoundary(2)
)
== 1
)
assert (
await redis_client.zremrangebyscore(key, ScoreBoundary(1), InfBound.NEG_INF)
== 0
)
assert (
await redis_client.zremrangebyscore(
"non_existing_set", InfBound.NEG_INF, InfBound.POS_INF
)
== 0
)

assert await redis_client.set(key, "value") == OK
with pytest.raises(RequestError):
await redis_client.zremrangebyscore(key, InfBound.NEG_INF, InfBound.POS_INF)

@pytest.mark.parametrize("cluster_mode", [True, False])
@pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3])
async def test_zcard(self, redis_client: TRedisClient):
Expand Down
16 changes: 9 additions & 7 deletions python/python/tests/test_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ async def transaction_test(
transaction.sismember(key7, "bar")
args.append(True)

transaction.zadd(key8, {"one": 1, "two": 2, "three": 3})
args.append(3)
transaction.zadd(key8, {"one": 1, "two": 2, "three": 3, "four": 4})
args.append(4)
transaction.zrank(key8, "one")
args.append(0)
if not await check_if_server_version_lt(redis_client, "7.2.0"):
Expand All @@ -166,19 +166,21 @@ async def transaction_test(
transaction.zrem(key8, ["one"])
args.append(1)
transaction.zcard(key8)
args.append(2)
args.append(3)
transaction.zcount(key8, ScoreBoundary(2, is_inclusive=True), InfBound.POS_INF)
args.append(2)
args.append(3)
transaction.zscore(key8, "two")
args.append(2.0)
transaction.zrange(key8, RangeByIndex(start=0, stop=-1))
args.append(["two", "three"])
args.append(["two", "three", "four"])
transaction.zrange_withscores(key8, RangeByIndex(start=0, stop=-1))
args.append({"two": 2, "three": 3})
args.append({"two": 2, "three": 3, "four": 4})
transaction.zpopmin(key8)
args.append({"two": 2.0})
transaction.zpopmax(key8)
args.append({"three": 3})
args.append({"four": 4})
transaction.zremrangebyscore(key8, InfBound.NEG_INF, InfBound.POS_INF)
args.append(1)
return args


Expand Down

0 comments on commit f1d219c

Please sign in to comment.