From d9f750ba5cd1fc2bb890414b0737b42997cb5a74 Mon Sep 17 00:00:00 2001 From: Shoham Elias <116083498+shohamazon@users.noreply.github.com> Date: Wed, 17 Jan 2024 19:43:18 +0200 Subject: [PATCH] When recieving LPOP/RPOP with count, convert result to Array --- node/src/BaseClient.ts | 50 ++++++++++--- node/tests/SharedTests.ts | 4 +- python/python/glide/async_commands/core.py | 87 +++++++++++++++------- python/python/tests/test_async_client.py | 4 +- 4 files changed, 103 insertions(+), 42 deletions(-) diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index 7ca3a9349b..52342fa9cd 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -632,20 +632,33 @@ export class BaseClient { } /** Removes and returns the first elements of the list stored at `key`. - * By default, the command pops a single element from the beginning of the list. - * When `count` is provided, the command pops up to `count` elements, depending on the list's length. + * The command pops a single element from the beginning of the list. * See https://redis.io/commands/lpop/ for details. * * @param key - The key of the list. - * @param count - The count of the elements to pop from the list. - * @returns The value of the first element if `count` is not provided. If `count` is provided, a list of the popped elements will be returned depending on the list's length. + * @returns The value of the first element. * If `key` does not exist null will be returned. * If `key` holds a value that is not a list, an error is raised. */ public lpop( key: string, - count?: number - ): Promise { + ): Promise { + return this.createWritePromise(createLPop(key)); + } + + /** Removes and returns up to `count` elements of the list stored at `key`, depending on the list's length. + * See https://redis.io/commands/lpop/ for details. + * + * @param key - The key of the list. + * @param count - The count of the elements to pop from the list. + * @returns A list of the popped elements will be returned depending on the list's length. + * If `key` does not exist null will be returned. + * If `key` holds a value that is not a list, an error is raised. + */ + public lpopCount( + key: string, + count: number + ): Promise { return this.createWritePromise(createLPop(key, count)); } @@ -730,20 +743,33 @@ export class BaseClient { } /** Removes and returns the last elements of the list stored at `key`. - * By default, the command pops a single element from the end of the list. - * When `count` is provided, the command pops up to `count` elements, depending on the list's length. + * The command pops a single element from the end of the list. * See https://redis.io/commands/rpop/ for details. * * @param key - The key of the list. - * @param count - The count of the elements to pop from the list. - * @returns The value of the last element if `count` is not provided. If `count` is provided, list of popped elements will be returned depending on the list's length. + * @returns The value of the last element. * If `key` does not exist null will be returned. * If `key` holds a value that is not a list, an error is raised. */ public rpop( key: string, - count?: number - ): Promise { + ): Promise { + return this.createWritePromise(createRPop(key)); + } + + /** Removes and returns up to `count` elements from the list stored at `key`, depending on the list's length. + * See https://redis.io/commands/rpop/ for details. + * + * @param key - The key of the list. + * @param count - The count of the elements to pop from the list. + * @returns A list of popped elements will be returned depending on the list's length. + * If `key` does not exist null will be returned. + * If `key` holds a value that is not a list, an error is raised. + */ + public rpopCount( + key: string, + count: number + ): Promise { return this.createWritePromise(createRPop(key, count)); } diff --git a/node/tests/SharedTests.ts b/node/tests/SharedTests.ts index 84df565641..5683440c5e 100644 --- a/node/tests/SharedTests.ts +++ b/node/tests/SharedTests.ts @@ -755,7 +755,7 @@ export function runBaseTests(config: { "value3", "value4", ]); - expect(await client.lpop(key, 2)).toEqual(["value2", "value3"]); + expect(await client.lpopCount(key, 2)).toEqual(["value2", "value3"]); expect(await client.lrange("nonExistingKey", 0, -1)).toEqual( [] ); @@ -899,7 +899,7 @@ export function runBaseTests(config: { const valueList = ["value1", "value2", "value3", "value4"]; expect(await client.rpush(key, valueList)).toEqual(4); expect(await client.rpop(key)).toEqual("value4"); - expect(await client.rpop(key, 2)).toEqual(["value3", "value2"]); + expect(await client.rpopCount(key, 2)).toEqual(["value3", "value2"]); expect(await client.rpop("nonExistingKey")).toEqual(null); }); }, diff --git a/python/python/glide/async_commands/core.py b/python/python/glide/async_commands/core.py index ef0cdef8d8..d3c3b18766 100644 --- a/python/python/glide/async_commands/core.py +++ b/python/python/glide/async_commands/core.py @@ -568,37 +568,55 @@ async def lpush(self, key: str, elements: List[str]) -> int: int, await self._execute_command(RequestType.LPush, [key] + elements) ) - async def lpop( - self, key: str, count: Optional[int] = None - ) -> Optional[Union[str, List[str]]]: + async def lpop(self, key: str) -> Optional[str]: """Remove and return the first elements of the list stored at `key`. - By default, the command pops a single element from the beginning of the list. - When `count` is provided, the command pops up to `count` elements, depending on the list's length. + The command pops a single element from the beginning of the list. See https://redis.io/commands/lpop/ for details. Args: key (str): The key of the list. - count (Optional[int]): The count of elements to pop from the list. Default is to pop a single element. Returns: - Optional[Union[str, List[str]]: The value of the first element if `count` is not provided. - If `count` is provided, a list of popped elements will be returned depending on the list's length. + Optional[str]: The value of the first element. If `key` does not exist, None will be returned. If `key` holds a value that is not a list, an error is returned. Examples: >>> await client.lpop("my_list") "value1" - >>> await client.lpop("my_list", 2) - ["value2", "value3"] >>> await client.lpop("non_exiting_key") None """ - args: List[str] = [key] if count is None else [key, str(count)] return cast( - Optional[Union[str, List[str]]], - await self._execute_command(RequestType.LPop, args), + Optional[str], + await self._execute_command(RequestType.LPop, [key]), + ) + + async def lpop_count(self, key: str, count: int) -> Optional[List[str]]: + """Remove and return up to `count` elements from the list stored at `key`, depending on the list's length. + See https://redis.io/commands/lpop/ for details. + + Args: + key (str): The key of the list. + count (int): The count of elements to pop from the list. + + Returns: + Optional[List[str]]: A a list of popped elements will be returned depending on the list's length. + If `key` does not exist, None will be returned. + If `key` holds a value that is not a list, an error is returned. + + Examples: + + >>> await client.lpop("my_list", 2) + ["value1", "value2"] + >>> await client.lpop("non_exiting_key" , 3) + None + """ + + return cast( + Optional[List[str]], + await self._execute_command(RequestType.LPop, [key, str(count)]), ) async def lrange(self, key: str, start: int, end: int) -> List[str]: @@ -660,37 +678,54 @@ async def rpush(self, key: str, elements: List[str]) -> int: int, await self._execute_command(RequestType.RPush, [key] + elements) ) - async def rpop( - self, key: str, count: Optional[int] = None - ) -> Optional[Union[str, List[str]]]: + async def rpop(self, key: str, count: Optional[int] = None) -> Optional[str]: """Removes and returns the last elements of the list stored at `key`. - By default, the command pops a single element from the end of the list. - When `count` is provided, the command pops up to `count` elements, depending on the list's length. + The command pops a single element from the end of the list. See https://redis.io/commands/rpop/ for details. Args: key (str): The key of the list. - count (Optional[int]): The count of elements to pop from the list. Default is to pop a single element. Returns: - Optional[Union[str, List[str]]: The value of the last element if `count` is not provided. - If `count` is provided, a list of popped elements will be returned depending on the list's length. + Optional[str]: The value of the last element. If `key` does not exist, None will be returned. If `key` holds a value that is not a list, an error is returned. Examples: >>> await client.rpop("my_list") "value1" - >>> await client.rpop("my_list", 2) - ["value2", "value3"] >>> await client.rpop("non_exiting_key") None """ - args: List[str] = [key] if count is None else [key, str(count)] return cast( - Optional[Union[str, List[str]]], - await self._execute_command(RequestType.RPop, args), + Optional[str], + await self._execute_command(RequestType.RPop, [key]), + ) + + async def rpop_count(self, key: str, count: int) -> Optional[List[str]]: + """Removes and returns up to `count` elements from the list stored at `key`, depending on the list's length. + See https://redis.io/commands/rpop/ for details. + + Args: + key (str): The key of the list. + count (int): The count of elements to pop from the list. + + Returns: + Optional[List[str]: A list of popped elements will be returned depending on the list's length. + If `key` does not exist, None will be returned. + If `key` holds a value that is not a list, an error is returned. + + Examples: + >>> await client.rpop("my_list", 2) + ["value1", "value2"] + >>> await client.rpop("non_exiting_key" , 7) + None + """ + + return cast( + Optional[List[str]], + await self._execute_command(RequestType.RPop, [key, str(count)]), ) async def sadd(self, key: str, members: List[str]) -> int: diff --git a/python/python/tests/test_async_client.py b/python/python/tests/test_async_client.py index a6482c65f6..b0b9553383 100644 --- a/python/python/tests/test_async_client.py +++ b/python/python/tests/test_async_client.py @@ -680,7 +680,7 @@ async def test_lpush_lpop_lrange(self, redis_client: TRedisClient): assert await redis_client.lpush(key, value_list) == 4 assert await redis_client.lpop(key) == value_list[-1] assert await redis_client.lrange(key, 0, -1) == value_list[-2::-1] - assert await redis_client.lpop(key, 2) == value_list[-2:0:-1] + assert await redis_client.lpop_count(key, 2) == value_list[-2:0:-1] assert await redis_client.lrange("non_existing_key", 0, -1) == [] assert await redis_client.lpop("non_existing_key") is None @@ -711,7 +711,7 @@ async def test_rpush_rpop(self, redis_client: TRedisClient): assert await redis_client.rpush(key, value_list) == 4 assert await redis_client.rpop(key) == value_list[-1] - assert await redis_client.rpop(key, 2) == value_list[-2:0:-1] + assert await redis_client.rpop_count(key, 2) == value_list[-2:0:-1] assert await redis_client.rpop("non_existing_key") is None @pytest.mark.parametrize("cluster_mode", [True, False])