Skip to content

Commit

Permalink
When recieving LPOP/RPOP with count, convert result to Array
Browse files Browse the repository at this point in the history
  • Loading branch information
shohamazon committed Jan 17, 2024
1 parent 9edc7e2 commit d9f750b
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 42 deletions.
50 changes: 38 additions & 12 deletions node/src/BaseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string | string[] | null> {
): Promise<string | null> {
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<string[] | null> {
return this.createWritePromise(createLPop(key, count));
}

Expand Down Expand Up @@ -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<string | string[] | null> {
): Promise<string | null> {
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<string[] | null> {
return this.createWritePromise(createRPop(key, count));
}

Expand Down
4 changes: 2 additions & 2 deletions node/tests/SharedTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,7 @@ export function runBaseTests<Context>(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(
[]
);
Expand Down Expand Up @@ -899,7 +899,7 @@ export function runBaseTests<Context>(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);
});
},
Expand Down
87 changes: 61 additions & 26 deletions python/python/glide/async_commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]:
Expand Down Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions python/python/tests/test_async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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])
Expand Down

0 comments on commit d9f750b

Please sign in to comment.