From b7038b5361fc28bb4eed27b0935eff5e4a1bad5f Mon Sep 17 00:00:00 2001 From: Shoham Elias Date: Thu, 13 Jun 2024 14:21:51 +0000 Subject: [PATCH] Python: adds HSTRLEN command --- CHANGELOG.md | 1 + python/python/glide/async_commands/core.py | 25 ++++++++++++++++++- .../glide/async_commands/transaction.py | 15 +++++++++++ python/python/tests/test_async_client.py | 15 +++++++++++ python/python/tests/test_transaction.py | 2 ++ 5 files changed, 57 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd15282fbd..f850ddca0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ * Node: Added XLEN command ([#1555](https://github.com/aws/glide-for-redis/pull/1555)) * Node: Added ZINTERCARD command ([#1553](https://github.com/aws/glide-for-redis/pull/1553)) * Python: Added LMPOP and BLMPOP commands ([#1547](https://github.com/aws/glide-for-redis/pull/1547)) +* Python: Added HSTRLEN command ([#1564](https://github.com/aws/glide-for-redis/pull/1564)) ### Breaking Changes * Node: Update XREAD to return a Map of Map ([#1494](https://github.com/aws/glide-for-redis/pull/1494)) diff --git a/python/python/glide/async_commands/core.py b/python/python/glide/async_commands/core.py index 8f5bd5f192..5bb53c8938 100644 --- a/python/python/glide/async_commands/core.py +++ b/python/python/glide/async_commands/core.py @@ -838,7 +838,7 @@ async def hget(self, key: str, field: str) -> Optional[str]: Returns None if `field` is not presented in the hash or `key` does not exist. Examples: - >>> await client.hset("my_hash", "field") + >>> await client.hset("my_hash", "field", "value") >>> await client.hget("my_hash", "field") "value" >>> await client.hget("my_hash", "nonexistent_field") @@ -1152,6 +1152,29 @@ async def hrandfield_withvalues(self, key: str, count: int) -> List[List[str]]: ), ) + async def hstrlen(self, key: str, field: str) -> int: + """ + Returns the string length of the value associated with `field` in the hash stored at `key`. + + See https://valkey.io/commands/hstrlen/ for more details. + + Args: + key (str): The key of the hash. + field (str): The field in the hash. + + Returns: + int: The string length or 0 if `field` or `key` does not exist. + + Examples: + >>> await client.hset("my_hash", "field", "value") + >>> await client.hstrlen("my_hash", "my_field") + 5 + """ + return cast( + int, + await self._execute_command(RequestType.HStrlen, [key, field]), + ) + async def lpush(self, key: str, elements: List[str]) -> int: """ Insert all the specified values at the head of the list stored at `key`. diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index 7204bf10c7..9f4f5b9d95 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -718,6 +718,21 @@ def hrandfield_withvalues(self: TTransaction, key: str, count: int) -> TTransact RequestType.HRandField, [key, str(count), "WITHVALUES"] ) + def hstrlen(self: TTransaction, key: str, field: str) -> TTransaction: + """ + Returns the string length of the value associated with `field` in the hash stored at `key`. + + See https://valkey.io/commands/hstrlen/ for more details. + + Args: + key (str): The key of the hash. + field (str): The field in the hash. + + Commands response: + int: The string length or 0 if `field` or `key` does not exist. + """ + return self.append_command(RequestType.HStrlen, [key, field]) + def lpush(self: TTransaction, key: str, elements: List[str]) -> TTransaction: """ Insert all the specified values at the head of the list stored at `key`. diff --git a/python/python/tests/test_async_client.py b/python/python/tests/test_async_client.py index 45d7865087..1ce17cd366 100644 --- a/python/python/tests/test_async_client.py +++ b/python/python/tests/test_async_client.py @@ -865,6 +865,21 @@ async def test_hrandfield_withvalues(self, redis_client: TRedisClient): with pytest.raises(RequestError): await redis_client.hrandfield_withvalues(key2, 5) + @pytest.mark.parametrize("cluster_mode", [True, False]) + @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) + async def test_hstrlen(self, redis_client: TRedisClient): + key = get_random_string(10) + + assert await redis_client.hstrlen(key, "field") == 0 + assert await redis_client.hset(key, {"field": "value"}) == 1 + assert await redis_client.hstrlen(key, "field") == 5 + + assert await redis_client.hstrlen(key, "field2") == 0 + + await redis_client.set(key, "value") + with pytest.raises(RequestError): + await redis_client.hstrlen(key, "field") + @pytest.mark.parametrize("cluster_mode", [True, False]) @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_lpush_lpop_lrange(self, redis_client: TRedisClient): diff --git a/python/python/tests/test_transaction.py b/python/python/tests/test_transaction.py index 1d753658e3..eac3e8e032 100644 --- a/python/python/tests/test_transaction.py +++ b/python/python/tests/test_transaction.py @@ -164,6 +164,8 @@ async def transaction_test( args.append([key3]) transaction.hrandfield_withvalues(key4, 1) args.append([[key3, "10.5"]]) + transaction.hstrlen(key4, key3) + args.append(4) transaction.client_getname() args.append(None)