Skip to content

Commit

Permalink
Python: adds SISMEMBER command (valkey-io#972)
Browse files Browse the repository at this point in the history
  • Loading branch information
shohamazon authored Feb 29, 2024
1 parent 9eddc1e commit 3809a28
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 4 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 @@

- Node: Allow routing Cluster requests by address. ([#1021](https://github.com/aws/glide-for-redis/pull/1021))
* Python: Added HSETNX command. ([#954](https://github.com/aws/glide-for-redis/pull/954))
* Python: Added SISMEMBER command ([#971](https://github.com/aws/glide-for-redis/pull/971))

## 0.2.0 (2024-02-11)

Expand All @@ -16,7 +17,7 @@
* Python, Node: When recieving LPOP/RPOP with count, convert result to Array. ([#811](https://github.com/aws/glide-for-redis/pull/811))
* Python, Node: Added TYPE command ([#945](https://github.com/aws/glide-for-redis/pull/945), [#980](https://github.com/aws/glide-for-redis/pull/980))
* Python, Node: Added HLEN command ([#944](https://github.com/aws/glide-for-redis/pull/944), [#981](https://github.com/aws/glide-for-redis/pull/981))
* Node: Added ZCOUNT command ([#909](https://github.com/aws/glide-for-redis/pull/909))
* Python, Node: Added ZCOUNT command ([#878](https://github.com/aws/glide-for-redis/pull/878)) ([#909](https://github.com/aws/glide-for-redis/pull/909))
* Python: Added ECHO command ([#953](https://github.com/aws/glide-for-redis/pull/953))
* Python, Node: Added ZPOPMIN command ([#975](https://github.com/aws/glide-for-redis/pull/975), [#1008](https://github.com/aws/glide-for-redis/pull/1008))
* Node: Added STRLEN command ([#993](https://github.com/aws/glide-for-redis/pull/993))
Expand Down
5 changes: 2 additions & 3 deletions glide-core/src/client/value_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,8 @@ pub(crate) fn expected_type_for_cmd(cmd: &Cmd) -> Option<ExpectedReturnType> {
Some(ExpectedReturnType::Map)
}
b"INCRBYFLOAT" | b"HINCRBYFLOAT" => Some(ExpectedReturnType::Double),
b"HEXISTS" | b"HSETNX" | b"EXPIRE" | b"EXPIREAT" | b"PEXPIRE" | b"PEXPIREAT" => {
Some(ExpectedReturnType::Boolean)
}
b"HEXISTS" | b"HSETNX" | b"EXPIRE" | b"EXPIREAT" | b"PEXPIRE" | b"PEXPIREAT"
| b"SISMEMBER" => Some(ExpectedReturnType::Boolean),
b"SMEMBERS" => Some(ExpectedReturnType::Set),
b"ZSCORE" => Some(ExpectedReturnType::DoubleOrNull),
b"ZPOPMIN" | b"ZPOPMAX" => Some(ExpectedReturnType::MapOfStringToDouble),
Expand Down
1 change: 1 addition & 0 deletions glide-core/src/protobuf/redis_request.proto
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ enum RequestType {
XGroupCreate = 80;
XGroupDestroy = 81;
HSetNX = 82;
SIsMember = 83;
}

message Command {
Expand Down
1 change: 1 addition & 0 deletions glide-core/src/socket_listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ fn get_command(request: &Command) -> Option<Cmd> {
RequestType::XGroupDestroy => Some(get_two_word_command("XGROUP", "DESTROY")),
RequestType::XTrim => Some(cmd("XTRIM")),
RequestType::HSetNX => Some(cmd("HSETNX")),
RequestType::SIsMember => Some(cmd("SISMEMBER")),
}
}

Expand Down
29 changes: 29 additions & 0 deletions python/python/glide/async_commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,35 @@ async def scard(self, key: str) -> int:
"""
return cast(int, await self._execute_command(RequestType.SCard, [key]))

async def sismember(
self,
key: str,
member: str,
) -> bool:
"""
Returns if `member` is a member of the set stored at `key`.
See https://redis.io/commands/sismember/ for more details.
Args:
key (str): The key of the set.
member (str): The member to check for existence in the set.
Returns:
bool: True if the member exists in the set, False otherwise.
If `key` doesn't exist, it is treated as an empty set and the command returns False.
Examples:
>>> await client.sismember("my_set", "member1")
True # Indicates that "member1" exists in the set "my_set".
>>> await client.sismember("my_set", "non_existing_member")
False # Indicates that "non_existing_member" does not exist in the set "my_set".
"""
return cast(
bool,
await self._execute_command(RequestType.SIsMember, [key, member]),
)

async def ltrim(self, key: str, start: int, end: int) -> TOK:
"""
Trim an existing list so that it will contain only the specified range of elements specified.
Expand Down
20 changes: 20 additions & 0 deletions python/python/glide/async_commands/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,26 @@ def scard(self: TTransaction, key: str) -> TTransaction:
"""
return self.append_command(RequestType.SCard, [key])

def sismember(
self: TTransaction,
key: str,
member: str,
) -> TTransaction:
"""
Returns if `member` is a member of the set stored at `key`.
See https://redis.io/commands/sismember/ for more details.
Args:
key (str): The key of the set.
member (str): The member to check for existence in the set.
Commands response:
bool: True if the member exists in the set, False otherwise.
If `key` doesn't exist, it is treated as an empty set and the command returns False.
"""
return self.append_command(RequestType.SIsMember, [key, member])

def ltrim(self: TTransaction, key: str, start: int, end: int) -> TTransaction:
"""
Trim an existing list so that it will contain only the specified range of elements specified.
Expand Down
10 changes: 10 additions & 0 deletions python/python/tests/test_async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,16 @@ async def test_sadd_srem_smembers_scard_wrong_type_raise_error(
await redis_client.smembers(key)
assert "Operation against a key holding the wrong kind of value" in str(e)

@pytest.mark.parametrize("cluster_mode", [True, False])
@pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3])
async def test_sismember(self, redis_client: TRedisClient):
key = get_random_string(10)
member = get_random_string(5)
assert await redis_client.sadd(key, [member]) == 1
assert await redis_client.sismember(key, member)
assert not await redis_client.sismember(key, get_random_string(5))
assert not await redis_client.sismember("non_existing_key", member)

@pytest.mark.parametrize("cluster_mode", [True, False])
@pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3])
async def test_ltrim(self, redis_client: TRedisClient):
Expand Down
2 changes: 2 additions & 0 deletions python/python/tests/test_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ def transaction_test(
args.append({"bar"})
transaction.scard(key7)
args.append(1)
transaction.sismember(key7, "bar")
args.append(True)

transaction.zadd(key8, {"one": 1, "two": 2, "three": 3})
args.append(3)
Expand Down

0 comments on commit 3809a28

Please sign in to comment.