From 7100a0216ca13121289cd97be29af22a52f0908d Mon Sep 17 00:00:00 2001 From: GilboaAWS Date: Wed, 22 May 2024 13:49:51 +0000 Subject: [PATCH 01/24] Adds sort command to python --- glide-core/src/protobuf/redis_request.proto | 1 + glide-core/src/request_type.rs | 3 + python/python/glide/__init__.py | 2 + .../glide/async_commands/cluster_commands.py | 83 +++++++++++- python/python/glide/async_commands/core.py | 45 +++++++ .../async_commands/standalone_commands.py | 99 ++++++++++++++- .../glide/async_commands/transaction.py | 119 ++++++++++++++++++ python/python/tests/test_async_client.py | 113 +++++++++++++++++ python/python/tests/test_transaction.py | 45 ++++++- 9 files changed, 502 insertions(+), 8 deletions(-) diff --git a/glide-core/src/protobuf/redis_request.proto b/glide-core/src/protobuf/redis_request.proto index 886ab27d21..ae13004920 100644 --- a/glide-core/src/protobuf/redis_request.proto +++ b/glide-core/src/protobuf/redis_request.proto @@ -195,6 +195,7 @@ enum RequestType { PExpireTime = 157; BLMPop = 158; XLen = 159; + Sort = 160; LSet = 165; XDel = 166; XRange = 167; diff --git a/glide-core/src/request_type.rs b/glide-core/src/request_type.rs index eb2292098f..70ef9d80ae 100644 --- a/glide-core/src/request_type.rs +++ b/glide-core/src/request_type.rs @@ -165,6 +165,7 @@ pub enum RequestType { PExpireTime = 157, BLMPop = 158, XLen = 159, + Sort = 160, LSet = 165, XDel = 166, XRange = 167, @@ -349,6 +350,7 @@ impl From<::protobuf::EnumOrUnknown> for RequestType { ProtobufRequestType::GetDel => RequestType::GetDel, ProtobufRequestType::SRandMember => RequestType::SRandMember, ProtobufRequestType::SInterCard => RequestType::SInterCard, + ProtobufRequestType::Sort => RequestType::Sort, } } } @@ -521,6 +523,7 @@ impl RequestType { RequestType::GetDel => Some(cmd("GETDEL")), RequestType::SRandMember => Some(cmd("SRANDMEMBER")), RequestType::SInterCard => Some(cmd("SINTERCARD")), + RequestType::Sort => Some(cmd("SORT")), } } } diff --git a/python/python/glide/__init__.py b/python/python/glide/__init__.py index 8928249303..a8929e428e 100644 --- a/python/python/glide/__init__.py +++ b/python/python/glide/__init__.py @@ -14,6 +14,7 @@ TrimByMaxLen, TrimByMinId, UpdateOptions, + SortOrder, ) from glide.async_commands.redis_modules import json from glide.async_commands.sorted_set import ( @@ -107,6 +108,7 @@ "TrimByMaxLen", "TrimByMinId", "UpdateOptions", + "SortOrder", # Logger "Logger", "LogLevel", diff --git a/python/python/glide/async_commands/cluster_commands.py b/python/python/glide/async_commands/cluster_commands.py index 872b4d12a4..71707e8144 100644 --- a/python/python/glide/async_commands/cluster_commands.py +++ b/python/python/glide/async_commands/cluster_commands.py @@ -2,9 +2,14 @@ from __future__ import annotations -from typing import Dict, List, Mapping, Optional, cast - -from glide.async_commands.core import CoreCommands, InfoSection +from typing import Dict, List, Mapping, Optional, cast, Tuple + +from glide.async_commands.core import ( + CoreCommands, + InfoSection, + SortOrder, + _build_sort_args, +) from glide.async_commands.transaction import BaseTransaction, ClusterTransaction from glide.constants import TOK, TClusterResponse, TResult, TSingleNodeRoute from glide.protobuf.redis_request_pb2 import RequestType @@ -367,3 +372,75 @@ async def lastsave(self, route: Optional[Route] = None) -> TClusterResponse[int] TClusterResponse[int], await self._execute_command(RequestType.LastSave, [], route), ) + + async def sort( + self, + key: str, + limit: Optional[Tuple[int, int]] = None, + order: Optional[SortOrder] = None, + alpha: Optional[bool] = None, + ) -> List[Optional[str]]: + """ + Sorts the elements in the list, set, or sorted set at `key` and returns the result. + To store the result into a new key, see `sort_store`. + + see https://valkey-io.github.io/commands/sort/ for more details. + + Args: + key (str): The key of the list, set, or sorted set to be sorted. + limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. + order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + + Returns: + List[Optional[str]]: Returns a list of sorted elements. + + Examples: + >>> await client.lpush("mylist", 3, 1, 2) + >>> await client.sort("mylist") + ['1', '2', '3'] + >>> await client.sort("mylist", order=SortOrder.DESC) + ['3', '2', '1'] + >>> await client.lpush("mylist", 2, 1, 2, 3, 3, 1) + >>> await client.sort("mylist", limit=(2, 3)) + ['2', '2', '3'] + """ + args = _build_sort_args(key, None, limit, None, order, alpha) + result = await self._execute_command(RequestType.Sort, args) + return cast(List[Optional[str]], result) + + async def sort_store( + self, + key: str, + store: str, + limit: Optional[Tuple[int, int]] = None, + order: Optional[SortOrder] = None, + alpha: Optional[bool] = None, + ) -> int: + """ + Sorts the elements in the list, set, or sorted set at `key` and stores the result in `store`. + When in cluster mode, `key` and `store` must map to the same hash slot. + To get the sort result, see `sort`. + + see https://valkey-io.github.io/commands/sort/ for more details. + + Args: + key (str): The key of the list, set, or sorted set to be sorted. + store (str): The key where the sorted result will be stored. + limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. + order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + + Returns: + int: The number of elements in the sorted key stored at `store`. + + Examples: + >>> await client.lpush("mylist", 3, 1, 2) + >>> await client.sort_store("mylist", "sorted_list") + 3 # Indicates that the sorted list "sorted_list" contains three elements. + >>> await client.lrange("sorted_list", 0, -1) + ['1', '2', '3'] + """ + args = _build_sort_args(key, None, limit, None, order, alpha, store=store) + result = await self._execute_command(RequestType.Sort, args) + return cast(int, result) diff --git a/python/python/glide/async_commands/core.py b/python/python/glide/async_commands/core.py index 5ea9aa1a6d..11d458b3bd 100644 --- a/python/python/glide/async_commands/core.py +++ b/python/python/glide/async_commands/core.py @@ -135,6 +135,18 @@ class UpdateOptions(Enum): GREATER_THAN = "GT" +class SortOrder(Enum): + """ + SORT order options: options for sorting elements. + + - ASC: Sort in ascending order. + - DESC: Sort in descending order. + """ + + ASC = "ASC" + DESC = "DESC" + + class GeospatialData: def __init__(self, longitude: float, latitude: float): """ @@ -361,6 +373,39 @@ class InsertPosition(Enum): AFTER = "AFTER" +def _build_sort_args( + key: str, + by_pattern: Optional[str] = None, + limit: Optional[Tuple[int, int]] = None, + get_patterns: Optional[List[str]] = None, + order: Optional[SortOrder] = None, + alpha: Optional[bool] = None, + store: Optional[str] = None, +) -> List[str]: + args = [key] + + if by_pattern: + args.extend(["BY", by_pattern]) + + if limit: + args.extend(["LIMIT", str(limit[0]), str(limit[1])]) + + if get_patterns: + for pattern in get_patterns: + args.extend(["GET", pattern]) + + if order: + args.append(order.value) + + if alpha: + args.append("ALPHA") + + if store: + args.extend(["STORE", store]) + + return args + + class CoreCommands(Protocol): async def _execute_command( self, diff --git a/python/python/glide/async_commands/standalone_commands.py b/python/python/glide/async_commands/standalone_commands.py index 83a99a2b8a..deef2f0622 100644 --- a/python/python/glide/async_commands/standalone_commands.py +++ b/python/python/glide/async_commands/standalone_commands.py @@ -2,9 +2,14 @@ from __future__ import annotations -from typing import Dict, List, Mapping, Optional, cast - -from glide.async_commands.core import CoreCommands, InfoSection +from typing import Dict, List, Mapping, Optional, cast, Tuple + +from glide.async_commands.core import ( + CoreCommands, + InfoSection, + SortOrder, + _build_sort_args, +) from glide.async_commands.transaction import BaseTransaction, Transaction from glide.constants import TOK, TResult from glide.protobuf.redis_request_pb2 import RequestType @@ -264,3 +269,91 @@ async def lastsave(self) -> int: int, await self._execute_command(RequestType.LastSave, []), ) + + async def sort( + self, + key: str, + by_pattern: Optional[str] = None, + limit: Optional[Tuple[int, int]] = None, + get_patterns: Optional[List[str]] = None, + order: Optional[SortOrder] = None, + alpha: Optional[bool] = None, + ) -> List[Optional[str]]: + """ + Sorts the elements in the list, set, or sorted set at `key` and returns the result. + The `sort` command can be used to sort elements based on different criteria and apply transformations on sorted elements. + To store the result into a new key, see `sort_store`. + + see https://valkey-io.github.io/commands/sort/ for more details. + + Args: + key (str): The key of the list, set, or sorted set to be sorted. + by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. + limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. + get_patterns (Optional[List[str]]): One or more patterns to extract values to return. + order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + + Returns: + List[Optional[str]]: Returns a list of sorted elements. + + Examples: + >>> await client.lpush("mylist", 3, 1, 2) + >>> await client.sort("mylist") + ['1', '2', '3'] + >>> await client.sort("mylist", order=SortOrder.DESC) + ['3', '2', '1'] + >>> await client.lpush("mylist", 2, 1, 2, 3, 3, 1) + >>> await client.sort("mylist", limit=(2, 3)) + ['2', '2', '3'] + >>> await client.hset("user:1", "name", "Alice", "age", 30) + >>> await client.hset("user:2", "name", "Bob", "age", 25) + >>> await client.lpush("user_ids", 2, 1) + >>> await client.sort("user_ids", by_pattern="user:*->age", get_patterns=["user:*->name"]) + ['Bob', 'Alice'] + """ + args = _build_sort_args(key, by_pattern, limit, get_patterns, order, alpha) + result = await self._execute_command(RequestType.Sort, args) + return cast(List[Optional[str]], result) + + async def sort_store( + self, + key: str, + store: str, + by_pattern: Optional[str] = None, + limit: Optional[Tuple[int, int]] = None, + get_patterns: Optional[List[str]] = None, + order: Optional[SortOrder] = None, + alpha: Optional[bool] = None, + ) -> int: + """ + Sorts the elements in the list, set, or sorted set at `key` and stores the result in `store`. + The `sort` command can be used to sort elements based on different criteria, apply transformations on sorted elements, and store the result in a new key. + To get the sort result, see `sort`. + + see https://valkey-io.github.io/commands/sort/ for more details. + + Args: + key (str): The key of the list, set, or sorted set to be sorted. + store (str): The key where the sorted result will be stored. + by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. + limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. + get_patterns (Optional[List[str]]): One or more patterns to extract values to return. + order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + + Returns: + int: The number of elements in the sorted key stored at `store`. + + Examples: + >>> await client.lpush("mylist", 3, 1, 2) + >>> await client.sort_store("mylist", "sorted_list") + 3 # Indicates that the sorted list "sorted_list" contains three elements. + >>> await client.lrange("sorted_list", 0, -1) + ['1', '2', '3'] + """ + args = _build_sort_args( + key, by_pattern, limit, get_patterns, order, alpha, store=store + ) + result = await self._execute_command(RequestType.Sort, args) + return cast(int, result) diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index c5d4e3949e..5e3b1c95a3 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -14,6 +14,8 @@ StreamAddOptions, StreamTrimOptions, UpdateOptions, + SortOrder, + _build_sort_args, ) from glide.async_commands.sorted_set import ( AggregationType, @@ -2745,6 +2747,70 @@ def select(self, index: int) -> "Transaction": """ return self.append_command(RequestType.Select, [str(index)]) + def sort( + self: TTransaction, + key: str, + by_pattern: Optional[str] = None, + limit: Optional[Tuple[int, int]] = None, + get_patterns: Optional[List[str]] = None, + order: Optional[SortOrder] = None, + alpha: Optional[bool] = None, + ) -> TTransaction: + """ + Sorts the elements in the list, set, or sorted set at `key` and returns the result. + The `sort` command can be used to sort elements based on different criteria and apply transformations on sorted elements. + To store the result into a new key, see `sort_store`. + + see https://valkey-io.github.io/commands/sort/ for more details. + + Args: + key (str): The key of the list, set, or sorted set to be sorted. + by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. + limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. + get_patterns (Optional[List[str]]): One or more patterns to extract values to return. + order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + + Command response: + List[Optional[str]]: Returns a list of sorted elements. + """ + args = _build_sort_args(key, by_pattern, limit, get_patterns, order, alpha) + return self.append_command(RequestType.Sort, args) + + def sort_store( + self: TTransaction, + key: str, + store: str, + by_pattern: Optional[str] = None, + limit: Optional[Tuple[int, int]] = None, + get_patterns: Optional[List[str]] = None, + order: Optional[SortOrder] = None, + alpha: Optional[bool] = None, + ) -> TTransaction: + """ + Sorts the elements in the list, set, or sorted set at `key` and stores the result in `store`. + The `sort` command can be used to sort elements based on different criteria, apply transformations on sorted elements, and store the result in a new key. + To get the sort result, see `sort`. + + see https://valkey-io.github.io/commands/sort/ for more details. + + Args: + key (str): The key of the list, set, or sorted set to be sorted. + store (str): The key where the sorted result will be stored. + by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. + limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. + get_patterns (Optional[List[str]]): One or more patterns to extract values to return. + order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + + Command response: + int: The number of elements in the sorted key stored at `store`. + """ + args = _build_sort_args( + key, by_pattern, limit, get_patterns, order, alpha, store=store + ) + return self.append_command(RequestType.Sort, args) + class ClusterTransaction(BaseTransaction): """ @@ -2755,5 +2821,58 @@ class ClusterTransaction(BaseTransaction): are documented alongside each method. """ + def sort( + self, + key: str, + limit: Optional[Tuple[int, int]] = None, + order: Optional[SortOrder] = None, + alpha: Optional[bool] = None, + ) -> List[Optional[str]]: + """ + Sorts the elements in the list, set, or sorted set at `key` and returns the result. + To store the result into a new key, see `sort_store`. + + see https://valkey-io.github.io/commands/sort/ for more details. + + Args: + key (str): The key of the list, set, or sorted set to be sorted. + limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. + order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + + Command response: + List[Optional[str]]: A list of sorted elements. + """ + args = _build_sort_args(key, None, limit, None, order, alpha) + return self.append_command(RequestType.Sort, args) + + def sort_store( + self, + key: str, + store: str, + limit: Optional[Tuple[int, int]] = None, + order: Optional[SortOrder] = None, + alpha: Optional[bool] = None, + ) -> int: + """ + Sorts the elements in the list, set, or sorted set at `key` and stores the result in `store`. + When in cluster mode, `key` and `store` must map to the same hash slot. + To get the sort result, see `sort`. + + see https://valkey-io.github.io/commands/sort/ for more details. + + Args: + key (str): The key of the list, set, or sorted set to be sorted. + store (str): The key where the sorted result will be stored. + limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. + order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + + Command response: + int: The number of elements in the sorted key stored at `store`. + """ + args = _build_sort_args(key, None, limit, None, order, alpha, store=store) + return self.append_command(RequestType.Sort, args) + # TODO: add all CLUSTER commands pass diff --git a/python/python/tests/test_async_client.py b/python/python/tests/test_async_client.py index bd1a51366a..2c4e7806b4 100644 --- a/python/python/tests/test_async_client.py +++ b/python/python/tests/test_async_client.py @@ -25,6 +25,7 @@ TrimByMaxLen, TrimByMinId, UpdateOptions, + SortOrder, ) from glide.async_commands.sorted_set import ( AggregationType, @@ -3416,6 +3417,117 @@ async def test_type(self, redis_client: TRedisClient): assert (await redis_client.type(key)).lower() == "none" + @pytest.mark.parametrize("cluster_mode", [False]) + @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) + async def test_sort_and_sort_store_with_get_or_by_args( + self, redis_client: TRedisClient + ): + key = "{SameSlotKey}" + get_random_string(10) + store = "{SameSlotKey}" + get_random_string(10) + user_key1, user_key2, user_key3, user_key4, user_key5 = ( + "user:1", + "user:2", + "user:3", + "user:4", + "user:5", + ) + + # Prepare some data + assert await redis_client.hset(user_key1, {"name": "Alice", "age": "30"}) == 2 + assert await redis_client.hset(user_key2, {"name": "Bob", "age": "25"}) == 2 + assert await redis_client.hset(user_key3, {"name": "Charlie", "age": "35"}) == 2 + assert await redis_client.hset(user_key4, {"name": "Dave", "age": "20"}) == 2 + assert await redis_client.hset(user_key5, {"name": "Eve", "age": "40"}) == 2 + assert await redis_client.lpush("user_ids", ["5", "4", "3", "2", "1"]) == 5 + + # Test sort with all arguments + assert await redis_client.lpush(key, ["3", "1", "2"]) == 3 + result = await redis_client.sort( + key, + limit=(0, 2), + get_patterns=["user:*->name"], + order=SortOrder.ASC, + alpha=True, + ) + assert result == ["Alice", "Bob"] + + # Test sort_store with all arguments + result = await redis_client.sort_store( + key, + store, + limit=(0, 2), + get_patterns=["user:*->name"], + order=SortOrder.ASC, + alpha=True, + ) + assert result == 2 + sorted_list = await redis_client.lrange(store, 0, -1) + assert sorted_list == ["Alice", "Bob"] + + # Test sort with `by` argument + result = await redis_client.sort( + "user_ids", + by_pattern="user:*->age", + get_patterns=["user:*->name"], + alpha=True, + ) + assert result == ["Dave", "Bob", "Alice", "Charlie", "Eve"] + + @pytest.mark.parametrize("cluster_mode", [True, False]) + @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) + async def test_sort_and_sort_store_without_get_or_by_args( + self, redis_client: TRedisClient + ): + key = "{SameSlotKey}" + get_random_string(10) + store = "{SameSlotKey}" + get_random_string(10) + + # Test sort with non-existing key + result = await redis_client.sort("non_existing_key") + assert result == [] + + # Test sort_store with non-existing key + result = await redis_client.sort_store("{SameSlotKey}:non_existing_key", store) + assert result == 0 + + # Test each argument separately + assert await redis_client.lpush(key, ["5", "2", "4", "1", "3"]) == 5 + + # by_pattern argument + result = await redis_client.sort(key) + assert result == ["1", "2", "3", "4", "5"] + + # limit argument + result = await redis_client.sort(key, limit=(1, 3)) + assert result == ["2", "3", "4"] + + # order argument + result = await redis_client.sort(key, order=SortOrder.DESC) + assert result == ["5", "4", "3", "2", "1"] + + assert await redis_client.lpush(key, ["a"]) == 6 + + with pytest.raises(RequestError) as e: + await redis_client.sort(key) + assert "can't be converted into double" in str(e).lower() + + # alpha argument + result = await redis_client.sort(key, alpha=True) + assert result == ["1", "2", "3", "4", "5", "a"] + + # Combining multiple arguments + result = await redis_client.sort( + key, limit=(1, 3), order=SortOrder.DESC, alpha=True + ) + assert result == ["5", "4", "3"] + + # Test sort_store with combined arguments + result = await redis_client.sort_store( + key, store, limit=(1, 3), order=SortOrder.DESC, alpha=True + ) + assert result == 3 + sorted_list = await redis_client.lrange(store, 0, -1) + assert sorted_list == ["5", "4", "3"] + @pytest.mark.parametrize("cluster_mode", [True, False]) @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_echo(self, redis_client: TRedisClient): @@ -3791,6 +3903,7 @@ async def test_multi_key_command_returns_cross_slot_error( redis_client.zinter_withscores(["def", "ghi"]), redis_client.zunion(["def", "ghi"]), redis_client.zunion_withscores(["def", "ghi"]), + redis_client.sort_store("abc", "zxy"), ] if not await check_if_server_version_lt(redis_client, "7.0.0"): diff --git a/python/python/tests/test_transaction.py b/python/python/tests/test_transaction.py index 3891c97b28..57a5b7a3a8 100644 --- a/python/python/tests/test_transaction.py +++ b/python/python/tests/test_transaction.py @@ -9,6 +9,7 @@ from glide.async_commands.core import ( GeospatialData, InsertPosition, + SortOrder, StreamAddOptions, TrimByMinId, ) @@ -53,6 +54,8 @@ async def transaction_test( key14 = "{{{}}}:{}".format(keyslot, get_random_string(3)) # sorted set key15 = "{{{}}}:{}".format(keyslot, get_random_string(3)) # sorted set key16 = "{{{}}}:{}".format(keyslot, get_random_string(3)) # sorted set + key17 = "{{{}}}:{}".format(keyslot, get_random_string(3)) # sort + key18 = "{{{}}}:{}".format(keyslot, get_random_string(3)) # sort value = datetime.now(timezone.utc).strftime("%m/%d/%Y, %H:%M:%S") value2 = get_random_string(5) @@ -362,6 +365,24 @@ async def transaction_test( transaction.xtrim(key11, TrimByMinId(threshold="0-2", exact=True)) args.append(1) + transaction.lpush(key17, ["2", "1", "4", "3", "a"]) + args.append(5) + transaction.sort( + key17, + limit=(1, 4), + order=SortOrder.ASC, + alpha=True, + ) + args.append(["2", "3", "4", "a"]) + transaction.sort_store( + key17, + key18, + limit=(1, 4), + order=SortOrder.ASC, + alpha=True, + ) + args.append(4) + min_version = "7.0.0" if not await check_if_server_version_lt(redis_client, min_version): transaction.zadd(key16, {"a": 1, "b": 2, "c": 3, "d": 4}) @@ -496,12 +517,31 @@ async def test_standalone_transaction(self, redis_client: RedisClient): assert await redis_client.custom_command(["FLUSHALL"]) == OK keyslot = get_random_string(3) key = "{{{}}}:{}".format(keyslot, get_random_string(3)) # to get the same slot + key1 = "{{{}}}:{}".format(keyslot, get_random_string(3)) # to get the same slot value = get_random_string(5) transaction = Transaction() transaction.info() transaction.select(1) transaction.set(key, value) transaction.get(key) + transaction.hset("user:1", {"name": "Alice", "age": "30"}) + transaction.hset("user:2", {"name": "Bob", "age": "25"}) + transaction.lpush(key1, ["2", "1"]) + transaction.sort( + key1, + by_pattern="user:*->age", + get_patterns=["user:*->name"], + order=SortOrder.ASC, + alpha=True, + ) + transaction.sort_store( + key1, + "newSortedKey", + by_pattern="user:*->age", + get_patterns=["user:*->name"], + order=SortOrder.ASC, + alpha=True, + ) transaction.select(0) transaction.get(key) expected = await transaction_test(transaction, keyslot, redis_client) @@ -509,8 +549,9 @@ async def test_standalone_transaction(self, redis_client: RedisClient): assert isinstance(result, list) assert isinstance(result[0], str) assert "# Memory" in result[0] - assert result[1:6] == [OK, OK, value, OK, None] - assert result[6:] == expected + assert result[1:4] == [OK, OK, value] + assert result[4:11] == [2, 2, 2, ["Bob", "Alice"], 2, OK, None] + assert result[11:] == expected def test_transaction_clear(self): transaction = Transaction() From 200724280c9b5348c729754260aa007b76ca1161 Mon Sep 17 00:00:00 2001 From: GilboaAWS Date: Sun, 26 May 2024 07:48:30 +0000 Subject: [PATCH 02/24] addressed `Run isort . --profile black --check --diff` --- python/python/glide/__init__.py | 4 +- .../glide/async_commands/cluster_commands.py | 2 +- python/python/glide/async_commands/core.py | 10 ++- .../async_commands/standalone_commands.py | 2 +- .../glide/async_commands/transaction.py | 10 +-- python/python/tests/test_async_client.py | 75 ++++++++++--------- 6 files changed, 55 insertions(+), 48 deletions(-) diff --git a/python/python/glide/__init__.py b/python/python/glide/__init__.py index a8929e428e..b9e587c0e4 100644 --- a/python/python/glide/__init__.py +++ b/python/python/glide/__init__.py @@ -9,12 +9,12 @@ GeoUnit, InfoSection, InsertPosition, + SortOrder, StreamAddOptions, StreamTrimOptions, TrimByMaxLen, TrimByMinId, UpdateOptions, - SortOrder, ) from glide.async_commands.redis_modules import json from glide.async_commands.sorted_set import ( @@ -103,12 +103,12 @@ "RangeByLex", "RangeByScore", "ScoreFilter", + "SortOrder", "StreamAddOptions", "StreamTrimOptions", "TrimByMaxLen", "TrimByMinId", "UpdateOptions", - "SortOrder", # Logger "Logger", "LogLevel", diff --git a/python/python/glide/async_commands/cluster_commands.py b/python/python/glide/async_commands/cluster_commands.py index 71707e8144..4f69d6ea46 100644 --- a/python/python/glide/async_commands/cluster_commands.py +++ b/python/python/glide/async_commands/cluster_commands.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, List, Mapping, Optional, cast, Tuple +from typing import Dict, List, Mapping, Optional, Tuple, cast from glide.async_commands.core import ( CoreCommands, diff --git a/python/python/glide/async_commands/core.py b/python/python/glide/async_commands/core.py index 11d458b3bd..ed62f896fa 100644 --- a/python/python/glide/async_commands/core.py +++ b/python/python/glide/async_commands/core.py @@ -138,13 +138,17 @@ class UpdateOptions(Enum): class SortOrder(Enum): """ SORT order options: options for sorting elements. - - - ASC: Sort in ascending order. - - DESC: Sort in descending order. """ ASC = "ASC" + """ + ASC: Sort in ascending order. + """ + DESC = "DESC" + """ + DESC: Sort in descending order. + """ class GeospatialData: diff --git a/python/python/glide/async_commands/standalone_commands.py b/python/python/glide/async_commands/standalone_commands.py index deef2f0622..ac3111fdb7 100644 --- a/python/python/glide/async_commands/standalone_commands.py +++ b/python/python/glide/async_commands/standalone_commands.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, List, Mapping, Optional, cast, Tuple +from typing import Dict, List, Mapping, Optional, Tuple, cast from glide.async_commands.core import ( CoreCommands, diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index 5e3b1c95a3..5909fbf3e3 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -11,10 +11,10 @@ GeoUnit, InfoSection, InsertPosition, + SortOrder, StreamAddOptions, StreamTrimOptions, UpdateOptions, - SortOrder, _build_sort_args, ) from glide.async_commands.sorted_set import ( @@ -2822,12 +2822,12 @@ class ClusterTransaction(BaseTransaction): """ def sort( - self, + self: TTransaction, key: str, limit: Optional[Tuple[int, int]] = None, order: Optional[SortOrder] = None, alpha: Optional[bool] = None, - ) -> List[Optional[str]]: + ) -> TTransaction: """ Sorts the elements in the list, set, or sorted set at `key` and returns the result. To store the result into a new key, see `sort_store`. @@ -2847,13 +2847,13 @@ def sort( return self.append_command(RequestType.Sort, args) def sort_store( - self, + self: TTransaction, key: str, store: str, limit: Optional[Tuple[int, int]] = None, order: Optional[SortOrder] = None, alpha: Optional[bool] = None, - ) -> int: + ) -> TTransaction: """ Sorts the elements in the list, set, or sorted set at `key` and stores the result in `store`. When in cluster mode, `key` and `store` must map to the same hash slot. diff --git a/python/python/tests/test_async_client.py b/python/python/tests/test_async_client.py index 2c4e7806b4..5a29a2912d 100644 --- a/python/python/tests/test_async_client.py +++ b/python/python/tests/test_async_client.py @@ -21,11 +21,11 @@ InfBound, InfoSection, InsertPosition, + SortOrder, StreamAddOptions, TrimByMaxLen, TrimByMinId, UpdateOptions, - SortOrder, ) from glide.async_commands.sorted_set import ( AggregationType, @@ -3440,38 +3440,39 @@ async def test_sort_and_sort_store_with_get_or_by_args( assert await redis_client.hset(user_key5, {"name": "Eve", "age": "40"}) == 2 assert await redis_client.lpush("user_ids", ["5", "4", "3", "2", "1"]) == 5 - # Test sort with all arguments - assert await redis_client.lpush(key, ["3", "1", "2"]) == 3 - result = await redis_client.sort( - key, - limit=(0, 2), - get_patterns=["user:*->name"], - order=SortOrder.ASC, - alpha=True, - ) - assert result == ["Alice", "Bob"] - - # Test sort_store with all arguments - result = await redis_client.sort_store( - key, - store, - limit=(0, 2), - get_patterns=["user:*->name"], - order=SortOrder.ASC, - alpha=True, - ) - assert result == 2 - sorted_list = await redis_client.lrange(store, 0, -1) - assert sorted_list == ["Alice", "Bob"] + if isinstance(redis_client, RedisClient): + # Test sort with all arguments + assert await redis_client.lpush(key, ["3", "1", "2"]) == 3 + result = await redis_client.sort( + key, + limit=(0, 2), + get_patterns=["user:*->name"], + order=SortOrder.ASC, + alpha=True, + ) + assert result == ["Alice", "Bob"] - # Test sort with `by` argument - result = await redis_client.sort( - "user_ids", - by_pattern="user:*->age", - get_patterns=["user:*->name"], - alpha=True, - ) - assert result == ["Dave", "Bob", "Alice", "Charlie", "Eve"] + # Test sort_store with all arguments + sort_store_result = await redis_client.sort_store( + key, + store, + limit=(0, 2), + get_patterns=["user:*->name"], + order=SortOrder.ASC, + alpha=True, + ) + assert sort_store_result == 2 + sorted_list = await redis_client.lrange(store, 0, -1) + assert sorted_list == ["Alice", "Bob"] + + # Test sort with `by` argument + result = await redis_client.sort( + "user_ids", + by_pattern="user:*->age", + get_patterns=["user:*->name"], + alpha=True, + ) + assert result == ["Dave", "Bob", "Alice", "Charlie", "Eve"] @pytest.mark.parametrize("cluster_mode", [True, False]) @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) @@ -3486,8 +3487,10 @@ async def test_sort_and_sort_store_without_get_or_by_args( assert result == [] # Test sort_store with non-existing key - result = await redis_client.sort_store("{SameSlotKey}:non_existing_key", store) - assert result == 0 + sort_store_result = await redis_client.sort_store( + "{SameSlotKey}:non_existing_key", store + ) + assert sort_store_result == 0 # Test each argument separately assert await redis_client.lpush(key, ["5", "2", "4", "1", "3"]) == 5 @@ -3521,10 +3524,10 @@ async def test_sort_and_sort_store_without_get_or_by_args( assert result == ["5", "4", "3"] # Test sort_store with combined arguments - result = await redis_client.sort_store( + sort_store_result = await redis_client.sort_store( key, store, limit=(1, 3), order=SortOrder.DESC, alpha=True ) - assert result == 3 + assert sort_store_result == 3 sorted_list = await redis_client.lrange(store, 0, -1) assert sorted_list == ["5", "4", "3"] From 6e767a5681bda28bd6099f0febc574b560ee534c Mon Sep 17 00:00:00 2001 From: Gilboab <97948000+GilboaAWS@users.noreply.github.com> Date: Sun, 26 May 2024 13:39:07 +0300 Subject: [PATCH 03/24] Apply suggestions from code review Co-authored-by: Yury-Fridlyand --- python/python/glide/async_commands/cluster_commands.py | 4 ++-- python/python/glide/async_commands/standalone_commands.py | 4 ++-- python/python/glide/async_commands/transaction.py | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/python/python/glide/async_commands/cluster_commands.py b/python/python/glide/async_commands/cluster_commands.py index 4f69d6ea46..49123462ba 100644 --- a/python/python/glide/async_commands/cluster_commands.py +++ b/python/python/glide/async_commands/cluster_commands.py @@ -384,7 +384,7 @@ async def sort( Sorts the elements in the list, set, or sorted set at `key` and returns the result. To store the result into a new key, see `sort_store`. - see https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey-io.github.io/commands/sort/ for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. @@ -422,7 +422,7 @@ async def sort_store( When in cluster mode, `key` and `store` must map to the same hash slot. To get the sort result, see `sort`. - see https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey-io.github.io/commands/sort/ for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. diff --git a/python/python/glide/async_commands/standalone_commands.py b/python/python/glide/async_commands/standalone_commands.py index ac3111fdb7..277a8d388a 100644 --- a/python/python/glide/async_commands/standalone_commands.py +++ b/python/python/glide/async_commands/standalone_commands.py @@ -284,7 +284,7 @@ async def sort( The `sort` command can be used to sort elements based on different criteria and apply transformations on sorted elements. To store the result into a new key, see `sort_store`. - see https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey-io.github.io/commands/sort/ for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. @@ -331,7 +331,7 @@ async def sort_store( The `sort` command can be used to sort elements based on different criteria, apply transformations on sorted elements, and store the result in a new key. To get the sort result, see `sort`. - see https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey-io.github.io/commands/sort/ for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index 5909fbf3e3..e13e984ce4 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -2761,7 +2761,7 @@ def sort( The `sort` command can be used to sort elements based on different criteria and apply transformations on sorted elements. To store the result into a new key, see `sort_store`. - see https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey-io.github.io/commands/sort/ for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. @@ -2792,7 +2792,7 @@ def sort_store( The `sort` command can be used to sort elements based on different criteria, apply transformations on sorted elements, and store the result in a new key. To get the sort result, see `sort`. - see https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey-io.github.io/commands/sort/ for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. @@ -2832,7 +2832,7 @@ def sort( Sorts the elements in the list, set, or sorted set at `key` and returns the result. To store the result into a new key, see `sort_store`. - see https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey-io.github.io/commands/sort/ for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. @@ -2859,7 +2859,7 @@ def sort_store( When in cluster mode, `key` and `store` must map to the same hash slot. To get the sort result, see `sort`. - see https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey-io.github.io/commands/sort/ for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. From ef8e5b198ee792a09d664388702e75d6129bfe07 Mon Sep 17 00:00:00 2001 From: GilboaAWS Date: Mon, 27 May 2024 08:17:12 +0000 Subject: [PATCH 04/24] Addressed comments from PR --- python/python/glide/__init__.py | 3 +- .../glide/async_commands/cluster_commands.py | 37 +++++++++------ .../glide/async_commands/command_args.py | 47 +++++++++++++++++++ python/python/glide/async_commands/core.py | 21 ++------- .../python/glide/async_commands/sorted_set.py | 19 +------- .../async_commands/standalone_commands.py | 16 +++---- .../glide/async_commands/transaction.py | 18 +++---- python/python/tests/test_async_client.py | 12 ++--- python/python/tests/test_transaction.py | 6 +-- 9 files changed, 100 insertions(+), 79 deletions(-) create mode 100644 python/python/glide/async_commands/command_args.py diff --git a/python/python/glide/__init__.py b/python/python/glide/__init__.py index b9e587c0e4..3fd31c5d22 100644 --- a/python/python/glide/__init__.py +++ b/python/python/glide/__init__.py @@ -1,5 +1,6 @@ # Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 +from glide.async_commands.command_args import Limit, SortOrder from glide.async_commands.core import ( ConditionalChange, ExpireOptions, @@ -9,7 +10,6 @@ GeoUnit, InfoSection, InsertPosition, - SortOrder, StreamAddOptions, StreamTrimOptions, TrimByMaxLen, @@ -21,7 +21,6 @@ AggregationType, InfBound, LexBoundary, - Limit, RangeByIndex, RangeByLex, RangeByScore, diff --git a/python/python/glide/async_commands/cluster_commands.py b/python/python/glide/async_commands/cluster_commands.py index 49123462ba..e4edac551b 100644 --- a/python/python/glide/async_commands/cluster_commands.py +++ b/python/python/glide/async_commands/cluster_commands.py @@ -4,12 +4,8 @@ from typing import Dict, List, Mapping, Optional, Tuple, cast -from glide.async_commands.core import ( - CoreCommands, - InfoSection, - SortOrder, - _build_sort_args, -) +from glide.async_commands.command_args import Limit, SortOrder +from glide.async_commands.core import CoreCommands, InfoSection, _build_sort_args from glide.async_commands.transaction import BaseTransaction, ClusterTransaction from glide.constants import TOK, TClusterResponse, TResult, TSingleNodeRoute from glide.protobuf.redis_request_pb2 import RequestType @@ -376,34 +372,47 @@ async def lastsave(self, route: Optional[Route] = None) -> TClusterResponse[int] async def sort( self, key: str, - limit: Optional[Tuple[int, int]] = None, + limit: Optional[Limit] = None, order: Optional[SortOrder] = None, alpha: Optional[bool] = None, - ) -> List[Optional[str]]: + ) -> List[str]: """ Sorts the elements in the list, set, or sorted set at `key` and returns the result. To store the result into a new key, see `sort_store`. + By default, sorting is numeric, and elements are compared by their value interpreted as double precision floating point numbers. + See https://valkey-io.github.io/commands/sort/ for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. - limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. - order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). - alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + limit (Optional[Limit]): The limit argument for a range query. Defaults to None. See `Limit` class for more information. + A tuple specifying the offset and count for limiting the number of results returned. + The `limit` parameter takes a tuple `(offset, count)` where `offset` specifies the starting position and `count` specifies the maximum number of elements to return. + If `offset` exceeds the length of the returned result, an empty list is returned. + order (Optional[SortOrder]): Specifies the order to sort the elements. + Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + alpha (Optional[bool]): When `True`, sorts elements lexicographically. When `False` (default), sorts elements numerically. + Use this when the list, set, or sorted set contains string values that cannot be converted into double precision floating point numbers. Returns: - List[Optional[str]]: Returns a list of sorted elements. + List[str]: A list of sorted elements. Examples: - >>> await client.lpush("mylist", 3, 1, 2) + >>> await client.lpush("mylist", '3', '1', '2') >>> await client.sort("mylist") ['1', '2', '3'] + >>> await client.sort("mylist", order=SortOrder.DESC) ['3', '2', '1'] - >>> await client.lpush("mylist", 2, 1, 2, 3, 3, 1) + + >>> await client.lpush("mylist", '2', '1', '2', '3', '3', '1') >>> await client.sort("mylist", limit=(2, 3)) ['2', '2', '3'] + + >>> await client.lpush("mylist", "a", "b", "c", "d") + >>> await client.sort("mylist", limit=(3, 2), order=SortOrder.DESC, alpha=True) + ['b', 'a'] """ args = _build_sort_args(key, None, limit, None, order, alpha) result = await self._execute_command(RequestType.Sort, args) diff --git a/python/python/glide/async_commands/command_args.py b/python/python/glide/async_commands/command_args.py new file mode 100644 index 0000000000..6505fd2eae --- /dev/null +++ b/python/python/glide/async_commands/command_args.py @@ -0,0 +1,47 @@ +# Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 + +from enum import Enum +from typing import List, Optional, Tuple, Union + + +class Limit: + """ + Represents a limit argument for range queries in various Redis commands. + + The `LIMIT` argument is commonly used to specify a subset of results from the matching elements, + similar to the `LIMIT` clause in SQL (e.g., `SELECT LIMIT offset, count`). + + This class can be utilized in multiple Redis commands that support limit options, + such as [ZRANGE](https://valkey.io/commands/zrange), [SORT](https://valkey.io/commands/sort/), and others. + + Args: + offset (int): The starting position of the range. + count (int): The maximum number of elements to include in the range. + A negative count returns all elements from the offset. + + Examples: + >>> limit = Limit(0, 10) # Fetch the first 10 elements + >>> limit = Limit(5, -1) # Fetch all elements starting from the 5th element + """ + + def __init__(self, offset: int, count: int): + self.offset = offset + self.count = count + + self.count = count + + +class SortOrder(Enum): + """ + SORT order options: options for sorting elements. + """ + + ASC = "ASC" + """ + ASC: Sort in ascending order. + """ + + DESC = "DESC" + """ + DESC: Sort in descending order. + """ diff --git a/python/python/glide/async_commands/core.py b/python/python/glide/async_commands/core.py index ed62f896fa..80e1ce9257 100644 --- a/python/python/glide/async_commands/core.py +++ b/python/python/glide/async_commands/core.py @@ -16,6 +16,7 @@ get_args, ) +from glide.async_commands.command_args import Limit, SortOrder from glide.async_commands.sorted_set import ( AggregationType, InfBound, @@ -135,22 +136,6 @@ class UpdateOptions(Enum): GREATER_THAN = "GT" -class SortOrder(Enum): - """ - SORT order options: options for sorting elements. - """ - - ASC = "ASC" - """ - ASC: Sort in ascending order. - """ - - DESC = "DESC" - """ - DESC: Sort in descending order. - """ - - class GeospatialData: def __init__(self, longitude: float, latitude: float): """ @@ -380,7 +365,7 @@ class InsertPosition(Enum): def _build_sort_args( key: str, by_pattern: Optional[str] = None, - limit: Optional[Tuple[int, int]] = None, + limit: Optional[Limit] = None, get_patterns: Optional[List[str]] = None, order: Optional[SortOrder] = None, alpha: Optional[bool] = None, @@ -392,7 +377,7 @@ def _build_sort_args( args.extend(["BY", by_pattern]) if limit: - args.extend(["LIMIT", str(limit[0]), str(limit[1])]) + args.extend(["LIMIT", str(limit.offset), str(limit.count)]) if get_patterns: for pattern in get_patterns: diff --git a/python/python/glide/async_commands/sorted_set.py b/python/python/glide/async_commands/sorted_set.py index 7ac92f1e99..5e99da8631 100644 --- a/python/python/glide/async_commands/sorted_set.py +++ b/python/python/glide/async_commands/sorted_set.py @@ -3,6 +3,8 @@ from enum import Enum from typing import List, Optional, Tuple, Union +from glide.async_commands.command_args import Limit + class InfBound(Enum): """ @@ -88,23 +90,6 @@ def __init__(self, value: str, is_inclusive: bool = True): self.value = f"[{value}" if is_inclusive else f"({value}" -class Limit: - """ - Represents a limit argument for a range query in a sorted set to be used in [ZRANGE](https://redis.io/commands/zrange) command. - - The optional LIMIT argument can be used to obtain a sub-range from the matching elements - (similar to SELECT LIMIT offset, count in SQL). - Args: - offset (int): The offset from the start of the range. - count (int): The number of elements to include in the range. - A negative count returns all elements from the offset. - """ - - def __init__(self, offset: int, count: int): - self.offset = offset - self.count = count - - class RangeByIndex: """ Represents a range by index (rank) in a sorted set. diff --git a/python/python/glide/async_commands/standalone_commands.py b/python/python/glide/async_commands/standalone_commands.py index 277a8d388a..38a463be57 100644 --- a/python/python/glide/async_commands/standalone_commands.py +++ b/python/python/glide/async_commands/standalone_commands.py @@ -4,12 +4,8 @@ from typing import Dict, List, Mapping, Optional, Tuple, cast -from glide.async_commands.core import ( - CoreCommands, - InfoSection, - SortOrder, - _build_sort_args, -) +from glide.async_commands.command_args import Limit, SortOrder +from glide.async_commands.core import CoreCommands, InfoSection, _build_sort_args from glide.async_commands.transaction import BaseTransaction, Transaction from glide.constants import TOK, TResult from glide.protobuf.redis_request_pb2 import RequestType @@ -274,7 +270,7 @@ async def sort( self, key: str, by_pattern: Optional[str] = None, - limit: Optional[Tuple[int, int]] = None, + limit: Optional[Limit] = None, get_patterns: Optional[List[str]] = None, order: Optional[SortOrder] = None, alpha: Optional[bool] = None, @@ -289,7 +285,7 @@ async def sort( Args: key (str): The key of the list, set, or sorted set to be sorted. by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. - limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. + limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. get_patterns (Optional[List[str]]): One or more patterns to extract values to return. order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. @@ -321,7 +317,7 @@ async def sort_store( key: str, store: str, by_pattern: Optional[str] = None, - limit: Optional[Tuple[int, int]] = None, + limit: Optional[Limit] = None, get_patterns: Optional[List[str]] = None, order: Optional[SortOrder] = None, alpha: Optional[bool] = None, @@ -337,7 +333,7 @@ async def sort_store( key (str): The key of the list, set, or sorted set to be sorted. store (str): The key where the sorted result will be stored. by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. - limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. + limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. get_patterns (Optional[List[str]]): One or more patterns to extract values to return. order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index e13e984ce4..e96bec5b50 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -3,6 +3,7 @@ import threading from typing import List, Mapping, Optional, Tuple, TypeVar, Union +from glide.async_commands.command_args import Limit, SortOrder from glide.async_commands.core import ( ConditionalChange, ExpireOptions, @@ -11,7 +12,6 @@ GeoUnit, InfoSection, InsertPosition, - SortOrder, StreamAddOptions, StreamTrimOptions, UpdateOptions, @@ -2751,7 +2751,7 @@ def sort( self: TTransaction, key: str, by_pattern: Optional[str] = None, - limit: Optional[Tuple[int, int]] = None, + limit: Optional[Limit] = None, get_patterns: Optional[List[str]] = None, order: Optional[SortOrder] = None, alpha: Optional[bool] = None, @@ -2766,7 +2766,7 @@ def sort( Args: key (str): The key of the list, set, or sorted set to be sorted. by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. - limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. + limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. get_patterns (Optional[List[str]]): One or more patterns to extract values to return. order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. @@ -2782,7 +2782,7 @@ def sort_store( key: str, store: str, by_pattern: Optional[str] = None, - limit: Optional[Tuple[int, int]] = None, + limit: Optional[Limit] = None, get_patterns: Optional[List[str]] = None, order: Optional[SortOrder] = None, alpha: Optional[bool] = None, @@ -2798,7 +2798,7 @@ def sort_store( key (str): The key of the list, set, or sorted set to be sorted. store (str): The key where the sorted result will be stored. by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. - limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. + limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. get_patterns (Optional[List[str]]): One or more patterns to extract values to return. order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. @@ -2824,7 +2824,7 @@ class ClusterTransaction(BaseTransaction): def sort( self: TTransaction, key: str, - limit: Optional[Tuple[int, int]] = None, + limit: Optional[Limit] = None, order: Optional[SortOrder] = None, alpha: Optional[bool] = None, ) -> TTransaction: @@ -2836,7 +2836,7 @@ def sort( Args: key (str): The key of the list, set, or sorted set to be sorted. - limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. + limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. @@ -2850,7 +2850,7 @@ def sort_store( self: TTransaction, key: str, store: str, - limit: Optional[Tuple[int, int]] = None, + limit: Optional[Limit] = None, order: Optional[SortOrder] = None, alpha: Optional[bool] = None, ) -> TTransaction: @@ -2864,7 +2864,7 @@ def sort_store( Args: key (str): The key of the list, set, or sorted set to be sorted. store (str): The key where the sorted result will be stored. - limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. + limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. diff --git a/python/python/tests/test_async_client.py b/python/python/tests/test_async_client.py index 5a29a2912d..1cd4aa2b5a 100644 --- a/python/python/tests/test_async_client.py +++ b/python/python/tests/test_async_client.py @@ -11,6 +11,7 @@ import pytest from glide import ClosingError, RequestError, Script +from glide.async_commands.command_args import Limit, SortOrder from glide.async_commands.core import ( ConditionalChange, ExpireOptions, @@ -21,7 +22,6 @@ InfBound, InfoSection, InsertPosition, - SortOrder, StreamAddOptions, TrimByMaxLen, TrimByMinId, @@ -3445,7 +3445,7 @@ async def test_sort_and_sort_store_with_get_or_by_args( assert await redis_client.lpush(key, ["3", "1", "2"]) == 3 result = await redis_client.sort( key, - limit=(0, 2), + limit=Limit(0, 2), get_patterns=["user:*->name"], order=SortOrder.ASC, alpha=True, @@ -3456,7 +3456,7 @@ async def test_sort_and_sort_store_with_get_or_by_args( sort_store_result = await redis_client.sort_store( key, store, - limit=(0, 2), + limit=Limit(0, 2), get_patterns=["user:*->name"], order=SortOrder.ASC, alpha=True, @@ -3500,7 +3500,7 @@ async def test_sort_and_sort_store_without_get_or_by_args( assert result == ["1", "2", "3", "4", "5"] # limit argument - result = await redis_client.sort(key, limit=(1, 3)) + result = await redis_client.sort(key, limit=Limit(1, 3)) assert result == ["2", "3", "4"] # order argument @@ -3519,13 +3519,13 @@ async def test_sort_and_sort_store_without_get_or_by_args( # Combining multiple arguments result = await redis_client.sort( - key, limit=(1, 3), order=SortOrder.DESC, alpha=True + key, limit=Limit(1, 3), order=SortOrder.DESC, alpha=True ) assert result == ["5", "4", "3"] # Test sort_store with combined arguments sort_store_result = await redis_client.sort_store( - key, store, limit=(1, 3), order=SortOrder.DESC, alpha=True + key, store, limit=Limit(1, 3), order=SortOrder.DESC, alpha=True ) assert sort_store_result == 3 sorted_list = await redis_client.lrange(store, 0, -1) diff --git a/python/python/tests/test_transaction.py b/python/python/tests/test_transaction.py index 57a5b7a3a8..9d87886ee0 100644 --- a/python/python/tests/test_transaction.py +++ b/python/python/tests/test_transaction.py @@ -6,10 +6,10 @@ import pytest from glide import RequestError +from glide.async_commands.command_args import Limit, SortOrder from glide.async_commands.core import ( GeospatialData, InsertPosition, - SortOrder, StreamAddOptions, TrimByMinId, ) @@ -369,7 +369,7 @@ async def transaction_test( args.append(5) transaction.sort( key17, - limit=(1, 4), + limit=Limit(1, 4), order=SortOrder.ASC, alpha=True, ) @@ -377,7 +377,7 @@ async def transaction_test( transaction.sort_store( key17, key18, - limit=(1, 4), + limit=Limit(1, 4), order=SortOrder.ASC, alpha=True, ) From 8cb47fd6598bf0f6db687bc69655d0bfcfdb7976 Mon Sep 17 00:00:00 2001 From: GilboaAWS Date: Mon, 27 May 2024 08:48:16 +0000 Subject: [PATCH 05/24] Changed SortOrder to OrderBy --- python/python/glide/__init__.py | 4 ++-- .../glide/async_commands/cluster_commands.py | 18 +++++++++--------- .../glide/async_commands/command_args.py | 2 +- python/python/glide/async_commands/core.py | 4 ++-- .../async_commands/standalone_commands.py | 14 +++++++------- .../python/glide/async_commands/transaction.py | 18 +++++++++--------- python/python/tests/test_async_client.py | 12 ++++++------ python/python/tests/test_transaction.py | 10 +++++----- 8 files changed, 41 insertions(+), 41 deletions(-) diff --git a/python/python/glide/__init__.py b/python/python/glide/__init__.py index 3fd31c5d22..ebd86eca1c 100644 --- a/python/python/glide/__init__.py +++ b/python/python/glide/__init__.py @@ -1,6 +1,6 @@ # Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 -from glide.async_commands.command_args import Limit, SortOrder +from glide.async_commands.command_args import Limit, OrderBy from glide.async_commands.core import ( ConditionalChange, ExpireOptions, @@ -102,7 +102,7 @@ "RangeByLex", "RangeByScore", "ScoreFilter", - "SortOrder", + "OrderBy", "StreamAddOptions", "StreamTrimOptions", "TrimByMaxLen", diff --git a/python/python/glide/async_commands/cluster_commands.py b/python/python/glide/async_commands/cluster_commands.py index e4edac551b..01ebc082c3 100644 --- a/python/python/glide/async_commands/cluster_commands.py +++ b/python/python/glide/async_commands/cluster_commands.py @@ -4,7 +4,7 @@ from typing import Dict, List, Mapping, Optional, Tuple, cast -from glide.async_commands.command_args import Limit, SortOrder +from glide.async_commands.command_args import Limit, OrderBy from glide.async_commands.core import CoreCommands, InfoSection, _build_sort_args from glide.async_commands.transaction import BaseTransaction, ClusterTransaction from glide.constants import TOK, TClusterResponse, TResult, TSingleNodeRoute @@ -373,7 +373,7 @@ async def sort( self, key: str, limit: Optional[Limit] = None, - order: Optional[SortOrder] = None, + order: Optional[OrderBy] = None, alpha: Optional[bool] = None, ) -> List[str]: """ @@ -390,8 +390,8 @@ async def sort( A tuple specifying the offset and count for limiting the number of results returned. The `limit` parameter takes a tuple `(offset, count)` where `offset` specifies the starting position and `count` specifies the maximum number of elements to return. If `offset` exceeds the length of the returned result, an empty list is returned. - order (Optional[SortOrder]): Specifies the order to sort the elements. - Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + order (Optional[OrderBy]): Specifies the order to sort the elements. + Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): When `True`, sorts elements lexicographically. When `False` (default), sorts elements numerically. Use this when the list, set, or sorted set contains string values that cannot be converted into double precision floating point numbers. @@ -403,15 +403,15 @@ async def sort( >>> await client.sort("mylist") ['1', '2', '3'] - >>> await client.sort("mylist", order=SortOrder.DESC) + >>> await client.sort("mylist", order=OrderBy.DESC) ['3', '2', '1'] >>> await client.lpush("mylist", '2', '1', '2', '3', '3', '1') - >>> await client.sort("mylist", limit=(2, 3)) + >>> await client.sort("mylist", limit=Limit(2, 3)) ['2', '2', '3'] >>> await client.lpush("mylist", "a", "b", "c", "d") - >>> await client.sort("mylist", limit=(3, 2), order=SortOrder.DESC, alpha=True) + >>> await client.sort("mylist", limit=Limit(3, 2), order=OrderBy.DESC, alpha=True) ['b', 'a'] """ args = _build_sort_args(key, None, limit, None, order, alpha) @@ -423,7 +423,7 @@ async def sort_store( key: str, store: str, limit: Optional[Tuple[int, int]] = None, - order: Optional[SortOrder] = None, + order: Optional[OrderBy] = None, alpha: Optional[bool] = None, ) -> int: """ @@ -437,7 +437,7 @@ async def sort_store( key (str): The key of the list, set, or sorted set to be sorted. store (str): The key where the sorted result will be stored. limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. - order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. Returns: diff --git a/python/python/glide/async_commands/command_args.py b/python/python/glide/async_commands/command_args.py index 6505fd2eae..1ba3c779e0 100644 --- a/python/python/glide/async_commands/command_args.py +++ b/python/python/glide/async_commands/command_args.py @@ -31,7 +31,7 @@ def __init__(self, offset: int, count: int): self.count = count -class SortOrder(Enum): +class OrderBy(Enum): """ SORT order options: options for sorting elements. """ diff --git a/python/python/glide/async_commands/core.py b/python/python/glide/async_commands/core.py index 80e1ce9257..57d41fbb17 100644 --- a/python/python/glide/async_commands/core.py +++ b/python/python/glide/async_commands/core.py @@ -16,7 +16,7 @@ get_args, ) -from glide.async_commands.command_args import Limit, SortOrder +from glide.async_commands.command_args import Limit, OrderBy from glide.async_commands.sorted_set import ( AggregationType, InfBound, @@ -367,7 +367,7 @@ def _build_sort_args( by_pattern: Optional[str] = None, limit: Optional[Limit] = None, get_patterns: Optional[List[str]] = None, - order: Optional[SortOrder] = None, + order: Optional[OrderBy] = None, alpha: Optional[bool] = None, store: Optional[str] = None, ) -> List[str]: diff --git a/python/python/glide/async_commands/standalone_commands.py b/python/python/glide/async_commands/standalone_commands.py index 38a463be57..99ede108dc 100644 --- a/python/python/glide/async_commands/standalone_commands.py +++ b/python/python/glide/async_commands/standalone_commands.py @@ -4,7 +4,7 @@ from typing import Dict, List, Mapping, Optional, Tuple, cast -from glide.async_commands.command_args import Limit, SortOrder +from glide.async_commands.command_args import Limit, OrderBy from glide.async_commands.core import CoreCommands, InfoSection, _build_sort_args from glide.async_commands.transaction import BaseTransaction, Transaction from glide.constants import TOK, TResult @@ -272,7 +272,7 @@ async def sort( by_pattern: Optional[str] = None, limit: Optional[Limit] = None, get_patterns: Optional[List[str]] = None, - order: Optional[SortOrder] = None, + order: Optional[OrderBy] = None, alpha: Optional[bool] = None, ) -> List[Optional[str]]: """ @@ -287,7 +287,7 @@ async def sort( by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. get_patterns (Optional[List[str]]): One or more patterns to extract values to return. - order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. Returns: @@ -297,10 +297,10 @@ async def sort( >>> await client.lpush("mylist", 3, 1, 2) >>> await client.sort("mylist") ['1', '2', '3'] - >>> await client.sort("mylist", order=SortOrder.DESC) + >>> await client.sort("mylist", order=OrderBy.DESC) ['3', '2', '1'] >>> await client.lpush("mylist", 2, 1, 2, 3, 3, 1) - >>> await client.sort("mylist", limit=(2, 3)) + >>> await client.sort("mylist", limit=Limit(2, 3)) ['2', '2', '3'] >>> await client.hset("user:1", "name", "Alice", "age", 30) >>> await client.hset("user:2", "name", "Bob", "age", 25) @@ -319,7 +319,7 @@ async def sort_store( by_pattern: Optional[str] = None, limit: Optional[Limit] = None, get_patterns: Optional[List[str]] = None, - order: Optional[SortOrder] = None, + order: Optional[OrderBy] = None, alpha: Optional[bool] = None, ) -> int: """ @@ -335,7 +335,7 @@ async def sort_store( by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. get_patterns (Optional[List[str]]): One or more patterns to extract values to return. - order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. Returns: diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index e96bec5b50..483bf8a6bc 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -3,7 +3,7 @@ import threading from typing import List, Mapping, Optional, Tuple, TypeVar, Union -from glide.async_commands.command_args import Limit, SortOrder +from glide.async_commands.command_args import Limit, OrderBy from glide.async_commands.core import ( ConditionalChange, ExpireOptions, @@ -2753,7 +2753,7 @@ def sort( by_pattern: Optional[str] = None, limit: Optional[Limit] = None, get_patterns: Optional[List[str]] = None, - order: Optional[SortOrder] = None, + order: Optional[OrderBy] = None, alpha: Optional[bool] = None, ) -> TTransaction: """ @@ -2768,7 +2768,7 @@ def sort( by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. get_patterns (Optional[List[str]]): One or more patterns to extract values to return. - order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. Command response: @@ -2784,7 +2784,7 @@ def sort_store( by_pattern: Optional[str] = None, limit: Optional[Limit] = None, get_patterns: Optional[List[str]] = None, - order: Optional[SortOrder] = None, + order: Optional[OrderBy] = None, alpha: Optional[bool] = None, ) -> TTransaction: """ @@ -2800,7 +2800,7 @@ def sort_store( by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. get_patterns (Optional[List[str]]): One or more patterns to extract values to return. - order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. Command response: @@ -2825,7 +2825,7 @@ def sort( self: TTransaction, key: str, limit: Optional[Limit] = None, - order: Optional[SortOrder] = None, + order: Optional[OrderBy] = None, alpha: Optional[bool] = None, ) -> TTransaction: """ @@ -2837,7 +2837,7 @@ def sort( Args: key (str): The key of the list, set, or sorted set to be sorted. limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. - order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. Command response: @@ -2851,7 +2851,7 @@ def sort_store( key: str, store: str, limit: Optional[Limit] = None, - order: Optional[SortOrder] = None, + order: Optional[OrderBy] = None, alpha: Optional[bool] = None, ) -> TTransaction: """ @@ -2865,7 +2865,7 @@ def sort_store( key (str): The key of the list, set, or sorted set to be sorted. store (str): The key where the sorted result will be stored. limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. - order (Optional[SortOrder]): Specifies the order to sort the elements. Can be `SortOrder.ASC` (ascending) or `SortOrder.DESC` (descending). + order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. Command response: diff --git a/python/python/tests/test_async_client.py b/python/python/tests/test_async_client.py index 1cd4aa2b5a..04b3abb05e 100644 --- a/python/python/tests/test_async_client.py +++ b/python/python/tests/test_async_client.py @@ -11,7 +11,7 @@ import pytest from glide import ClosingError, RequestError, Script -from glide.async_commands.command_args import Limit, SortOrder +from glide.async_commands.command_args import Limit, OrderBy from glide.async_commands.core import ( ConditionalChange, ExpireOptions, @@ -3447,7 +3447,7 @@ async def test_sort_and_sort_store_with_get_or_by_args( key, limit=Limit(0, 2), get_patterns=["user:*->name"], - order=SortOrder.ASC, + order=OrderBy.ASC, alpha=True, ) assert result == ["Alice", "Bob"] @@ -3458,7 +3458,7 @@ async def test_sort_and_sort_store_with_get_or_by_args( store, limit=Limit(0, 2), get_patterns=["user:*->name"], - order=SortOrder.ASC, + order=OrderBy.ASC, alpha=True, ) assert sort_store_result == 2 @@ -3504,7 +3504,7 @@ async def test_sort_and_sort_store_without_get_or_by_args( assert result == ["2", "3", "4"] # order argument - result = await redis_client.sort(key, order=SortOrder.DESC) + result = await redis_client.sort(key, order=OrderBy.DESC) assert result == ["5", "4", "3", "2", "1"] assert await redis_client.lpush(key, ["a"]) == 6 @@ -3519,13 +3519,13 @@ async def test_sort_and_sort_store_without_get_or_by_args( # Combining multiple arguments result = await redis_client.sort( - key, limit=Limit(1, 3), order=SortOrder.DESC, alpha=True + key, limit=Limit(1, 3), order=OrderBy.DESC, alpha=True ) assert result == ["5", "4", "3"] # Test sort_store with combined arguments sort_store_result = await redis_client.sort_store( - key, store, limit=Limit(1, 3), order=SortOrder.DESC, alpha=True + key, store, limit=Limit(1, 3), order=OrderBy.DESC, alpha=True ) assert sort_store_result == 3 sorted_list = await redis_client.lrange(store, 0, -1) diff --git a/python/python/tests/test_transaction.py b/python/python/tests/test_transaction.py index 9d87886ee0..3ce0a3acf5 100644 --- a/python/python/tests/test_transaction.py +++ b/python/python/tests/test_transaction.py @@ -6,7 +6,7 @@ import pytest from glide import RequestError -from glide.async_commands.command_args import Limit, SortOrder +from glide.async_commands.command_args import Limit, OrderBy from glide.async_commands.core import ( GeospatialData, InsertPosition, @@ -370,7 +370,7 @@ async def transaction_test( transaction.sort( key17, limit=Limit(1, 4), - order=SortOrder.ASC, + order=OrderBy.ASC, alpha=True, ) args.append(["2", "3", "4", "a"]) @@ -378,7 +378,7 @@ async def transaction_test( key17, key18, limit=Limit(1, 4), - order=SortOrder.ASC, + order=OrderBy.ASC, alpha=True, ) args.append(4) @@ -531,7 +531,7 @@ async def test_standalone_transaction(self, redis_client: RedisClient): key1, by_pattern="user:*->age", get_patterns=["user:*->name"], - order=SortOrder.ASC, + order=OrderBy.ASC, alpha=True, ) transaction.sort_store( @@ -539,7 +539,7 @@ async def test_standalone_transaction(self, redis_client: RedisClient): "newSortedKey", by_pattern="user:*->age", get_patterns=["user:*->name"], - order=SortOrder.ASC, + order=OrderBy.ASC, alpha=True, ) transaction.select(0) From e295566ae3c4c1f5fefa625f94251f3557570169 Mon Sep 17 00:00:00 2001 From: Gilboab <97948000+GilboaAWS@users.noreply.github.com> Date: Mon, 27 May 2024 11:54:49 +0300 Subject: [PATCH 06/24] Updated valkey path in links. Co-authored-by: Shoham Elias <116083498+shohamazon@users.noreply.github.com> --- python/python/glide/async_commands/cluster_commands.py | 4 ++-- python/python/glide/async_commands/standalone_commands.py | 4 ++-- python/python/glide/async_commands/transaction.py | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/python/python/glide/async_commands/cluster_commands.py b/python/python/glide/async_commands/cluster_commands.py index 01ebc082c3..d099e89c30 100644 --- a/python/python/glide/async_commands/cluster_commands.py +++ b/python/python/glide/async_commands/cluster_commands.py @@ -382,7 +382,7 @@ async def sort( By default, sorting is numeric, and elements are compared by their value interpreted as double precision floating point numbers. - See https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey.io/commands/sort for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. @@ -431,7 +431,7 @@ async def sort_store( When in cluster mode, `key` and `store` must map to the same hash slot. To get the sort result, see `sort`. - See https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey.io/commands/sort for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. diff --git a/python/python/glide/async_commands/standalone_commands.py b/python/python/glide/async_commands/standalone_commands.py index 99ede108dc..47adba25c7 100644 --- a/python/python/glide/async_commands/standalone_commands.py +++ b/python/python/glide/async_commands/standalone_commands.py @@ -280,7 +280,7 @@ async def sort( The `sort` command can be used to sort elements based on different criteria and apply transformations on sorted elements. To store the result into a new key, see `sort_store`. - See https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey.io/commands/sort for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. @@ -327,7 +327,7 @@ async def sort_store( The `sort` command can be used to sort elements based on different criteria, apply transformations on sorted elements, and store the result in a new key. To get the sort result, see `sort`. - See https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey.io/commands/sort for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index 483bf8a6bc..78c989a624 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -2761,7 +2761,7 @@ def sort( The `sort` command can be used to sort elements based on different criteria and apply transformations on sorted elements. To store the result into a new key, see `sort_store`. - See https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey.io/commands/sort for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. @@ -2792,7 +2792,7 @@ def sort_store( The `sort` command can be used to sort elements based on different criteria, apply transformations on sorted elements, and store the result in a new key. To get the sort result, see `sort`. - See https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey.io/commands/sort for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. @@ -2832,7 +2832,7 @@ def sort( Sorts the elements in the list, set, or sorted set at `key` and returns the result. To store the result into a new key, see `sort_store`. - See https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey.io/commands/sort for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. @@ -2859,7 +2859,7 @@ def sort_store( When in cluster mode, `key` and `store` must map to the same hash slot. To get the sort result, see `sort`. - See https://valkey-io.github.io/commands/sort/ for more details. + See https://valkey.io/commands/sort for more details. Args: key (str): The key of the list, set, or sorted set to be sorted. From 0e6555158c9129aea4feefe770212293e9152ede Mon Sep 17 00:00:00 2001 From: Gilboab <97948000+GilboaAWS@users.noreply.github.com> Date: Mon, 27 May 2024 11:56:49 +0300 Subject: [PATCH 07/24] Removed `pass` from Transaction Class. Co-authored-by: Shoham Elias <116083498+shohamazon@users.noreply.github.com> --- python/python/glide/async_commands/transaction.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index 78c989a624..f9feed460c 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -2875,4 +2875,3 @@ def sort_store( return self.append_command(RequestType.Sort, args) # TODO: add all CLUSTER commands - pass From 19ec5360f53c8533f821be362c4c019b82fb08f2 Mon Sep 17 00:00:00 2001 From: GilboaAWS Date: Mon, 27 May 2024 10:36:15 +0000 Subject: [PATCH 08/24] Fix `Limit` doc --- python/python/glide/async_commands/cluster_commands.py | 9 +++------ .../python/glide/async_commands/standalone_commands.py | 4 ++-- python/python/glide/async_commands/transaction.py | 8 ++++---- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/python/python/glide/async_commands/cluster_commands.py b/python/python/glide/async_commands/cluster_commands.py index d099e89c30..20a8f713d5 100644 --- a/python/python/glide/async_commands/cluster_commands.py +++ b/python/python/glide/async_commands/cluster_commands.py @@ -386,10 +386,7 @@ async def sort( Args: key (str): The key of the list, set, or sorted set to be sorted. - limit (Optional[Limit]): The limit argument for a range query. Defaults to None. See `Limit` class for more information. - A tuple specifying the offset and count for limiting the number of results returned. - The `limit` parameter takes a tuple `(offset, count)` where `offset` specifies the starting position and `count` specifies the maximum number of elements to return. - If `offset` exceeds the length of the returned result, an empty list is returned. + limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): When `True`, sorts elements lexicographically. When `False` (default), sorts elements numerically. @@ -422,7 +419,7 @@ async def sort_store( self, key: str, store: str, - limit: Optional[Tuple[int, int]] = None, + limit: Optional[Limit] = None, order: Optional[OrderBy] = None, alpha: Optional[bool] = None, ) -> int: @@ -436,7 +433,7 @@ async def sort_store( Args: key (str): The key of the list, set, or sorted set to be sorted. store (str): The key where the sorted result will be stored. - limit (Optional[Tuple[int, int]]): A tuple specifying the offset and count for limiting the number of results. + limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. diff --git a/python/python/glide/async_commands/standalone_commands.py b/python/python/glide/async_commands/standalone_commands.py index 47adba25c7..886a9b926e 100644 --- a/python/python/glide/async_commands/standalone_commands.py +++ b/python/python/glide/async_commands/standalone_commands.py @@ -285,7 +285,7 @@ async def sort( Args: key (str): The key of the list, set, or sorted set to be sorted. by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. - limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. + limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. get_patterns (Optional[List[str]]): One or more patterns to extract values to return. order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. @@ -333,7 +333,7 @@ async def sort_store( key (str): The key of the list, set, or sorted set to be sorted. store (str): The key where the sorted result will be stored. by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. - limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. + limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. get_patterns (Optional[List[str]]): One or more patterns to extract values to return. order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index f9feed460c..22769184cb 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -2766,7 +2766,7 @@ def sort( Args: key (str): The key of the list, set, or sorted set to be sorted. by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. - limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. + limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. get_patterns (Optional[List[str]]): One or more patterns to extract values to return. order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. @@ -2798,7 +2798,7 @@ def sort_store( key (str): The key of the list, set, or sorted set to be sorted. store (str): The key where the sorted result will be stored. by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. - limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. + limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. get_patterns (Optional[List[str]]): One or more patterns to extract values to return. order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. @@ -2836,7 +2836,7 @@ def sort( Args: key (str): The key of the list, set, or sorted set to be sorted. - limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. + limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. @@ -2864,7 +2864,7 @@ def sort_store( Args: key (str): The key of the list, set, or sorted set to be sorted. store (str): The key where the sorted result will be stored. - limit (Optional[Limit]): A tuple specifying the offset and count for limiting the number of results. + limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. From d1a5068052360e3947186c0008db67a9ca63cc97 Mon Sep 17 00:00:00 2001 From: GilboaAWS Date: Wed, 29 May 2024 11:31:50 +0000 Subject: [PATCH 09/24] Updated sort args doc. --- .../glide/async_commands/cluster_commands.py | 6 +- .../async_commands/standalone_commands.py | 38 +++++++++-- .../glide/async_commands/transaction.py | 63 +++++++++++++++---- 3 files changed, 88 insertions(+), 19 deletions(-) diff --git a/python/python/glide/async_commands/cluster_commands.py b/python/python/glide/async_commands/cluster_commands.py index 20a8f713d5..fef60b3d35 100644 --- a/python/python/glide/async_commands/cluster_commands.py +++ b/python/python/glide/async_commands/cluster_commands.py @@ -434,8 +434,10 @@ async def sort_store( key (str): The key of the list, set, or sorted set to be sorted. store (str): The key where the sorted result will be stored. limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. - order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). - alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + order (Optional[OrderBy]): Specifies the order to sort the elements. + Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). + alpha (Optional[bool]): When `True`, sorts elements lexicographically. When `False` (default), sorts elements numerically. + Use this when the list, set, or sorted set contains string values that cannot be converted into double precision floating point numbers. Returns: int: The number of elements in the sorted key stored at `store`. diff --git a/python/python/glide/async_commands/standalone_commands.py b/python/python/glide/async_commands/standalone_commands.py index 886a9b926e..42bb9662c1 100644 --- a/python/python/glide/async_commands/standalone_commands.py +++ b/python/python/glide/async_commands/standalone_commands.py @@ -284,9 +284,24 @@ async def sort( Args: key (str): The key of the list, set, or sorted set to be sorted. - by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. + by_pattern (Optional[str]): A pattern to sort by external keys instead of by the elements stored at the key themselves. + The pattern should contain an asterisk (*) as a placeholder for the element values, where the value + from the key replaces the asterisk to create the key name. For example, if `key` contains IDs of objects, + `by_pattern` can be used to sort these IDs based on an attribute of the objects, like their weights or + timestamps. + E.g., if `by_pattern` is `weight_*`, the command will sort the elements by the values of the + keys `weight_`. + If not provided, elements are sorted by their value. limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. - get_patterns (Optional[List[str]]): One or more patterns to extract values to return. + get_pattern (Optional[str]): A pattern used to retrieve external keys' values, instead of the elements at `key`. + The pattern should contain an asterisk (*) as a placeholder for the element values, where the value + from `key` replaces the asterisk to create the key name. This allows the sorted elements to be + transformed based on the related keys values. For example, if `key` contains IDs of users, `get_pattern` + can be used to retrieve specific attributes of these users, such as their names or email addresses. + E.g., if `get_pattern` is `name_*`, the command will return the values of the keys `name_` + for each sorted element. Multiple `get_pattern` arguments can be provided to retrieve multiple attributes. + The special value `#` can be used to include the actual element from `key` being sorted. + If not provided, only the sorted elements themselves are returned. order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. @@ -332,9 +347,24 @@ async def sort_store( Args: key (str): The key of the list, set, or sorted set to be sorted. store (str): The key where the sorted result will be stored. - by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. + by_pattern (Optional[str]): A pattern to sort by external keys instead of by the elements stored at the key themselves. + The pattern should contain an asterisk (*) as a placeholder for the element values, where the value + from the key replaces the asterisk to create the key name. For example, if `key` contains IDs of objects, + `by_pattern` can be used to sort these IDs based on an attribute of the objects, like their weights or + timestamps. + E.g., if `by_pattern` is `weight_*`, the command will sort the elements by the values of the + keys `weight_`. + If not provided, elements are sorted by their value. limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. - get_patterns (Optional[List[str]]): One or more patterns to extract values to return. + get_pattern (Optional[str]): A pattern used to retrieve external keys' values, instead of the elements at `key`. + The pattern should contain an asterisk (*) as a placeholder for the element values, where the value + from `key` replaces the asterisk to create the key name. This allows the sorted elements to be + transformed based on the related keys values. For example, if `key` contains IDs of users, `get_pattern` + can be used to retrieve specific attributes of these users, such as their names or email addresses. + E.g., if `get_pattern` is `name_*`, the command will return the values of the keys `name_` + for each sorted element. Multiple `get_pattern` arguments can be provided to retrieve multiple attributes. + The special value `#` can be used to include the actual element from `key` being sorted. + If not provided, only the sorted elements themselves are returned. order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index 22769184cb..e24a0fa2bb 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -2765,11 +2765,28 @@ def sort( Args: key (str): The key of the list, set, or sorted set to be sorted. - by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. + by_pattern (Optional[str]): A pattern to sort by external keys instead of by the elements stored at the key themselves. + The pattern should contain an asterisk (*) as a placeholder for the element values, where the value + from the key replaces the asterisk to create the key name. For example, if `key` contains IDs of objects, + `by_pattern` can be used to sort these IDs based on an attribute of the objects, like their weights or + timestamps. + E.g., if `by_pattern` is `weight_*`, the command will sort the elements by the values of the + keys `weight_`. + If not provided, elements are sorted by their value. limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. - get_patterns (Optional[List[str]]): One or more patterns to extract values to return. - order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). - alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + get_pattern (Optional[str]): A pattern used to retrieve external keys' values, instead of the elements at `key`. + The pattern should contain an asterisk (*) as a placeholder for the element values, where the value + from `key` replaces the asterisk to create the key name. This allows the sorted elements to be + transformed based on the related keys values. For example, if `key` contains IDs of users, `get_pattern` + can be used to retrieve specific attributes of these users, such as their names or email addresses. + E.g., if `get_pattern` is `name_*`, the command will return the values of the keys `name_` + for each sorted element. Multiple `get_pattern` arguments can be provided to retrieve multiple attributes. + The special value `#` can be used to include the actual element from `key` being sorted. + If not provided, only the sorted elements themselves are returned. + order (Optional[OrderBy]): Specifies the order to sort the elements. + Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). + alpha (Optional[bool]): When `True`, sorts elements lexicographically. When `False` (default), sorts elements numerically. + Use this when the list, set, or sorted set contains string values that cannot be converted into double precision floating point numbers. Command response: List[Optional[str]]: Returns a list of sorted elements. @@ -2796,12 +2813,28 @@ def sort_store( Args: key (str): The key of the list, set, or sorted set to be sorted. - store (str): The key where the sorted result will be stored. - by_pattern (Optional[str]): A pattern to sort by. If not provided, elements are sorted by their value. + by_pattern (Optional[str]): A pattern to sort by external keys instead of by the elements stored at the key themselves. + The pattern should contain an asterisk (*) as a placeholder for the element values, where the value + from the key replaces the asterisk to create the key name. For example, if `key` contains IDs of objects, + `by_pattern` can be used to sort these IDs based on an attribute of the objects, like their weights or + timestamps. + E.g., if `by_pattern` is `weight_*`, the command will sort the elements by the values of the + keys `weight_`. + If not provided, elements are sorted by their value. limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. - get_patterns (Optional[List[str]]): One or more patterns to extract values to return. - order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). - alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + get_pattern (Optional[str]): A pattern used to retrieve external keys' values, instead of the elements at `key`. + The pattern should contain an asterisk (*) as a placeholder for the element values, where the value + from `key` replaces the asterisk to create the key name. This allows the sorted elements to be + transformed based on the related keys values. For example, if `key` contains IDs of users, `get_pattern` + can be used to retrieve specific attributes of these users, such as their names or email addresses. + E.g., if `get_pattern` is `name_*`, the command will return the values of the keys `name_` + for each sorted element. Multiple `get_pattern` arguments can be provided to retrieve multiple attributes. + The special value `#` can be used to include the actual element from `key` being sorted. + If not provided, only the sorted elements themselves are returned. + order (Optional[OrderBy]): Specifies the order to sort the elements. + Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). + alpha (Optional[bool]): When `True`, sorts elements lexicographically. When `False` (default), sorts elements numerically. + Use this when the list, set, or sorted set contains string values that cannot be converted into double precision floating point numbers. Command response: int: The number of elements in the sorted key stored at `store`. @@ -2837,8 +2870,10 @@ def sort( Args: key (str): The key of the list, set, or sorted set to be sorted. limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. - order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). - alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + order (Optional[OrderBy]): Specifies the order to sort the elements. + Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). + alpha (Optional[bool]): When `True`, sorts elements lexicographically. When `False` (default), sorts elements numerically. + Use this when the list, set, or sorted set contains string values that cannot be converted into double precision floating point numbers. Command response: List[Optional[str]]: A list of sorted elements. @@ -2865,8 +2900,10 @@ def sort_store( key (str): The key of the list, set, or sorted set to be sorted. store (str): The key where the sorted result will be stored. limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. - order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). - alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + order (Optional[OrderBy]): Specifies the order to sort the elements. + Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). + alpha (Optional[bool]): When `True`, sorts elements lexicographically. When `False` (default), sorts elements numerically. + Use this when the list, set, or sorted set contains string values that cannot be converted into double precision floating point numbers. Command response: int: The number of elements in the sorted key stored at `store`. From d8bd446ac9aa62392b9ac3a1aa3a6ded3b1784aa Mon Sep 17 00:00:00 2001 From: GilboaAWS Date: Wed, 29 May 2024 11:39:56 +0000 Subject: [PATCH 10/24] Fix return from function --- python/python/glide/async_commands/cluster_commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/python/glide/async_commands/cluster_commands.py b/python/python/glide/async_commands/cluster_commands.py index fef60b3d35..5823729c3d 100644 --- a/python/python/glide/async_commands/cluster_commands.py +++ b/python/python/glide/async_commands/cluster_commands.py @@ -413,7 +413,7 @@ async def sort( """ args = _build_sort_args(key, None, limit, None, order, alpha) result = await self._execute_command(RequestType.Sort, args) - return cast(List[Optional[str]], result) + return cast(List[str], result) async def sort_store( self, From 216123a376ad2dd8c16bb2e642fda775f380a68e Mon Sep 17 00:00:00 2001 From: GilboaAWS Date: Wed, 29 May 2024 11:54:33 +0000 Subject: [PATCH 11/24] Addressed comments. Renamed store to destination fixed standalone client arg to RedisClient instead of TRedisClient. --- .../glide/async_commands/cluster_commands.py | 6 +- .../async_commands/standalone_commands.py | 6 +- .../glide/async_commands/transaction.py | 11 ++-- python/python/tests/test_async_client.py | 65 +++++++++---------- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/python/python/glide/async_commands/cluster_commands.py b/python/python/glide/async_commands/cluster_commands.py index 5823729c3d..ad51ffd866 100644 --- a/python/python/glide/async_commands/cluster_commands.py +++ b/python/python/glide/async_commands/cluster_commands.py @@ -418,7 +418,7 @@ async def sort( async def sort_store( self, key: str, - store: str, + destination: str, limit: Optional[Limit] = None, order: Optional[OrderBy] = None, alpha: Optional[bool] = None, @@ -432,7 +432,7 @@ async def sort_store( Args: key (str): The key of the list, set, or sorted set to be sorted. - store (str): The key where the sorted result will be stored. + destination (str): The key where the sorted result will be stored. limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). @@ -449,6 +449,6 @@ async def sort_store( >>> await client.lrange("sorted_list", 0, -1) ['1', '2', '3'] """ - args = _build_sort_args(key, None, limit, None, order, alpha, store=store) + args = _build_sort_args(key, None, limit, None, order, alpha, store=destination) result = await self._execute_command(RequestType.Sort, args) return cast(int, result) diff --git a/python/python/glide/async_commands/standalone_commands.py b/python/python/glide/async_commands/standalone_commands.py index 42bb9662c1..d5c3fc3386 100644 --- a/python/python/glide/async_commands/standalone_commands.py +++ b/python/python/glide/async_commands/standalone_commands.py @@ -330,7 +330,7 @@ async def sort( async def sort_store( self, key: str, - store: str, + destination: str, by_pattern: Optional[str] = None, limit: Optional[Limit] = None, get_patterns: Optional[List[str]] = None, @@ -346,7 +346,7 @@ async def sort_store( Args: key (str): The key of the list, set, or sorted set to be sorted. - store (str): The key where the sorted result will be stored. + destination (str): The key where the sorted result will be stored. by_pattern (Optional[str]): A pattern to sort by external keys instead of by the elements stored at the key themselves. The pattern should contain an asterisk (*) as a placeholder for the element values, where the value from the key replaces the asterisk to create the key name. For example, if `key` contains IDs of objects, @@ -379,7 +379,7 @@ async def sort_store( ['1', '2', '3'] """ args = _build_sort_args( - key, by_pattern, limit, get_patterns, order, alpha, store=store + key, by_pattern, limit, get_patterns, order, alpha, store=destination ) result = await self._execute_command(RequestType.Sort, args) return cast(int, result) diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index e24a0fa2bb..4a22f9b5c2 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -2797,7 +2797,7 @@ def sort( def sort_store( self: TTransaction, key: str, - store: str, + destination: str, by_pattern: Optional[str] = None, limit: Optional[Limit] = None, get_patterns: Optional[List[str]] = None, @@ -2813,6 +2813,7 @@ def sort_store( Args: key (str): The key of the list, set, or sorted set to be sorted. + destination (str): The key where the sorted result will be stored. by_pattern (Optional[str]): A pattern to sort by external keys instead of by the elements stored at the key themselves. The pattern should contain an asterisk (*) as a placeholder for the element values, where the value from the key replaces the asterisk to create the key name. For example, if `key` contains IDs of objects, @@ -2840,7 +2841,7 @@ def sort_store( int: The number of elements in the sorted key stored at `store`. """ args = _build_sort_args( - key, by_pattern, limit, get_patterns, order, alpha, store=store + key, by_pattern, limit, get_patterns, order, alpha, store=destination ) return self.append_command(RequestType.Sort, args) @@ -2884,7 +2885,7 @@ def sort( def sort_store( self: TTransaction, key: str, - store: str, + destination: str, limit: Optional[Limit] = None, order: Optional[OrderBy] = None, alpha: Optional[bool] = None, @@ -2898,7 +2899,7 @@ def sort_store( Args: key (str): The key of the list, set, or sorted set to be sorted. - store (str): The key where the sorted result will be stored. + destination (str): The key where the sorted result will be stored. limit (Optional[Limit]): Limiting the range of the query by setting offset and result count. See `Limit` class for more information. order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). @@ -2908,7 +2909,7 @@ def sort_store( Command response: int: The number of elements in the sorted key stored at `store`. """ - args = _build_sort_args(key, None, limit, None, order, alpha, store=store) + args = _build_sort_args(key, None, limit, None, order, alpha, store=destination) return self.append_command(RequestType.Sort, args) # TODO: add all CLUSTER commands diff --git a/python/python/tests/test_async_client.py b/python/python/tests/test_async_client.py index 04b3abb05e..286e11e397 100644 --- a/python/python/tests/test_async_client.py +++ b/python/python/tests/test_async_client.py @@ -3420,7 +3420,7 @@ async def test_type(self, redis_client: TRedisClient): @pytest.mark.parametrize("cluster_mode", [False]) @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_sort_and_sort_store_with_get_or_by_args( - self, redis_client: TRedisClient + self, redis_client: RedisClient ): key = "{SameSlotKey}" + get_random_string(10) store = "{SameSlotKey}" + get_random_string(10) @@ -3440,39 +3440,38 @@ async def test_sort_and_sort_store_with_get_or_by_args( assert await redis_client.hset(user_key5, {"name": "Eve", "age": "40"}) == 2 assert await redis_client.lpush("user_ids", ["5", "4", "3", "2", "1"]) == 5 - if isinstance(redis_client, RedisClient): - # Test sort with all arguments - assert await redis_client.lpush(key, ["3", "1", "2"]) == 3 - result = await redis_client.sort( - key, - limit=Limit(0, 2), - get_patterns=["user:*->name"], - order=OrderBy.ASC, - alpha=True, - ) - assert result == ["Alice", "Bob"] + # Test sort with all arguments + assert await redis_client.lpush(key, ["3", "1", "2"]) == 3 + result = await redis_client.sort( + key, + limit=Limit(0, 2), + get_patterns=["user:*->name"], + order=OrderBy.ASC, + alpha=True, + ) + assert result == ["Alice", "Bob"] - # Test sort_store with all arguments - sort_store_result = await redis_client.sort_store( - key, - store, - limit=Limit(0, 2), - get_patterns=["user:*->name"], - order=OrderBy.ASC, - alpha=True, - ) - assert sort_store_result == 2 - sorted_list = await redis_client.lrange(store, 0, -1) - assert sorted_list == ["Alice", "Bob"] - - # Test sort with `by` argument - result = await redis_client.sort( - "user_ids", - by_pattern="user:*->age", - get_patterns=["user:*->name"], - alpha=True, - ) - assert result == ["Dave", "Bob", "Alice", "Charlie", "Eve"] + # Test sort_store with all arguments + sort_store_result = await redis_client.sort_store( + key, + store, + limit=Limit(0, 2), + get_patterns=["user:*->name"], + order=OrderBy.ASC, + alpha=True, + ) + assert sort_store_result == 2 + sorted_list = await redis_client.lrange(store, 0, -1) + assert sorted_list == ["Alice", "Bob"] + + # Test sort with `by` argument + result = await redis_client.sort( + "user_ids", + by_pattern="user:*->age", + get_patterns=["user:*->name"], + alpha=True, + ) + assert result == ["Dave", "Bob", "Alice", "Charlie", "Eve"] @pytest.mark.parametrize("cluster_mode", [True, False]) @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) From 4c86e524909b3aa48e9f0f5ac803c70d1dcda629 Mon Sep 17 00:00:00 2001 From: GilboaAWS Date: Wed, 29 May 2024 12:00:38 +0000 Subject: [PATCH 12/24] Changed doc according to comments. --- python/python/glide/async_commands/cluster_commands.py | 2 +- python/python/glide/async_commands/standalone_commands.py | 2 +- python/python/glide/async_commands/transaction.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/python/glide/async_commands/cluster_commands.py b/python/python/glide/async_commands/cluster_commands.py index ad51ffd866..d6aac57b83 100644 --- a/python/python/glide/async_commands/cluster_commands.py +++ b/python/python/glide/async_commands/cluster_commands.py @@ -426,7 +426,7 @@ async def sort_store( """ Sorts the elements in the list, set, or sorted set at `key` and stores the result in `store`. When in cluster mode, `key` and `store` must map to the same hash slot. - To get the sort result, see `sort`. + To get the sort result without storing it into a key, see `sort`. See https://valkey.io/commands/sort for more details. diff --git a/python/python/glide/async_commands/standalone_commands.py b/python/python/glide/async_commands/standalone_commands.py index d5c3fc3386..55b0f86deb 100644 --- a/python/python/glide/async_commands/standalone_commands.py +++ b/python/python/glide/async_commands/standalone_commands.py @@ -340,7 +340,7 @@ async def sort_store( """ Sorts the elements in the list, set, or sorted set at `key` and stores the result in `store`. The `sort` command can be used to sort elements based on different criteria, apply transformations on sorted elements, and store the result in a new key. - To get the sort result, see `sort`. + To get the sort result without storing it into a key, see `sort`. See https://valkey.io/commands/sort for more details. diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index 4a22f9b5c2..520c656262 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -2807,7 +2807,7 @@ def sort_store( """ Sorts the elements in the list, set, or sorted set at `key` and stores the result in `store`. The `sort` command can be used to sort elements based on different criteria, apply transformations on sorted elements, and store the result in a new key. - To get the sort result, see `sort`. + To get the sort result without storing it into a key, see `sort`. See https://valkey.io/commands/sort for more details. @@ -2893,7 +2893,7 @@ def sort_store( """ Sorts the elements in the list, set, or sorted set at `key` and stores the result in `store`. When in cluster mode, `key` and `store` must map to the same hash slot. - To get the sort result, see `sort`. + To get the sort result without storing it into a key, see `sort`. See https://valkey.io/commands/sort for more details. From 7e44dd9c80a1bfa59aafea9fa2164212f6458042 Mon Sep 17 00:00:00 2001 From: Gilboab <97948000+GilboaAWS@users.noreply.github.com> Date: Wed, 29 May 2024 15:14:23 +0300 Subject: [PATCH 13/24] Apply suggestions from code review Co-authored-by: Aaron <69273634+aaron-congo@users.noreply.github.com> --- python/python/glide/async_commands/cluster_commands.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/python/glide/async_commands/cluster_commands.py b/python/python/glide/async_commands/cluster_commands.py index d6aac57b83..24be233982 100644 --- a/python/python/glide/async_commands/cluster_commands.py +++ b/python/python/glide/async_commands/cluster_commands.py @@ -405,10 +405,10 @@ async def sort( >>> await client.lpush("mylist", '2', '1', '2', '3', '3', '1') >>> await client.sort("mylist", limit=Limit(2, 3)) - ['2', '2', '3'] + ['1', '2', '2'] >>> await client.lpush("mylist", "a", "b", "c", "d") - >>> await client.sort("mylist", limit=Limit(3, 2), order=OrderBy.DESC, alpha=True) + >>> await client.sort("mylist", limit=Limit(2, 2), order=OrderBy.DESC, alpha=True) ['b', 'a'] """ args = _build_sort_args(key, None, limit, None, order, alpha) From 91f9157e643960a0da37086bbb827c17245a9a6e Mon Sep 17 00:00:00 2001 From: Gilboab <97948000+GilboaAWS@users.noreply.github.com> Date: Wed, 29 May 2024 16:17:56 +0300 Subject: [PATCH 14/24] Remove duplicated line Co-authored-by: Aaron <69273634+aaron-congo@users.noreply.github.com> --- python/python/glide/async_commands/command_args.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/python/python/glide/async_commands/command_args.py b/python/python/glide/async_commands/command_args.py index 1ba3c779e0..2eddf6c352 100644 --- a/python/python/glide/async_commands/command_args.py +++ b/python/python/glide/async_commands/command_args.py @@ -28,8 +28,6 @@ def __init__(self, offset: int, count: int): self.offset = offset self.count = count - self.count = count - class OrderBy(Enum): """ From 158ea718e20e5bda637cf6bd9f05f868b3de3fdc Mon Sep 17 00:00:00 2001 From: Gilboab <97948000+GilboaAWS@users.noreply.github.com> Date: Wed, 29 May 2024 16:31:34 +0300 Subject: [PATCH 15/24] Remove unused import of Tuple --- python/python/glide/async_commands/cluster_commands.py | 2 +- python/python/glide/async_commands/command_args.py | 2 +- python/python/glide/async_commands/standalone_commands.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/python/glide/async_commands/cluster_commands.py b/python/python/glide/async_commands/cluster_commands.py index 24be233982..e010f1f54b 100644 --- a/python/python/glide/async_commands/cluster_commands.py +++ b/python/python/glide/async_commands/cluster_commands.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, List, Mapping, Optional, Tuple, cast +from typing import Dict, List, Mapping, Optional, cast from glide.async_commands.command_args import Limit, OrderBy from glide.async_commands.core import CoreCommands, InfoSection, _build_sort_args diff --git a/python/python/glide/async_commands/command_args.py b/python/python/glide/async_commands/command_args.py index 2eddf6c352..00f4ca3367 100644 --- a/python/python/glide/async_commands/command_args.py +++ b/python/python/glide/async_commands/command_args.py @@ -1,7 +1,7 @@ # Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 from enum import Enum -from typing import List, Optional, Tuple, Union +from typing import List, Optional, Union class Limit: diff --git a/python/python/glide/async_commands/standalone_commands.py b/python/python/glide/async_commands/standalone_commands.py index 55b0f86deb..3e9de56d4f 100644 --- a/python/python/glide/async_commands/standalone_commands.py +++ b/python/python/glide/async_commands/standalone_commands.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, List, Mapping, Optional, Tuple, cast +from typing import Dict, List, Mapping, Optional, cast from glide.async_commands.command_args import Limit, OrderBy from glide.async_commands.core import CoreCommands, InfoSection, _build_sort_args From 08070651ad4f76a4ea9e657af7667c34456f1081 Mon Sep 17 00:00:00 2001 From: Gilboab <97948000+GilboaAWS@users.noreply.github.com> Date: Wed, 29 May 2024 16:49:51 +0300 Subject: [PATCH 16/24] Apply suggestions from code review Co-authored-by: Aaron <69273634+aaron-congo@users.noreply.github.com> --- python/python/glide/async_commands/standalone_commands.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/python/glide/async_commands/standalone_commands.py b/python/python/glide/async_commands/standalone_commands.py index 3e9de56d4f..1155d41cdc 100644 --- a/python/python/glide/async_commands/standalone_commands.py +++ b/python/python/glide/async_commands/standalone_commands.py @@ -314,8 +314,8 @@ async def sort( ['1', '2', '3'] >>> await client.sort("mylist", order=OrderBy.DESC) ['3', '2', '1'] - >>> await client.lpush("mylist", 2, 1, 2, 3, 3, 1) - >>> await client.sort("mylist", limit=Limit(2, 3)) + >>> await client.lpush("mylist2", 2, 1, 2, 3, 3, 1) + >>> await client.sort("mylist2", limit=Limit(2, 3)) ['2', '2', '3'] >>> await client.hset("user:1", "name", "Alice", "age", 30) >>> await client.hset("user:2", "name", "Bob", "age", 25) From 49a2bd4fde8a49a5e2e102b25c800db51342eaaa Mon Sep 17 00:00:00 2001 From: GilboaAWS Date: Wed, 29 May 2024 14:04:07 +0000 Subject: [PATCH 17/24] fixed tests. --- python/python/tests/test_async_client.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/python/python/tests/test_async_client.py b/python/python/tests/test_async_client.py index 286e11e397..8097f3ced5 100644 --- a/python/python/tests/test_async_client.py +++ b/python/python/tests/test_async_client.py @@ -3473,6 +3473,14 @@ async def test_sort_and_sort_store_with_get_or_by_args( ) assert result == ["Dave", "Bob", "Alice", "Charlie", "Eve"] + # Test Limit with count 0 + result = await redis_client.sort( + "user_ids", + limit=Limit(0, 0), + alpha=True, + ) + assert result == [] + @pytest.mark.parametrize("cluster_mode", [True, False]) @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_sort_and_sort_store_without_get_or_by_args( @@ -3494,7 +3502,7 @@ async def test_sort_and_sort_store_without_get_or_by_args( # Test each argument separately assert await redis_client.lpush(key, ["5", "2", "4", "1", "3"]) == 5 - # by_pattern argument + # Test w/o flags result = await redis_client.sort(key) assert result == ["1", "2", "3", "4", "5"] From c3649d5ece781cfc27e5ba572912fae2577958f2 Mon Sep 17 00:00:00 2001 From: Gilboab <97948000+GilboaAWS@users.noreply.github.com> Date: Sun, 2 Jun 2024 11:46:13 +0300 Subject: [PATCH 18/24] Fixed doc. --- .../glide/async_commands/standalone_commands.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/python/python/glide/async_commands/standalone_commands.py b/python/python/glide/async_commands/standalone_commands.py index 1155d41cdc..2b21fc9f1c 100644 --- a/python/python/glide/async_commands/standalone_commands.py +++ b/python/python/glide/async_commands/standalone_commands.py @@ -302,8 +302,10 @@ async def sort( for each sorted element. Multiple `get_pattern` arguments can be provided to retrieve multiple attributes. The special value `#` can be used to include the actual element from `key` being sorted. If not provided, only the sorted elements themselves are returned. - order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). - alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + order (Optional[OrderBy]): Specifies the order to sort the elements. + Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). + alpha (Optional[bool]): When `True`, sorts elements lexicographically. When `False` (default), sorts elements numerically. + Use this when the list, set, or sorted set contains string values that cannot be converted into double precision floating point Returns: List[Optional[str]]: Returns a list of sorted elements. @@ -365,8 +367,10 @@ async def sort_store( for each sorted element. Multiple `get_pattern` arguments can be provided to retrieve multiple attributes. The special value `#` can be used to include the actual element from `key` being sorted. If not provided, only the sorted elements themselves are returned. - order (Optional[OrderBy]): Specifies the order to sort the elements. Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). - alpha (Optional[bool]): Whether to sort elements lexicographically. If `False`, elements are sorted numerically. + order (Optional[OrderBy]): Specifies the order to sort the elements. + Can be `OrderBy.ASC` (ascending) or `OrderBy.DESC` (descending). + alpha (Optional[bool]): When `True`, sorts elements lexicographically. When `False` (default), sorts elements numerically. + Use this when the list, set, or sorted set contains string values that cannot be converted into double precision floating point Returns: int: The number of elements in the sorted key stored at `store`. From 911ebdfd1f30c18e1023c804695a6ddf27084c4d Mon Sep 17 00:00:00 2001 From: GilboaAWS Date: Sun, 2 Jun 2024 09:38:34 +0000 Subject: [PATCH 19/24] Added tests that return None in a list. --- python/python/tests/test_async_client.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/python/python/tests/test_async_client.py b/python/python/tests/test_async_client.py index 8097f3ced5..48abd147fa 100644 --- a/python/python/tests/test_async_client.py +++ b/python/python/tests/test_async_client.py @@ -3473,6 +3473,25 @@ async def test_sort_and_sort_store_with_get_or_by_args( ) assert result == ["Dave", "Bob", "Alice", "Charlie", "Eve"] + # Test sort with `by` argument with missing keys to sort by + assert await redis_client.lpush("user_ids", ["a"]) == 6 + result = await redis_client.sort( + "user_ids", + by_pattern="user:*->age", + get_patterns=["user:*->name"], + alpha=True, + ) + assert result == [None, "Dave", "Bob", "Alice", "Charlie", "Eve"] + + # Test sort with `by` argument with missing keys to sort by + result = await redis_client.sort( + "user_ids", + by_pattern="user:*->name", + get_patterns=["user:*->age"], + alpha=True, + ) + assert result == [None, "30", "25", "35", "20", "40"] + # Test Limit with count 0 result = await redis_client.sort( "user_ids", From 215140dc139ad37cef0f218d0e09fccd0c18f714 Mon Sep 17 00:00:00 2001 From: GilboaAWS Date: Sun, 2 Jun 2024 09:45:53 +0000 Subject: [PATCH 20/24] Added entry in the CHANGELOG for SORT in python. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b2e779163..8824030f35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * Python: Added GETDEL command ([#1514](https://github.com/aws/glide-for-redis/pull/1514)) * Python: Added ZINTER, ZUNION commands ([#1478](https://github.com/aws/glide-for-redis/pull/1478)) * Python: Added SINTERCARD command ([#1511](https://github.com/aws/glide-for-redis/pull/1511)) +* Python: Added SORT command ([#1439](https://github.com/aws/glide-for-redis/pull/1439)) ## 0.4.1 (2024-02-06) From 6f214f202559c7e891465599e3e4fc6b86688461 Mon Sep 17 00:00:00 2001 From: Gilboab <97948000+GilboaAWS@users.noreply.github.com> Date: Mon, 3 Jun 2024 17:09:17 +0300 Subject: [PATCH 21/24] Update python/python/glide/async_commands/command_args.py --- python/python/glide/async_commands/command_args.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/python/glide/async_commands/command_args.py b/python/python/glide/async_commands/command_args.py index 00f4ca3367..d308ca9ed7 100644 --- a/python/python/glide/async_commands/command_args.py +++ b/python/python/glide/async_commands/command_args.py @@ -15,7 +15,7 @@ class Limit: such as [ZRANGE](https://valkey.io/commands/zrange), [SORT](https://valkey.io/commands/sort/), and others. Args: - offset (int): The starting position of the range. + offset (int): The starting position of the range, zero based. count (int): The maximum number of elements to include in the range. A negative count returns all elements from the offset. From 952e0e00596a0989cd956c7779c6957ff3279493 Mon Sep 17 00:00:00 2001 From: GilboaAWS Date: Sun, 2 Jun 2024 09:45:53 +0000 Subject: [PATCH 22/24] Added entry in the CHANGELOG for SORT in python. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8824030f35..15e4177168 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ #### Fixes * Node: Fix set command bug with expiry option ([#1508](https://github.com/aws/glide-for-redis/pull/1508)) +* Python: Added SORT command ([#1439](https://github.com/aws/glide-for-redis/pull/1439)) ## 0.4.0 (2024-05-26) From dd4cac36926560c4a7cfcdfa052d883a516f53ac Mon Sep 17 00:00:00 2001 From: Gilboab <97948000+GilboaAWS@users.noreply.github.com> Date: Tue, 4 Jun 2024 16:02:09 +0300 Subject: [PATCH 23/24] Update CHANGELOG.md Co-authored-by: Yury-Fridlyand --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15e4177168..8824030f35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,6 @@ #### Fixes * Node: Fix set command bug with expiry option ([#1508](https://github.com/aws/glide-for-redis/pull/1508)) -* Python: Added SORT command ([#1439](https://github.com/aws/glide-for-redis/pull/1439)) ## 0.4.0 (2024-05-26) From f89eadc4ca07055c63fa773f1e4134a2dfa8fb97 Mon Sep 17 00:00:00 2001 From: Gilboab <97948000+GilboaAWS@users.noreply.github.com> Date: Wed, 5 Jun 2024 12:12:18 +0300 Subject: [PATCH 24/24] Updated Cluster's Transaction's Sort response to non None value. Co-authored-by: Yury-Fridlyand --- python/python/glide/async_commands/transaction.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index 520c656262..c33497e7ed 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -2877,7 +2877,7 @@ def sort( Use this when the list, set, or sorted set contains string values that cannot be converted into double precision floating point numbers. Command response: - List[Optional[str]]: A list of sorted elements. + List[str]: A list of sorted elements. """ args = _build_sort_args(key, None, limit, None, order, alpha) return self.append_command(RequestType.Sort, args)