From 0a233c1be517168d2aac2d068b7b65c6aac2c7cd Mon Sep 17 00:00:00 2001 From: Shoham Elias <116083498+shohamazon@users.noreply.github.com> Date: Tue, 13 Feb 2024 15:21:23 +0200 Subject: [PATCH] Python: adds TYPE command (#945) --- CHANGELOG.md | 1 + glide-core/src/protobuf/redis_request.proto | 1 + glide-core/src/socket_listener.rs | 1 + python/python/glide/async_commands/core.py | 20 +++++++++++++ .../glide/async_commands/transaction.py | 15 ++++++++++ python/python/tests/test_async_client.py | 30 +++++++++++++++++++ python/python/tests/test_transaction.py | 2 ++ 7 files changed, 70 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90a50a9f6b..10a3186bac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Python, Node: Added RPOPCOUNT and LPOPCOUNT to transaction ([#874](https://github.com/aws/glide-for-redis/pull/874)) * Standalone client: Improve connection errors. ([#854](https://github.com/aws/glide-for-redis/pull/854)) * Python, Node: When recieving LPOP/RPOP with count, convert result to Array. ([#811](https://github.com/aws/glide-for-redis/pull/811)) +* Python: Added TYPE command ([#945](https://github.com/aws/glide-for-redis/pull/945)) #### Features * Python, Node: Added support in Lua Scripts ([#775](https://github.com/aws/glide-for-redis/pull/775), [#860](https://github.com/aws/glide-for-redis/pull/860)) diff --git a/glide-core/src/protobuf/redis_request.proto b/glide-core/src/protobuf/redis_request.proto index 0f5d54eac6..c89654a47f 100644 --- a/glide-core/src/protobuf/redis_request.proto +++ b/glide-core/src/protobuf/redis_request.proto @@ -103,6 +103,7 @@ enum RequestType { Zcount = 65; ZIncrBy = 66; ZScore = 67; + Type = 68; } message Command { diff --git a/glide-core/src/socket_listener.rs b/glide-core/src/socket_listener.rs index 945d4131a9..7373827113 100644 --- a/glide-core/src/socket_listener.rs +++ b/glide-core/src/socket_listener.rs @@ -346,6 +346,7 @@ fn get_command(request: &Command) -> Option { RequestType::Zcount => Some(cmd("ZCOUNT")), RequestType::ZIncrBy => Some(cmd("ZINCRBY")), RequestType::ZScore => Some(cmd("ZSCORE")), + RequestType::Type => Some(cmd("TYPE")), } } diff --git a/python/python/glide/async_commands/core.py b/python/python/glide/async_commands/core.py index 4993aac2db..f8a86d6051 100644 --- a/python/python/glide/async_commands/core.py +++ b/python/python/glide/async_commands/core.py @@ -1100,6 +1100,26 @@ async def ttl(self, key: str) -> int: """ return cast(int, await self._execute_command(RequestType.TTL, [key])) + async def type(self, key: str) -> str: + """ + Returns the string representation of the type of the value stored at `key`. + + See https://redis.io/commands/type/ for more details. + + Args: + key (str): The key to check its data type. + + Returns: + str: If the key exists, the type of the stored value is returned. + Otherwise, a "none" string is returned. + + Examples: + >>> await client.set("key", "value") + >>> await client.type("key") + 'string' + """ + return cast(str, await self._execute_command(RequestType.Type, [key])) + async def zadd( self, key: str, diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index 37ad50c3d8..73ea272961 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -803,6 +803,21 @@ def ttl(self, key: str): """ self.append_command(RequestType.TTL, [key]) + def type(self, key: str): + """ + Returns the string representation of the type of the value stored at `key`. + + See https://redis.io/commands/type/ for more details. + + Args: + key (str): The key to check its data type. + + Commands response: + str: If the key exists, the type of the stored value is returned. + Otherwise, a "none" string is returned. + """ + self.append_command(RequestType.Type, [key]) + def zadd( self, key: str, diff --git a/python/python/tests/test_async_client.py b/python/python/tests/test_async_client.py index ffc0bca23e..1b87d9f19f 100644 --- a/python/python/tests/test_async_client.py +++ b/python/python/tests/test_async_client.py @@ -1174,6 +1174,36 @@ async def test_zscore(self, redis_client: TRedisClient): await redis_client.zscore("non_existing_key", "non_existing_member") == None ) + @pytest.mark.parametrize("cluster_mode", [True, False]) + @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) + async def test_type(self, redis_client: TRedisClient): + key = get_random_string(10) + assert await redis_client.set(key, "value") == OK + assert (await redis_client.type(key)).lower() == "string" + assert await redis_client.delete([key]) == 1 + + assert await redis_client.lpush(key, ["value"]) == 1 + assert (await redis_client.type(key)).lower() == "list" + assert await redis_client.delete([key]) == 1 + + assert await redis_client.sadd(key, ["value"]) == 1 + assert (await redis_client.type(key)).lower() == "set" + assert await redis_client.delete([key]) == 1 + + assert await redis_client.zadd(key, {"member": 1.0}) == 1 + assert (await redis_client.type(key)).lower() == "zset" + assert await redis_client.delete([key]) == 1 + + assert await redis_client.hset(key, {"field": "value"}) == 1 + assert (await redis_client.type(key)).lower() == "hash" + assert await redis_client.delete([key]) == 1 + + await redis_client.custom_command(["XADD", key, "*", "field", "value"]) + assert await redis_client.type(key) == "stream" + assert await redis_client.delete([key]) == 1 + + assert (await redis_client.type(key)).lower() == "none" + class TestCommandsUnitTests: def test_expiry_cmd_args(self): diff --git a/python/python/tests/test_transaction.py b/python/python/tests/test_transaction.py index 4840f94399..1248053199 100644 --- a/python/python/tests/test_transaction.py +++ b/python/python/tests/test_transaction.py @@ -35,6 +35,7 @@ def transaction_test( transaction.set(key, value) transaction.get(key) + transaction.type(key) transaction.exists([key]) @@ -98,6 +99,7 @@ def transaction_test( return [ OK, value, + "string", 1, 1, None,