Skip to content

Commit

Permalink
Python: added LMOVE and BLMOVE commands (valkey-io#1536)
Browse files Browse the repository at this point in the history
Python: added LMOVE and BLMOVE commands

Co-authored-by: Shoham Elias
  • Loading branch information
GilboaAWS authored Jun 9, 2024
1 parent 2af6a18 commit ddc1425
Show file tree
Hide file tree
Showing 7 changed files with 348 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* 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))
* Node: Added OBJECT ENCODING command ([#1518](https://github.com/aws/glide-for-redis/pull/1518))
* Python: Added LMOVE and BLMOVE commands ([#1536](https://github.com/aws/glide-for-redis/pull/1536))

### Breaking Changes
* Node: Update XREAD to return a Map of Map ([#1494](https://github.com/aws/glide-for-redis/pull/1494))
Expand Down
3 changes: 2 additions & 1 deletion python/python/glide/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0

from glide.async_commands.command_args import Limit, OrderBy
from glide.async_commands.command_args import Limit, ListDirection, OrderBy
from glide.async_commands.core import (
ConditionalChange,
ExpireOptions,
Expand Down Expand Up @@ -98,6 +98,7 @@
"json",
"LexBoundary",
"Limit",
"ListDirection",
"RangeByIndex",
"RangeByLex",
"RangeByScore",
Expand Down
16 changes: 16 additions & 0 deletions python/python/glide/async_commands/command_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,19 @@ class OrderBy(Enum):
"""
DESC: Sort in descending order.
"""


class ListDirection(Enum):
"""
Enumeration representing element popping or adding direction for List commands.
"""

LEFT = "LEFT"
"""
LEFT: Represents the option that elements should be popped from or added to the left side of a list.
"""

RIGHT = "RIGHT"
"""
RIGHT: Represents the option that elements should be popped from or added to the right side of a list.
"""
97 changes: 96 additions & 1 deletion python/python/glide/async_commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
get_args,
)

from glide.async_commands.command_args import Limit, OrderBy
from glide.async_commands.command_args import Limit, ListDirection, OrderBy
from glide.async_commands.sorted_set import (
AggregationType,
InfBound,
Expand Down Expand Up @@ -1496,6 +1496,101 @@ async def linsert(
),
)

async def lmove(
self,
source: str,
destination: str,
where_from: ListDirection,
where_to: ListDirection,
) -> Optional[str]:
"""
Atomically pops and removes the left/right-most element to the list stored at `source`
depending on `where_from`, and pushes the element at the first/last element of the list
stored at `destination` depending on `where_to`.
When in cluster mode, both `source` and `destination` must map to the same hash slot.
See https://valkey.io/commands/lmove/ for details.
Args:
source (str): The key to the source list.
destination (str): The key to the destination list.
where_from (ListDirection): The direction to remove the element from (`ListDirection.LEFT` or `ListDirection.RIGHT`).
where_to (ListDirection): The direction to add the element to (`ListDirection.LEFT` or `ListDirection.RIGHT`).
Returns:
Optional[str]: The popped element, or None if `source` does not exist.
Examples:
>>> client.lpush("testKey1", ["two", "one"])
>>> client.lpush("testKey2", ["four", "three"])
>>> await client.lmove("testKey1", "testKey2", ListDirection.LEFT, ListDirection.LEFT)
"one"
>>> updated_array1 = await client.lrange("testKey1", 0, -1)
["two"]
>>> await client.lrange("testKey2", 0, -1)
["one", "three", "four"]
Since: Redis version 6.2.0.
"""
return cast(
Optional[str],
await self._execute_command(
RequestType.LMove,
[source, destination, where_from.value, where_to.value],
),
)

async def blmove(
self,
source: str,
destination: str,
where_from: ListDirection,
where_to: ListDirection,
timeout: float,
) -> Optional[str]:
"""
Blocks the connection until it pops atomically and removes the left/right-most element to the
list stored at `source` depending on `where_from`, and pushes the element at the first/last element
of the list stored at `destination` depending on `where_to`.
`BLMOVE` is the blocking variant of `LMOVE`.
Notes:
1. When in cluster mode, both `source` and `destination` must map to the same hash slot.
2. `BLMOVE` is a client blocking command, see https://github.com/aws/glide-for-redis/wiki/General-Concepts#blocking-commands for more details and best practices.
See https://valkey.io/commands/blmove/ for details.
Args:
source (str): The key to the source list.
destination (str): The key to the destination list.
where_from (ListDirection): The direction to remove the element from (`ListDirection.LEFT` or `ListDirection.RIGHT`).
where_to (ListDirection): The direction to add the element to (`ListDirection.LEFT` or `ListDirection.RIGHT`).
timeout (float): The number of seconds to wait for a blocking operation to complete. A value of `0` will block indefinitely.
Returns:
Optional[str]: The popped element, or None if `source` does not exist or if the operation timed-out.
Examples:
>>> await client.lpush("testKey1", ["two", "one"])
>>> await client.lpush("testKey2", ["four", "three"])
>>> await client.blmove("testKey1", "testKey2", ListDirection.LEFT, ListDirection.LEFT, 0.1)
"one"
>>> await client.lrange("testKey1", 0, -1)
["two"]
>>> updated_array2 = await client.lrange("testKey2", 0, -1)
["one", "three", "four"]
Since: Redis version 6.2.0.
"""
return cast(
Optional[str],
await self._execute_command(
RequestType.BLMove,
[source, destination, where_from.value, where_to.value, str(timeout)],
),
)

async def sadd(self, key: str, members: List[str]) -> int:
"""
Add specified members to the set stored at `key`.
Expand Down
66 changes: 64 additions & 2 deletions python/python/glide/async_commands/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import threading
from typing import List, Mapping, Optional, Tuple, TypeVar, Union

from glide.async_commands.command_args import Limit, OrderBy
from glide.async_commands.command_args import Limit, ListDirection, OrderBy
from glide.async_commands.core import (
ConditionalChange,
ExpireOptions,
Expand Down Expand Up @@ -931,7 +931,7 @@ def linsert(
"""
Inserts `element` in the list at `key` either before or after the `pivot`.
See https://redis.io/commands/linsert/ for details.
See https://valkey.io/commands/linsert/ for details.
Args:
key (str): The key of the list.
Expand All @@ -949,6 +949,68 @@ def linsert(
RequestType.LInsert, [key, position.value, pivot, element]
)

def lmove(
self: TTransaction,
source: str,
destination: str,
where_from: ListDirection,
where_to: ListDirection,
) -> TTransaction:
"""
Atomically pops and removes the left/right-most element to the list stored at `source`
depending on `where_from`, and pushes the element at the first/last element of the list
stored at `destination` depending on `where_to`.
See https://valkey.io/commands/lmove/ for details.
Args:
source (str): The key to the source list.
destination (str): The key to the destination list.
where_from (ListDirection): The direction to remove the element from (`ListDirection.LEFT` or `ListDirection.RIGHT`).
where_to (ListDirection): The direction to add the element to (`ListDirection.LEFT` or `ListDirection.RIGHT`).
Command response:
Optional[str]: The popped element, or `None` if `source` does not exist.
Since: Redis version 6.2.0.
"""
return self.append_command(
RequestType.LMove, [source, destination, where_from.value, where_to.value]
)

def blmove(
self: TTransaction,
source: str,
destination: str,
where_from: ListDirection,
where_to: ListDirection,
timeout: float,
) -> TTransaction:
"""
Blocks the connection until it pops atomically and removes the left/right-most element to the
list stored at `source` depending on `where_from`, and pushes the element at the first/last element
of the list stored at `destination` depending on `where_to`.
`blmove` is the blocking variant of `lmove`.
See https://valkey.io/commands/blmove/ for details.
Args:
source (str): The key to the source list.
destination (str): The key to the destination list.
where_from (ListDirection): The direction to remove the element from (`ListDirection.LEFT` or `ListDirection.RIGHT`).
where_to (ListDirection): The direction to add the element to (`ListDirection.LEFT` or `ListDirection.RIGHT`).
timeout (float): The number of seconds to wait for a blocking operation to complete. A value of `0` will block indefinitely.
Command response:
Optional[str]: The popped element, or `None` if `source` does not exist or if the operation timed-out.
Since: Redis version 6.2.0.
"""
return self.append_command(
RequestType.BLMove,
[source, destination, where_from.value, where_to.value, str(timeout)],
)

def sadd(self: TTransaction, key: str, members: List[str]) -> TTransaction:
"""
Add specified members to the set stored at `key`.
Expand Down
Loading

0 comments on commit ddc1425

Please sign in to comment.