diff --git a/examples/python/client_example.py b/examples/python/client_example.py index 0d24352160..bcc52be8e8 100755 --- a/examples/python/client_example.py +++ b/examples/python/client_example.py @@ -30,9 +30,9 @@ def set_file_logger(level: LogLevel = LogLevel.WARN, file: Optional[str] = None) async def send_set_and_get(client: Union[GlideClient, GlideClusterClient]): set_response = await client.set("foo", "bar") - print(f"Set response is = {set_response}") + print(f"Set response is = {set_response!r}") get_response = await client.get("foo") - print(f"Get response is = {get_response}") + print(f"Get response is = {get_response!r}") async def test_standalone_client(host: str = "localhost", port: int = 6379): diff --git a/python/python/glide/async_commands/cluster_commands.py b/python/python/glide/async_commands/cluster_commands.py index 2606161ce5..904cc25aa0 100644 --- a/python/python/glide/async_commands/cluster_commands.py +++ b/python/python/glide/async_commands/cluster_commands.py @@ -12,14 +12,14 @@ _build_sort_args, ) from glide.async_commands.transaction import BaseTransaction, ClusterTransaction -from glide.constants import TOK, TClusterResponse, TResult, TSingleNodeRoute +from glide.constants import TOK, TClusterResponse, TEncodable, TResult, TSingleNodeRoute from glide.protobuf.redis_request_pb2 import RequestType from glide.routes import Route class ClusterCommands(CoreCommands): async def custom_command( - self, command_args: List[str], route: Optional[Route] = None + self, command_args: List[TEncodable], route: Optional[Route] = None ) -> TResult: """ Executes a single command, without checking inputs. @@ -30,7 +30,7 @@ async def custom_command( connection.customCommand(["CLIENT", "LIST","TYPE", "PUBSUB"], AllNodes()) Args: - command_args (List[str]): List of strings of the command's arguments. + command_args (List[TEncodable]): List of the command's arguments, where each argument is either a string or bytes. Every part of the command, including the command name and subcommands, should be added as a separate value in args. route (Optional[Route]): The command will be routed automatically based on the passed command's default request policy, unless `route` is provided, in which case the client will route the command to the nodes defined by `route`. Defaults to None. @@ -58,12 +58,13 @@ async def info( case the client will route the command to the nodes defined by `route`. Defaults to None. Returns: - TClusterResponse[str]: If a single node route is requested, returns a string containing the information for - the required sections. Otherwise, returns a dict of strings, with each key containing the address of + TClusterResponse[bytes]: If a single node route is requested, returns a bytes string containing the information for + the required sections. Otherwise, returns a dict of bytes strings, with each key containing the address of the queried node and value containing the information regarding the requested sections. """ - args = [section.value for section in sections] if sections else [] - + args: List[TEncodable] = ( + [section.value for section in sections] if sections else [] + ) return cast( TClusterResponse[bytes], await self._execute_command(RequestType.Info, args, route), @@ -150,7 +151,7 @@ async def client_id( Returns: TClusterResponse[int]: The id of the client. If a single node route is requested, returns a int representing the client's id. - Otherwise, returns a dict of [str , int] where each key contains the address of + Otherwise, returns a dict of [byte , int] where each key contains the address of the queried node and the value contains the client's id. """ return cast( @@ -159,70 +160,74 @@ async def client_id( ) async def ping( - self, message: Optional[str] = None, route: Optional[Route] = None - ) -> str: + self, message: Optional[TEncodable] = None, route: Optional[Route] = None + ) -> bytes: """ Ping the Redis server. See https://redis.io/commands/ping/ for more details. Args: - message (Optional[str]): An optional message to include in the PING command. If not provided, - the server will respond with "PONG". If provided, the server will respond with a copy of the message + message (Optional[TEncodable]): An optional message to include in the PING command. If not provided, + the server will respond with b"PONG". If provided, the server will respond with a copy of the message. route (Optional[Route]): The command will be sent to all primaries, unless `route` is provided, in which case the client will route the command to the nodes defined by `route` Returns: - str: "PONG" if `message` is not provided, otherwise return a copy of `message`. + bytes: b'PONG' if `message` is not provided, otherwise return a copy of `message`. Examples: >>> await client.ping() - "PONG" + b"PONG" >>> await client.ping("Hello") - "Hello" + b"Hello" """ argument = [] if message is None else [message] - return cast(str, await self._execute_command(RequestType.Ping, argument, route)) + return cast( + bytes, await self._execute_command(RequestType.Ping, argument, route) + ) async def config_get( - self, parameters: List[str], route: Optional[Route] = None - ) -> TClusterResponse[Dict[str, str]]: + self, parameters: List[TEncodable], route: Optional[Route] = None + ) -> TClusterResponse[Dict[bytes, bytes]]: """ Get the values of configuration parameters. See https://redis.io/commands/config-get/ for details. Args: - parameters (List[str]): A list of configuration parameter names to retrieve values for. + parameters (List[TEncodable]): A list of configuration parameter names to retrieve values for. route (Optional[Route]): The command will be routed to a random node, unless `route` is provided, in which case the client will route the command to the nodes defined by `route`. Returns: - TClusterResponse[Dict[str, str]]: A dictionary of values corresponding to the + TClusterResponse[Dict[bytes, bytes]]: A dictionary of values corresponding to the configuration parameters. - When specifying a route other than a single node, response will be : {Address (str) : response (Dict[str, str]) , ... } - with type of Dict[str, Dict[str, str]]. + When specifying a route other than a single node, response will be : {Address (bytes) : response (Dict[bytes, bytes]) , ... } + with type of Dict[bytes, Dict[bytes, bytes]]. Examples: >>> await client.config_get(["timeout"] , RandomNode()) - {'timeout': '1000'} - >>> await client.config_get(["timeout" , "maxmemory"]) - {'timeout': '1000', "maxmemory": "1GB"} + {b'timeout': b'1000'} + >>> await client.config_get(["timeout" , b"maxmemory"]) + {b'timeout': b'1000', b"maxmemory": b"1GB"} """ return cast( - TClusterResponse[Dict[str, str]], + TClusterResponse[Dict[bytes, bytes]], await self._execute_command(RequestType.ConfigGet, parameters, route), ) async def config_set( - self, parameters_map: Mapping[str, str], route: Optional[Route] = None + self, + parameters_map: Mapping[TEncodable, TEncodable], + route: Optional[Route] = None, ) -> TOK: """ Set configuration parameters to the specified values. See https://redis.io/commands/config-set/ for details. Args: - parameters_map (Mapping[str, str]): A map consisting of configuration + parameters_map (Mapping[TEncodable, TEncodable]): A map consisting of configuration parameters and their respective values to set. route (Optional[Route]): The command will be routed to all nodes, unless `route` is provided, @@ -232,10 +237,10 @@ async def config_set( OK: Returns OK if all configurations have been successfully set. Otherwise, raises an error. Examples: - >>> await client.config_set([("timeout", "1000")], [("maxmemory", "1GB")]) - OK + >>> await client.config_set({"timeout": "1000", b"maxmemory": b"1GB"}) + OK """ - parameters: List[str] = [] + parameters: List[TEncodable] = [] for pair in parameters_map.items(): parameters.extend(pair) return cast( @@ -245,7 +250,7 @@ async def config_set( async def client_getname( self, route: Optional[Route] = None - ) -> TClusterResponse[Optional[str]]: + ) -> TClusterResponse[Optional[bytes]]: """ Get the name of the connection to which the request is routed. See https://redis.io/commands/client-getname/ for more details. @@ -255,19 +260,19 @@ async def client_getname( in which case the client will route the command to the nodes defined by `route`. Returns: - TClusterResponse[Optional[str]]: The name of the client connection as a string if a name is set, + TClusterResponse[Optional[bytes]]: The name of the client connection as a bytes string if a name is set, or None if no name is assigned. When specifying a route other than a single node, response will be: - {Address (str) : response (Optional[str]) , ... } with type of Dict[str, Optional[str]]. + {Address (bytes) : response (Optional[bytes]) , ... } with type of Dict[str, Optional[str]]. Examples: >>> await client.client_getname() - 'Connection Name' + b'Connection Name' >>> await client.client_getname(AllNodes()) - {'addr': 'Connection Name', 'addr2': 'Connection Name', 'addr3': 'Connection Name'} + {b'addr': b'Connection Name', b'addr2': b'Connection Name', b'addr3': b'Connection Name'} """ return cast( - TClusterResponse[Optional[str]], + TClusterResponse[Optional[bytes]], await self._execute_command(RequestType.ClientGetName, [], route), ) @@ -291,61 +296,64 @@ async def dbsize(self, route: Optional[Route] = None) -> int: return cast(int, await self._execute_command(RequestType.DBSize, [], route)) async def echo( - self, message: str, route: Optional[Route] = None - ) -> TClusterResponse[str]: + self, message: TEncodable, route: Optional[Route] = None + ) -> TClusterResponse[bytes]: """ Echoes the provided `message` back. See https://redis.io/commands/echo for more details. Args: - message (str): The message to be echoed back. + message (TEncodable): The message to be echoed back. route (Optional[Route]): The command will be routed to a random node, unless `route` is provided, in which case the client will route the command to the nodes defined by `route`. Returns: - TClusterResponse[str]: The provided `message`. + TClusterResponse[bytes]: The provided `message`. When specifying a route other than a single node, response will be: - {Address (str) : response (str) , ... } with type of Dict[str, str]. + {Address (bytes) : response (bytes) , ... } with type of Dict[bytes, bytes]. Examples: - >>> await client.echo("Glide-for-Redis") - 'Glide-for-Redis' + >>> await client.echo(b"Glide-for-Redis") + b'Glide-for-Redis' >>> await client.echo("Glide-for-Redis", AllNodes()) - {'addr': 'Glide-for-Redis', 'addr2': 'Glide-for-Redis', 'addr3': 'Glide-for-Redis'} + {b'addr': b'Glide-for-Redis', b'addr2': b'Glide-for-Redis', b'addr3': b'Glide-for-Redis'} """ return cast( - TClusterResponse[str], + TClusterResponse[bytes], await self._execute_command(RequestType.Echo, [message], route), ) async def function_load( - self, library_code: str, replace: bool = False, route: Optional[Route] = None - ) -> str: + self, + library_code: TEncodable, + replace: bool = False, + route: Optional[Route] = None, + ) -> bytes: """ Loads a library to Redis. See https://valkey.io/docs/latest/commands/function-load/ for more details. Args: - library_code (str): The source code that implements the library. + library_code (TEncodable): The source code that implements the library. replace (bool): Whether the given library should overwrite a library with the same name if it already exists. route (Optional[Route]): The command will be routed to all primaries, unless `route` is provided, in which case the client will route the command to the nodes defined by `route`. Returns: - str: The library name that was loaded. + bytes: The library name that was loaded. Examples: >>> code = "#!lua name=mylib \n redis.register_function('myfunc', function(keys, args) return args[1] end)" >>> await client.function_load(code, True, RandomNode()) - "mylib" + b"mylib" Since: Redis 7.0.0. """ return cast( - str, + bytes, await self._execute_command( RequestType.FunctionLoad, ["REPLACE", library_code] if replace else [library_code], @@ -385,7 +393,7 @@ async def function_flush( ) async def function_delete( - self, library_name: str, route: Optional[Route] = None + self, library_name: TEncodable, route: Optional[Route] = None ) -> TOK: """ Deletes a library and all its functions. @@ -393,7 +401,7 @@ async def function_delete( See https://valkey.io/docs/latest/commands/function-delete/ for more details. Args: - library_code (str): The libary name to delete + library_code (TEncodable): The library name to delete route (Optional[Route]): The command will be routed to all primaries, unless `route` is provided, in which case the client will route the command to the nodes defined by `route`. @@ -417,8 +425,8 @@ async def function_delete( async def fcall_route( self, - function: str, - arguments: Optional[List[str]] = None, + function: TEncodable, + arguments: Optional[List[TEncodable]] = None, route: Optional[Route] = None, ) -> TClusterResponse[TResult]: """ @@ -426,8 +434,8 @@ async def fcall_route( See https://redis.io/commands/fcall/ for more details. Args: - function (str): The function name. - arguments (Optional[List[str]]): A list of `function` arguments. `Arguments` + function (TEncodable): The function name. + arguments (Optional[List[TEncodable]]): A list of `function` arguments. `Arguments` should not represent names of keys. route (Optional[Route]): The command will be routed to a random primay node, unless `route` is provided, in which case the client will route the command to the nodes defined by `route`. Defaults to None. @@ -435,12 +443,12 @@ async def fcall_route( Returns: TClusterResponse[TResult]: If a single node route is requested, returns a Optional[TResult] representing the function's return value. - Otherwise, returns a dict of [str , Optional[TResult]] where each key contains the address of + Otherwise, returns a dict of [bytes , Optional[TResult]] where each key contains the address of the queried node and the value contains the function's return value. Example: >>> await client.fcall("Deep_Thought", ["Answer", "to", "the", "Ultimate", "Question", "of", "Life,", "the", "Universe,", "and", "Everything"], RandomNode()) - 'new_value' # Returns the function's return value. + b'new_value' # Returns the function's return value. Since: Redis version 7.0.0. """ @@ -454,8 +462,8 @@ async def fcall_route( async def fcall_ro_route( self, - function: str, - arguments: Optional[List[str]] = None, + function: TEncodable, + arguments: Optional[List[TEncodable]] = None, route: Optional[Route] = None, ) -> TClusterResponse[TResult]: """ @@ -464,8 +472,8 @@ async def fcall_ro_route( See https://valkey.io/commands/fcall_ro for more details. Args: - function (str): The function name. - arguments (List[str]): An `array` of `function` arguments. `arguments` should not + function (TEncodable): The function name. + arguments (List[TEncodable]): An `array` of `function` arguments. `arguments` should not represent names of keys. route (Optional[Route]): Specifies the routing configuration of the command. The client will route the command to the nodes defined by `route`. @@ -479,7 +487,7 @@ async def fcall_ro_route( Since: Redis version 7.0.0. """ - args = [function, "0"] + args: List[TEncodable] = [function, "0"] if arguments is not None: args.extend(arguments) return cast( @@ -487,7 +495,9 @@ async def fcall_ro_route( await self._execute_command(RequestType.FCallReadOnly, args, route), ) - async def time(self, route: Optional[Route] = None) -> TClusterResponse[List[str]]: + async def time( + self, route: Optional[Route] = None + ) -> TClusterResponse[List[bytes]]: """ Returns the server time. @@ -498,20 +508,20 @@ async def time(self, route: Optional[Route] = None) -> TClusterResponse[List[str in which case the client will route the command to the nodes defined by `route`. Returns: - TClusterResponse[Optional[str]]: The current server time as a two items `array`: + TClusterResponse[Optional[bytes]]: The current server time as a two items `array`: A Unix timestamp and the amount of microseconds already elapsed in the current second. The returned `array` is in a [Unix timestamp, Microseconds already elapsed] format. When specifying a route other than a single node, response will be: - {Address (str) : response (List[str]) , ... } with type of Dict[str, List[str]]. + {Address (bytes) : response (List[bytes]) , ... } with type of Dict[bytes, List[bytes]]. Examples: >>> await client.time() - ['1710925775', '913580'] + [b'1710925775', b'913580'] >>> await client.time(AllNodes()) - {'addr': ['1710925775', '913580'], 'addr2': ['1710925775', '913580'], 'addr3': ['1710925775', '913580']} + {b'addr': [b'1710925775', b'913580'], b'addr2': [b'1710925775', b'913580'], b'addr3': [b'1710925775', b'913580']} """ return cast( - TClusterResponse[List[str]], + TClusterResponse[List[bytes]], await self._execute_command(RequestType.Time, [], route), ) @@ -528,14 +538,14 @@ async def lastsave(self, route: Optional[Route] = None) -> TClusterResponse[int] Returns: TClusterResponse[int]: The Unix time of the last successful DB save. If no route is provided, or a single node route is requested, returns an int representing the Unix time - of the last successful DB save. Otherwise, returns a dict of [str , int] where each key contains the + of the last successful DB save. Otherwise, returns a dict of [bytes , int] where each key contains the address of the queried node and the value contains the Unix time of the last successful DB save. Examples: >>> await client.lastsave() - 1710925775 # Unix time of the last DB save + 1710925775 # Unix time of the last DB save >>> await client.lastsave(AllNodes()) - {'addr1': 1710925775, 'addr2': 1710925775, 'addr3': 1710925775} # Unix time of the last DB save on each node + {b'addr1': 1710925775, b'addr2': 1710925775, b'addr3': 1710925775} # Unix time of the last DB save on each node """ return cast( TClusterResponse[int], @@ -544,11 +554,11 @@ async def lastsave(self, route: Optional[Route] = None) -> TClusterResponse[int] async def sort( self, - key: str, + key: TEncodable, limit: Optional[Limit] = None, order: Optional[OrderBy] = None, alpha: Optional[bool] = None, - ) -> List[str]: + ) -> List[bytes]: """ 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`. @@ -558,7 +568,7 @@ async def sort( See https://valkey.io/commands/sort for more details. Args: - key (str): The key of the list, set, or sorted set to be sorted. + key (TEncodable): 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). @@ -566,32 +576,32 @@ async def sort( Use this when the list, set, or sorted set contains string values that cannot be converted into double precision floating point numbers. Returns: - List[str]: A list of sorted elements. + List[bytes]: A list of sorted elements. Examples: - >>> await client.lpush("mylist", '3', '1', '2') + >>> await client.lpush(b"mylist", [b'3', b'1', b'2']) >>> await client.sort("mylist") - ['1', '2', '3'] + [b'1', b'2', b'3'] >>> await client.sort("mylist", order=OrderBy.DESC) - ['3', '2', '1'] + ['3', '2', '1'] - >>> await client.lpush("mylist", '2', '1', '2', '3', '3', '1') + >>> await client.lpush(b"mylist", [b'2', b'1', b'2', b'3', b'3', b'1']) >>> await client.sort("mylist", limit=Limit(2, 3)) - ['1', '2', '2'] + [b'2', b'2', b'3'] - >>> await client.lpush("mylist", "a", "b", "c", "d") - >>> await client.sort("mylist", limit=Limit(2, 2), order=OrderBy.DESC, alpha=True) - ['b', 'a'] + >>> await client.lpush(b"mylist", [b"a", b"b", b"c", b"d"]) + >>> await client.sort(b"mylist", limit=Limit(2, 2), order=OrderBy.DESC, alpha=True) + [b'b', b'a'] """ args = _build_sort_args(key, None, limit, None, order, alpha) result = await self._execute_command(RequestType.Sort, args) - return cast(List[str], result) + return cast(List[bytes], result) async def sort_store( self, - key: str, - destination: str, + key: TEncodable, + destination: TEncodable, limit: Optional[Limit] = None, order: Optional[OrderBy] = None, alpha: Optional[bool] = None, @@ -604,8 +614,8 @@ async def sort_store( See https://valkey.io/commands/sort for more details. 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. + key (TEncodable): The key of the list, set, or sorted set to be sorted. + destination (TEncodable): 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). @@ -616,17 +626,22 @@ async def sort_store( 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.lpush(b"mylist", [b'3', b'1', b'2']) + >>> await client.sort_store("mylist", b"sorted_list") + 3 # Indicates that the sorted list "sorted_list" contains three elements. >>> await client.lrange("sorted_list", 0, -1) - ['1', '2', '3'] + [b'1', b'2', b'3'] """ args = _build_sort_args(key, None, limit, None, order, alpha, store=destination) result = await self._execute_command(RequestType.Sort, args) return cast(int, result) - async def publish(self, message: str, channel: str, sharded: bool = False) -> int: + async def publish( + self, + message: TEncodable, + channel: TEncodable, + sharded: bool = False, + ) -> int: """ Publish a message on pubsub channel. This command aggregates PUBLISH and SPUBLISH commands functionalities. @@ -635,8 +650,8 @@ async def publish(self, message: str, channel: str, sharded: bool = False) -> in See https://valkey.io/commands/publish and https://valkey.io/commands/spublish for more details. Args: - message (str): Message to publish - channel (str): Channel to publish the message on. + message (TEncodable): Message to publish. + channel (TEncodable): Channel to publish the message on. sharded (bool): Use sharded pubsub mode. Available since Redis version 7.0. Returns: @@ -645,7 +660,7 @@ async def publish(self, message: str, channel: str, sharded: bool = False) -> in Examples: >>> await client.publish("Hi all!", "global-channel", False) 1 # Published 1 instance of "Hi all!" message on global-channel channel using non-sharded mode - >>> await client.publish("Hi to sharded channel1!", "channel1, True) + >>> await client.publish(b"Hi to sharded channel1!", b"channel1", True) 2 # Published 2 instances of "Hi to sharded channel1!" message on channel1 using sharded mode """ result = await self._execute_command( @@ -655,7 +670,7 @@ async def publish(self, message: str, channel: str, sharded: bool = False) -> in async def flushall( self, flush_mode: Optional[FlushMode] = None, route: Optional[Route] = None - ) -> TClusterResponse[TOK]: + ) -> TOK: """ Deletes all the keys of all the existing databases. This command never fails. @@ -667,26 +682,26 @@ async def flushall( in which case the client will route the command to the nodes defined by `route`. Returns: - TClusterResponse[TOK]: OK. + TOK: A simple OK response. Examples: - >>> await client.flushall(FlushMode.ASYNC) - OK # This command never fails. - >>> await client.flushall(FlushMode.ASYNC, AllNodes()) - OK # This command never fails. + >>> await client.flushall(FlushMode.ASYNC) + OK # This command never fails. + >>> await client.flushall(FlushMode.ASYNC, AllNodes()) + OK # This command never fails. """ - args = [] + args: List[TEncodable] = [] if flush_mode is not None: args.append(flush_mode.value) return cast( - TClusterResponse[TOK], + TOK, await self._execute_command(RequestType.FlushAll, args, route), ) async def flushdb( self, flush_mode: Optional[FlushMode] = None, route: Optional[Route] = None - ) -> TClusterResponse[TOK]: + ) -> TOK: """ Deletes all the keys of the currently selected database. This command never fails. @@ -698,29 +713,29 @@ async def flushdb( in which case the client will route the command to the nodes defined by `route`. Returns: - TOK: OK. + TOK: A simple OK response. Examples: - >>> await client.flushdb() - OK # The keys of the currently selected database were deleted. - >>> await client.flushdb(FlushMode.ASYNC) - OK # The keys of the currently selected database were deleted asynchronously. - >>> await client.flushdb(FlushMode.ASYNC, AllNodes()) - OK # The keys of the currently selected database were deleted asynchronously on all nodes. - """ - args = [] + >>> await client.flushdb() + OK # The keys of the currently selected database were deleted. + >>> await client.flushdb(FlushMode.ASYNC) + OK # The keys of the currently selected database were deleted asynchronously. + >>> await client.flushdb(FlushMode.ASYNC, AllNodes()) + OK # The keys of the currently selected database were deleted asynchronously on all nodes. + """ + args: List[TEncodable] = [] if flush_mode is not None: args.append(flush_mode.value) return cast( - TClusterResponse[TOK], + TOK, await self._execute_command(RequestType.FlushDB, args, route), ) async def copy( self, - source: str, - destination: str, + source: TEncodable, + destination: TEncodable, replace: Optional[bool] = None, ) -> bool: """ @@ -733,8 +748,8 @@ async def copy( Both `source` and `destination` must map to the same hash slot. Args: - source (str): The key to the source value. - destination (str): The key where the value should be copied to. + source (TEncodable): The key to the source value. + destination (TEncodable): The key where the value should be copied to. replace (Optional[bool]): If the destination key should be removed before copying the value to it. Returns: @@ -742,14 +757,14 @@ async def copy( Examples: >>> await client.set("source", "sheep") - >>> await client.copy("source", "destination") + >>> await client.copy(b"source", b"destination") True # Source was copied >>> await client.get("destination") - "sheep" + b"sheep" Since: Redis version 6.2.0. """ - args = [source, destination] + args: List[TEncodable] = [source, destination] if replace is True: args.append("REPLACE") return cast( @@ -762,7 +777,7 @@ async def lolwut( version: Optional[int] = None, parameters: Optional[List[int]] = None, route: Optional[Route] = None, - ) -> TClusterResponse[str]: + ) -> TClusterResponse[bytes]: """ Displays a piece of generative computer art and the Redis version. @@ -777,24 +792,26 @@ async def lolwut( in which case the client will route the command to the nodes defined by `route`. Returns: - TClusterResponse[str]: A piece of generative computer art along with the current Redis version. + TClusterResponse[bytes]: A piece of generative computer art along with the current Redis version. + When specifying a route other than a single node, response will be: + {Address (bytes) : response (bytes) , ... } with type of Dict[bytes, bytes]. Examples: - >>> await client.lolwut(6, [40, 20], ALL_NODES); - "Redis ver. 7.2.3" # Indicates the current Redis version + >>> await client.lolwut(6, [40, 20], RandomNode()); + b"Redis ver. 7.2.3" # Indicates the current Redis version """ - args = [] + args: List[TEncodable] = [] if version is not None: args.extend(["VERSION", str(version)]) if parameters: for var in parameters: args.extend(str(var)) return cast( - TClusterResponse[str], + TClusterResponse[bytes], await self._execute_command(RequestType.Lolwut, args, route), ) - async def random_key(self, route: Optional[Route] = None) -> Optional[str]: + async def random_key(self, route: Optional[Route] = None) -> Optional[bytes]: """ Returns a random existing key name. @@ -805,14 +822,14 @@ async def random_key(self, route: Optional[Route] = None) -> Optional[str]: in which case the client will route the command to the nodes defined by `route`. Returns: - Optional[str]: A random existing key name. + Optional[bytes]: A random existing key name. Examples: >>> await client.random_key() - "random_key_name" # "random_key_name" is a random existing key name. + b"random_key_name" # "random_key_name" is a random existing key name. """ return cast( - Optional[str], + Optional[bytes], await self._execute_command(RequestType.RandomKey, [], route), ) @@ -834,6 +851,7 @@ async def wait( timeout (int): The timeout value specified in milliseconds. A value of 0 will block indefinitely. route (Optional[Route]): The command will be routed to all primary nodes, unless `route` is provided, in which case the client will route the command to the nodes defined by `route`. + Returns: int: The number of replicas reached by all the writes performed in the context of the current connection. @@ -842,7 +860,7 @@ async def wait( >>> await client.wait(1, 1000); // return 1 when a replica is reached or 0 if 1000ms is reached. """ - args = [str(numreplicas), str(timeout)] + args: List[TEncodable] = [str(numreplicas), str(timeout)] return cast( int, await self._execute_command(RequestType.Wait, args, route), diff --git a/python/python/glide/async_commands/core.py b/python/python/glide/async_commands/core.py index b8ca75787a..431d2dc9ed 100644 --- a/python/python/glide/async_commands/core.py +++ b/python/python/glide/async_commands/core.py @@ -1,5 +1,4 @@ # Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 -from abc import ABC, abstractmethod from collections.abc import Mapping from dataclasses import dataclass from datetime import datetime, timedelta @@ -55,7 +54,7 @@ StreamTrimOptions, _create_xpending_range_args, ) -from glide.constants import TOK, TResult +from glide.constants import TOK, TEncodable, TResult from glide.protobuf.redis_request_pb2 import RequestType from glide.routes import Route @@ -308,14 +307,14 @@ class FlushMode(Enum): def _build_sort_args( - key: str, - by_pattern: Optional[str] = None, + key: TEncodable, + by_pattern: Optional[TEncodable] = None, limit: Optional[Limit] = None, - get_patterns: Optional[List[str]] = None, + get_patterns: Optional[List[TEncodable]] = None, order: Optional[OrderBy] = None, alpha: Optional[bool] = None, - store: Optional[str] = None, -) -> List[str]: + store: Optional[TEncodable] = None, +) -> List[TEncodable]: args = [key] if by_pattern: @@ -344,62 +343,62 @@ class CoreCommands(Protocol): async def _execute_command( self, request_type: RequestType.ValueType, - args: List[str], + args: List[TEncodable], route: Optional[Route] = ..., ) -> TResult: ... async def _execute_transaction( self, - commands: List[Tuple[RequestType.ValueType, List[str]]], + commands: List[Tuple[RequestType.ValueType, List[TEncodable]]], route: Optional[Route] = None, ) -> List[TResult]: ... async def _execute_script( self, hash: str, - keys: Optional[List[Union[str, bytes]]] = None, - args: Optional[List[Union[str, bytes]]] = None, + keys: Optional[List[TEncodable]] = None, + args: Optional[List[TEncodable]] = None, route: Optional[Route] = None, ) -> TResult: ... async def set( self, - key: str, - value: str, + key: TEncodable, + value: TEncodable, conditional_set: Optional[ConditionalChange] = None, expiry: Optional[ExpirySet] = None, return_old_value: bool = False, - ) -> Optional[str]: + ) -> Optional[bytes]: """ Set the given key with the given value. Return value is dependent on the passed options. See https://redis.io/commands/set/ for more details. Args: - key (str): the key to store. - value (str): the value to store with the given key. + key (TEncodable): the key to store. + value (TEncodable): the value to store with the given key. conditional_set (Optional[ConditionalChange], optional): set the key only if the given condition is met. Equivalent to [`XX` | `NX`] in the Redis API. Defaults to None. expiry (Optional[ExpirySet], optional): set expiriation to the given key. Equivalent to [`EX` | `PX` | `EXAT` | `PXAT` | `KEEPTTL`] in the Redis API. Defaults to None. - return_old_value (bool, optional): Return the old string stored at key, or None if key did not exist. + return_old_value (bool, optional): Return the old value stored at key, or None if key did not exist. An error is returned and SET aborted if the value stored at key is not a string. Equivalent to `GET` in the Redis API. Defaults to False. Returns: - Optional[str]: + Optional[bytes]: If the value is successfully set, return OK. If value isn't set because of only_if_exists or only_if_does_not_exist conditions, return None. - If return_old_value is set, return the old value as a string. + If return_old_value is set, return the old value as a bytes string. Example: - >>> await client.set("key", "value") + >>> await client.set(b"key", b"value") 'OK' >>> await client.set("key", "new_value",conditional_set=ConditionalChange.ONLY_IF_EXISTS, expiry=Expiry(ExpiryType.SEC, 5)) 'OK' # Set "new_value" to "key" only if "key" already exists, and set the key expiration to 5 seconds. >>> await client.set("key", "value", conditional_set=ConditionalChange.ONLY_IF_DOES_NOT_EXIST,return_old_value=True) - 'new_value' # Returns the old value of "key". + b'new_value' # Returns the old value of "key". >>> await client.get("key") - 'new_value' # Value wasn't modified back to being "value" because of "NX" flag. + b'new_value' # Value wasn't modified back to being "value" because of "NX" flag. """ args = [key, value] if conditional_set: @@ -408,86 +407,87 @@ async def set( args.append("GET") if expiry is not None: args.extend(expiry.get_cmd_args()) - return cast(Optional[str], await self._execute_command(RequestType.Set, args)) + return cast(Optional[bytes], await self._execute_command(RequestType.Set, args)) - async def get(self, key: str) -> Optional[str]: + async def get(self, key: TEncodable) -> Optional[bytes]: """ Get the value associated with the given key, or null if no such value exists. See https://redis.io/commands/get/ for details. Args: - key (str): The key to retrieve from the database. + key (TEncodable): The key to retrieve from the database. Returns: - Optional[str]: If the key exists, returns the value of the key as a string. Otherwise, return None. + Optional[bytes]: If the key exists, returns the value of the key as a byte string. Otherwise, return None. Example: >>> await client.get("key") - 'value' + b'value' """ - return cast(Optional[str], await self._execute_command(RequestType.Get, [key])) + args: List[TEncodable] = [key] + return cast(Optional[bytes], await self._execute_command(RequestType.Get, args)) - async def getdel(self, key: str) -> Optional[str]: + async def getdel(self, key: TEncodable) -> Optional[bytes]: """ - Gets a string value associated with the given `key` and deletes the key. + Gets a value associated with the given string `key` and deletes the key. See https://valkey.io/commands/getdel for more details. Args: - key (str): The `key` to retrieve from the database. + key (TEncodable): The `key` to retrieve from the database. Returns: - Optional[str]: If `key` exists, returns the `value` of `key`. Otherwise, returns `None`. + Optional[bytes]: If `key` exists, returns the `value` of `key`. Otherwise, returns `None`. Examples: >>> await client.set("key", "value") >>> await client.getdel("key") - 'value' + b'value' >>> await client.getdel("key") None """ return cast( - Optional[str], await self._execute_command(RequestType.GetDel, [key]) + Optional[bytes], await self._execute_command(RequestType.GetDel, [key]) ) - async def getrange(self, key: str, start: int, end: int) -> str: + async def getrange(self, key: TEncodable, start: int, end: int) -> bytes: """ - Returns the substring of the string value stored at `key`, determined by the offsets `start` and `end` (both are inclusive). - Negative offsets can be used in order to provide an offset starting from the end of the string. + Returns the substring of the value stored at `key`, determined by the offsets `start` and `end` (both are inclusive). + Negative offsets can be used in order to provide an offset starting from the end of the value. So `-1` means the last character, `-2` the penultimate and so forth. - If `key` does not exist, an empty string is returned. If `start` or `end` - are out of range, returns the substring within the valid range of the string. + If `key` does not exist, an empty byte string is returned. If `start` or `end` + are out of range, returns the substring within the valid range of the value. See https://valkey.io/commands/getrange/ for more details. Args: - key (str): The key of the string. + key (TEncodable): The key of the string. start (int): The starting offset. end (int): The ending offset. Returns: - str: A substring extracted from the value stored at `key`. + bytes: A substring extracted from the value stored at `key`. Examples: >>> await client.set("mykey", "This is a string") >>> await client.getrange("mykey", 0, 3) - "This" + b"This" >>> await client.getrange("mykey", -3, -1) - "ing" # extracted last 3 characters of a string + b"ing" # extracted last 3 characters of a string >>> await client.getrange("mykey", 0, 100) - "This is a string" + b"This is a string" >>> await client.getrange("non_existing", 5, 6) - "" + b"" """ return cast( - str, + bytes, await self._execute_command( RequestType.GetRange, [key, str(start), str(end)] ), ) - async def append(self, key: str, value: str) -> int: + async def append(self, key: TEncodable, value: TEncodable) -> int: """ Appends a value to a key. If `key` does not exist it is created and set as an empty string, so `APPEND` will be similar to `SET` in this special case. @@ -495,11 +495,11 @@ async def append(self, key: str, value: str) -> int: See https://redis.io/commands/append for more details. Args: - key (str): The key to which the value will be appended. - value (str): The value to append. + key (TEncodable): The key to which the value will be appended. + value (TEncodable): The value to append. Returns: - int: The length of the string after appending the value. + int: The length of the stored value after appending `value`. Examples: >>> await client.append("key", "Hello") @@ -507,17 +507,17 @@ async def append(self, key: str, value: str) -> int: >>> await client.append("key", " world") 11 # Indicates that " world" has been appended to the value of "key", resulting in a new value of "Hello world" with a length of 11. >>> await client.get("key") - "Hello world" # Returns the value stored in "key", which is now "Hello world". + b"Hello world" # Returns the value stored in "key", which is now "Hello world". """ return cast(int, await self._execute_command(RequestType.Append, [key, value])) - async def strlen(self, key: str) -> int: + async def strlen(self, key: TEncodable) -> int: """ Get the length of the string value stored at `key`. See https://redis.io/commands/strlen/ for more details. Args: - key (str): The key to return its length. + key (TEncodable): The key to return its length. Returns: int: The length of the string value stored at `key`. @@ -528,9 +528,10 @@ async def strlen(self, key: str) -> int: >>> await client.strlen("key") 5 # Indicates that the length of the string value stored at `key` is 5. """ - return cast(int, await self._execute_command(RequestType.Strlen, [key])) + args: List[TEncodable] = [key] + return cast(int, await self._execute_command(RequestType.Strlen, args)) - async def rename(self, key: str, new_key: str) -> TOK: + async def rename(self, key: TEncodable, new_key: TEncodable) -> TOK: """ Renames `key` to `new_key`. If `newkey` already exists it is overwritten. @@ -540,8 +541,8 @@ async def rename(self, key: str, new_key: str) -> TOK: When in cluster mode, both `key` and `newkey` must map to the same hash slot. Args: - key (str) : The key to rename. - new_key (str) : The new name of the key. + key (TEncodable) : The key to rename. + new_key (TEncodable) : The new name of the key. Returns: OK: If the `key` was successfully renamed, return "OK". If `key` does not exist, an error is thrown. @@ -550,7 +551,7 @@ async def rename(self, key: str, new_key: str) -> TOK: TOK, await self._execute_command(RequestType.Rename, [key, new_key]) ) - async def renamenx(self, key: str, new_key: str) -> bool: + async def renamenx(self, key: TEncodable, new_key: TEncodable) -> bool: """ Renames `key` to `new_key` if `new_key` does not yet exist. @@ -560,8 +561,8 @@ async def renamenx(self, key: str, new_key: str) -> bool: When in cluster mode, both `key` and `new_key` must map to the same hash slot. Args: - key (str): The key to rename. - new_key (str): The new key name. + key (TEncodable): The key to rename. + new_key (TEncodable): The new key name. Returns: bool: True if `key` was renamed to `new_key`, or False if `new_key` already exists. @@ -575,7 +576,7 @@ async def renamenx(self, key: str, new_key: str) -> bool: await self._execute_command(RequestType.RenameNX, [key, new_key]), ) - async def delete(self, keys: List[str]) -> int: + async def delete(self, keys: List[TEncodable]) -> int: """ Delete one or more keys from the database. A key is ignored if it does not exist. See https://redis.io/commands/del/ for details. @@ -584,7 +585,7 @@ async def delete(self, keys: List[str]) -> int: When in cluster mode, the command may route to multiple nodes when `keys` map to different hash slots. Args: - keys (List[str]): A list of keys to be deleted from the database. + keys (List[TEncodable]): A list of keys to be deleted from the database. Returns: int: The number of keys that were deleted. @@ -598,14 +599,14 @@ async def delete(self, keys: List[str]) -> int: """ return cast(int, await self._execute_command(RequestType.Del, keys)) - async def incr(self, key: str) -> int: + async def incr(self, key: TEncodable) -> int: """ Increments the number stored at `key` by one. If the key does not exist, it is set to 0 before performing the operation. See https://redis.io/commands/incr/ for more details. Args: - key (str): The key to increment its value. + key (TEncodable): The key to increment its value. Returns: int: The value of `key` after the increment. @@ -617,13 +618,13 @@ async def incr(self, key: str) -> int: """ return cast(int, await self._execute_command(RequestType.Incr, [key])) - async def incrby(self, key: str, amount: int) -> int: + async def incrby(self, key: TEncodable, amount: int) -> int: """ Increments the number stored at `key` by `amount`. If the key does not exist, it is set to 0 before performing the operation. See https://redis.io/commands/incrby/ for more details. Args: - key (str): The key to increment its value. + key (TEncodable): The key to increment its value. amount (int) : The amount to increment. Returns: @@ -638,7 +639,7 @@ async def incrby(self, key: str, amount: int) -> int: int, await self._execute_command(RequestType.IncrBy, [key, str(amount)]) ) - async def incrbyfloat(self, key: str, amount: float) -> float: + async def incrbyfloat(self, key: TEncodable, amount: float) -> float: """ Increment the string representing a floating point number stored at `key` by `amount`. By using a negative increment value, the value stored at the `key` is decremented. @@ -646,7 +647,7 @@ async def incrbyfloat(self, key: str, amount: float) -> float: See https://redis.io/commands/incrbyfloat/ for more details. Args: - key (str): The key to increment its value. + key (TEncodable): The key to increment its value. amount (float) : The amount to increment. Returns: @@ -662,7 +663,7 @@ async def incrbyfloat(self, key: str, amount: float) -> float: await self._execute_command(RequestType.IncrByFloat, [key, str(amount)]), ) - async def setrange(self, key: str, offset: int, value: str) -> int: + async def setrange(self, key: TEncodable, offset: int, value: TEncodable) -> int: """ Overwrites part of the string stored at `key`, starting at the specified `offset`, for the entire length of `value`. @@ -673,9 +674,9 @@ async def setrange(self, key: str, offset: int, value: str) -> int: See https://valkey.io/commands/setrange for more details. Args: - key (str): The key of the string to update. + key (TEncodable): The key of the string to update. offset (int): The position in the string where `value` should be written. - value (str): The string written with `offset`. + value (TEncodable): The value written with `offset`. Returns: int: The length of the string stored at `key` after it was modified. @@ -692,7 +693,7 @@ async def setrange(self, key: str, offset: int, value: str) -> int: ), ) - async def mset(self, key_value_map: Mapping[str, str]) -> TOK: + async def mset(self, key_value_map: Mapping[TEncodable, TEncodable]) -> TOK: """ Set multiple keys to multiple values in a single atomic operation. See https://redis.io/commands/mset/ for more details. @@ -701,7 +702,7 @@ async def mset(self, key_value_map: Mapping[str, str]) -> TOK: When in cluster mode, the command may route to multiple nodes when keys in `key_value_map` map to different hash slots. Args: - key_value_map (Mapping[str, str]): A map of key value pairs. + key_value_map (Mapping[TEncodable, TEncodable]): A map of key value pairs. Returns: OK: a simple OK response. @@ -710,12 +711,12 @@ async def mset(self, key_value_map: Mapping[str, str]) -> TOK: >>> await client.mset({"key" : "value", "key2": "value2"}) 'OK' """ - parameters: List[str] = [] + parameters: List[TEncodable] = [] for pair in key_value_map.items(): parameters.extend(pair) return cast(TOK, await self._execute_command(RequestType.MSet, parameters)) - async def msetnx(self, key_value_map: Mapping[str, str]) -> bool: + async def msetnx(self, key_value_map: Mapping[TEncodable, TEncodable]) -> bool: """ Sets multiple keys to values if the key does not exist. The operation is atomic, and if one or more keys already exist, the entire operation fails. @@ -726,7 +727,7 @@ async def msetnx(self, key_value_map: Mapping[str, str]) -> bool: See https://valkey.io/commands/msetnx/ for more details. Args: - key_value_map (Mapping[str, str]): A key-value map consisting of keys and their respective values to set. + key_value_map (Mapping[TEncodable, TEncodable]): A key-value map consisting of keys and their respective values to set. Returns: bool: True if all keys were set. False if no key was set. @@ -737,7 +738,7 @@ async def msetnx(self, key_value_map: Mapping[str, str]) -> bool: >>> await client.msetnx({"key2": "value4", "key3": "value5"}) False """ - parameters: List[str] = [] + parameters: List[TEncodable] = [] for pair in key_value_map.items(): parameters.extend(pair) return cast( @@ -745,7 +746,7 @@ async def msetnx(self, key_value_map: Mapping[str, str]) -> bool: await self._execute_command(RequestType.MSetNX, parameters), ) - async def mget(self, keys: List[str]) -> List[Optional[str]]: + async def mget(self, keys: List[TEncodable]) -> List[Optional[bytes]]: """ Retrieve the values of multiple keys. See https://redis.io/commands/mget/ for more details. @@ -754,30 +755,30 @@ async def mget(self, keys: List[str]) -> List[Optional[str]]: When in cluster mode, the command may route to multiple nodes when `keys` map to different hash slots. Args: - keys (List[str]): A list of keys to retrieve values for. + keys (List[TEncodable]): A list of keys to retrieve values for. Returns: - List[Optional[str]]: A list of values corresponding to the provided keys. If a key is not found, + List[Optional[bytes]]: A list of values corresponding to the provided keys. If a key is not found, its corresponding value in the list will be None. Examples: >>> await client.set("key1", "value1") >>> await client.set("key2", "value2") >>> await client.mget(["key1", "key2"]) - ['value1' , 'value2'] + [b'value1' , b'value2'] """ return cast( - List[Optional[str]], await self._execute_command(RequestType.MGet, keys) + List[Optional[bytes]], await self._execute_command(RequestType.MGet, keys) ) - async def decr(self, key: str) -> int: + async def decr(self, key: TEncodable) -> int: """ Decrement the number stored at `key` by one. If the key does not exist, it is set to 0 before performing the operation. See https://redis.io/commands/decr/ for more details. Args: - key (str): The key to increment its value. + key (TEncodable): The key to increment its value. Returns: int: The value of key after the decrement. @@ -789,14 +790,14 @@ async def decr(self, key: str) -> int: """ return cast(int, await self._execute_command(RequestType.Decr, [key])) - async def decrby(self, key: str, amount: int) -> int: + async def decrby(self, key: TEncodable, amount: int) -> int: """ Decrements the number stored at `key` by `amount`. If the key does not exist, it is set to 0 before performing the operation. See https://redis.io/commands/decrby/ for more details. Args: - key (str): The key to decrement its value. + key (TEncodable): The key to decrement its value. amount (int) : The amount to decrement. Returns: @@ -811,7 +812,7 @@ async def decrby(self, key: str, amount: int) -> int: int, await self._execute_command(RequestType.DecrBy, [key, str(amount)]) ) - async def touch(self, keys: List[str]) -> int: + async def touch(self, keys: List[TEncodable]) -> int: """ Updates the last access time of specified keys. @@ -821,7 +822,7 @@ async def touch(self, keys: List[str]) -> int: When in cluster mode, the command may route to multiple nodes when `keys` map to different hash slots. Args: - keys (List[str]): The keys to update last access time. + keys (List[TEncodable]): The keys to update last access time. Returns: int: The number of keys that were updated, a key is ignored if it doesn't exist. @@ -834,14 +835,18 @@ async def touch(self, keys: List[str]) -> int: """ return cast(int, await self._execute_command(RequestType.Touch, keys)) - async def hset(self, key: str, field_value_map: Mapping[str, str]) -> int: + async def hset( + self, + key: TEncodable, + field_value_map: Mapping[TEncodable, TEncodable], + ) -> int: """ Sets the specified fields to their respective values in the hash stored at `key`. See https://redis.io/commands/hset/ for more details. Args: - key (str): The key of the hash. - field_value_map (Mapping[str, str]): A field-value map consisting of fields and their corresponding values + key (TEncodable): The key of the hash. + field_value_map (Mapping[TEncodable, TEncodable]): A field-value map consisting of fields and their corresponding values to be set in the hash stored at the specified key. Returns: @@ -851,7 +856,7 @@ async def hset(self, key: str, field_value_map: Mapping[str, str]) -> int: >>> await client.hset("my_hash", {"field": "value", "field2": "value2"}) 2 # Indicates that 2 fields were successfully set in the hash "my_hash". """ - field_value_list: List[str] = [key] + field_value_list: List[TEncodable] = [key] for pair in field_value_map.items(): field_value_list.extend(pair) return cast( @@ -859,36 +864,36 @@ async def hset(self, key: str, field_value_map: Mapping[str, str]) -> int: await self._execute_command(RequestType.HSet, field_value_list), ) - async def hget(self, key: str, field: str) -> Optional[str]: + async def hget(self, key: TEncodable, field: TEncodable) -> Optional[bytes]: """ Retrieves the value associated with `field` in the hash stored at `key`. See https://redis.io/commands/hget/ for more details. Args: - key (str): The key of the hash. - field (str): The field whose value should be retrieved. + key (TEncodable): The key of the hash. + field (TEncodable): The field whose value should be retrieved. Returns: - Optional[str]: The value associated `field` in the hash. + Optional[bytes]: The value associated `field` in the hash. Returns None if `field` is not presented in the hash or `key` does not exist. Examples: >>> await client.hset("my_hash", "field", "value") >>> await client.hget("my_hash", "field") - "value" + b"value" >>> await client.hget("my_hash", "nonexistent_field") None """ return cast( - Optional[str], + Optional[bytes], await self._execute_command(RequestType.HGet, [key, field]), ) async def hsetnx( self, - key: str, - field: str, - value: str, + key: TEncodable, + field: TEncodable, + value: TEncodable, ) -> bool: """ Sets `field` in the hash stored at `key` to `value`, only if `field` does not yet exist. @@ -897,9 +902,9 @@ async def hsetnx( See https://redis.io/commands/hsetnx/ for more details. Args: - key (str): The key of the hash. - field (str): The field to set the value for. - value (str): The value to set. + key (TEncodable): The key of the hash. + field (TEncodable): The field to set the value for. + value (TEncodable): The value to set. Returns: bool: True if the field was set, False if the field already existed and was not set. @@ -915,7 +920,7 @@ async def hsetnx( await self._execute_command(RequestType.HSetNX, [key, field, value]), ) - async def hincrby(self, key: str, field: str, amount: int) -> int: + async def hincrby(self, key: TEncodable, field: TEncodable, amount: int) -> int: """ Increment or decrement the value of a `field` in the hash stored at `key` by the specified amount. By using a negative increment value, the value stored at `field` in the hash stored at `key` is decremented. @@ -923,8 +928,8 @@ async def hincrby(self, key: str, field: str, amount: int) -> int: See https://redis.io/commands/hincrby/ for more details. Args: - key (str): The key of the hash. - field (str): The field in the hash stored at `key` to increment or decrement its value. + key (TEncodable): The key of the hash. + field (TEncodable): The field in the hash stored at `key` to increment or decrement its value. amount (int): The amount by which to increment or decrement the field's value. Use a negative value to decrement. @@ -940,7 +945,9 @@ async def hincrby(self, key: str, field: str, amount: int) -> int: await self._execute_command(RequestType.HIncrBy, [key, field, str(amount)]), ) - async def hincrbyfloat(self, key: str, field: str, amount: float) -> float: + async def hincrbyfloat( + self, key: TEncodable, field: TEncodable, amount: float + ) -> float: """ Increment or decrement the floating-point value stored at `field` in the hash stored at `key` by the specified amount. @@ -949,8 +956,8 @@ async def hincrbyfloat(self, key: str, field: str, amount: float) -> float: See https://redis.io/commands/hincrbyfloat/ for more details. Args: - key (str): The key of the hash. - field (str): The field in the hash stored at `key` to increment or decrement its value. + key (TEncodable): The key of the hash. + field (TEncodable): The field in the hash stored at `key` to increment or decrement its value. amount (float): The amount by which to increment or decrement the field's value. Use a negative value to decrement. @@ -968,14 +975,14 @@ async def hincrbyfloat(self, key: str, field: str, amount: float) -> float: ), ) - async def hexists(self, key: str, field: str) -> bool: + async def hexists(self, key: TEncodable, field: TEncodable) -> bool: """ Check if a field exists in the hash stored at `key`. See https://redis.io/commands/hexists/ for more details. Args: - key (str): The key of the hash. - field (str): The field to check in the hash stored at `key`. + key (TEncodable): The key of the hash. + field (TEncodable): The field to check in the hash stored at `key`. Returns: bool: Returns 'True' if the hash contains the specified field. If the hash does not contain the field, @@ -991,58 +998,60 @@ async def hexists(self, key: str, field: str) -> bool: bool, await self._execute_command(RequestType.HExists, [key, field]) ) - async def hgetall(self, key: str) -> Dict[str, str]: + async def hgetall(self, key: TEncodable) -> Dict[bytes, bytes]: """ Returns all fields and values of the hash stored at `key`. See https://redis.io/commands/hgetall/ for details. Args: - key (str): The key of the hash. + key (TEncodable): The key of the hash. Returns: - Dict[str, str]: A dictionary of fields and their values stored in the hash. Every field name in the list is followed by + Dict[bytes, bytes]: A dictionary of fields and their values stored in the hash. Every field name in the list is followed by its value. If `key` does not exist, it returns an empty dictionary. Examples: >>> await client.hgetall("my_hash") - {"field1": "value1", "field2": "value2"} + {b"field1": b"value1", b"field2": b"value2"} """ return cast( - Dict[str, str], await self._execute_command(RequestType.HGetAll, [key]) + Dict[bytes, bytes], await self._execute_command(RequestType.HGetAll, [key]) ) - async def hmget(self, key: str, fields: List[str]) -> List[Optional[str]]: + async def hmget( + self, key: TEncodable, fields: List[TEncodable] + ) -> List[Optional[bytes]]: """ Retrieve the values associated with specified fields in the hash stored at `key`. See https://redis.io/commands/hmget/ for details. Args: - key (str): The key of the hash. - fields (List[str]): The list of fields in the hash stored at `key` to retrieve from the database. + key (TEncodable): The key of the hash. + fields (List[TEncodable]): The list of fields in the hash stored at `key` to retrieve from the database. Returns: - List[Optional[str]]: A list of values associated with the given fields, in the same order as they are requested. + List[Optional[bytes]]: A list of values associated with the given fields, in the same order as they are requested. For every field that does not exist in the hash, a null value is returned. If `key` does not exist, it is treated as an empty hash, and the function returns a list of null values. Examples: >>> await client.hmget("my_hash", ["field1", "field2"]) - ["value1", "value2"] # A list of values associated with the specified fields. + [b"value1", b"value2"] # A list of values associated with the specified fields. """ return cast( - List[Optional[str]], + List[Optional[bytes]], await self._execute_command(RequestType.HMGet, [key] + fields), ) - async def hdel(self, key: str, fields: List[str]) -> int: + async def hdel(self, key: TEncodable, fields: List[TEncodable]) -> int: """ Remove specified fields from the hash stored at `key`. See https://redis.io/commands/hdel/ for more details. Args: - key (str): The key of the hash. - fields (List[str]): The list of fields to remove from the hash stored at `key`. + key (TEncodable): The key of the hash. + fields (List[TEncodable]): The list of fields to remove from the hash stored at `key`. Returns: int: The number of fields that were removed from the hash, excluding specified but non-existing fields. @@ -1054,14 +1063,14 @@ async def hdel(self, key: str, fields: List[str]) -> int: """ return cast(int, await self._execute_command(RequestType.HDel, [key] + fields)) - async def hlen(self, key: str) -> int: + async def hlen(self, key: TEncodable) -> int: """ Returns the number of fields contained in the hash stored at `key`. See https://redis.io/commands/hlen/ for more details. Args: - key (str): The key of the hash. + key (TEncodable): The key of the hash. Returns: int: The number of fields in the hash, or 0 when the key does not exist. @@ -1075,127 +1084,129 @@ async def hlen(self, key: str) -> int: """ return cast(int, await self._execute_command(RequestType.HLen, [key])) - async def hvals(self, key: str) -> List[str]: + async def hvals(self, key: TEncodable) -> List[bytes]: """ Returns all values in the hash stored at `key`. See https://redis.io/commands/hvals/ for more details. Args: - key (str): The key of the hash. + key (TEncodable): The key of the hash. Returns: - List[str]: A list of values in the hash, or an empty list when the key does not exist. + List[bytes]: A list of values in the hash, or an empty list when the key does not exist. Examples: >>> await client.hvals("my_hash") - ["value1", "value2", "value3"] # Returns all the values stored in the hash "my_hash". + [b"value1", b"value2", b"value3"] # Returns all the values stored in the hash "my_hash". """ - return cast(List[str], await self._execute_command(RequestType.HVals, [key])) + return cast(List[bytes], await self._execute_command(RequestType.HVals, [key])) - async def hkeys(self, key: str) -> List[str]: + async def hkeys(self, key: TEncodable) -> List[bytes]: """ Returns all field names in the hash stored at `key`. See https://redis.io/commands/hkeys/ for more details. Args: - key (str): The key of the hash. + key (TEncodable): The key of the hash. Returns: - List[str]: A list of field names for the hash, or an empty list when the key does not exist. + List[bytes]: A list of field names for the hash, or an empty list when the key does not exist. Examples: >>> await client.hkeys("my_hash") - ["field1", "field2", "field3"] # Returns all the field names stored in the hash "my_hash". + [b"field1", b"field2", b"field3"] # Returns all the field names stored in the hash "my_hash". """ - return cast(List[str], await self._execute_command(RequestType.HKeys, [key])) + return cast(List[bytes], await self._execute_command(RequestType.HKeys, [key])) - async def hrandfield(self, key: str) -> Optional[str]: + async def hrandfield(self, key: TEncodable) -> Optional[bytes]: """ Returns a random field name from the hash value stored at `key`. See https://valkey.io/commands/hrandfield for more details. Args: - key (str): The key of the hash. + key (TEncodable): The key of the hash. Returns: - Optional[str]: A random field name from the hash stored at `key`. + Optional[bytes]: A random field name from the hash stored at `key`. If the hash does not exist or is empty, None will be returned. Examples: >>> await client.hrandfield("my_hash") - "field1" # A random field name stored in the hash "my_hash". + b"field1" # A random field name stored in the hash "my_hash". """ return cast( - Optional[str], await self._execute_command(RequestType.HRandField, [key]) + Optional[bytes], await self._execute_command(RequestType.HRandField, [key]) ) - async def hrandfield_count(self, key: str, count: int) -> List[str]: + async def hrandfield_count(self, key: TEncodable, count: int) -> List[bytes]: """ Retrieves up to `count` random field names from the hash value stored at `key`. See https://valkey.io/commands/hrandfield for more details. Args: - key (str): The key of the hash. + key (TEncodable): The key of the hash. count (int): The number of field names to return. If `count` is positive, returns unique elements. If `count` is negative, allows for duplicates elements. Returns: - List[str]: A list of random field names from the hash. + List[bytes]: A list of random field names from the hash. If the hash does not exist or is empty, the response will be an empty list. Examples: >>> await client.hrandfield_count("my_hash", -3) - ["field1", "field1", "field2"] # Non-distinct, random field names stored in the hash "my_hash". + [b"field1", b"field1", b"field2"] # Non-distinct, random field names stored in the hash "my_hash". >>> await client.hrandfield_count("non_existing_hash", 3) [] # Empty list """ return cast( - List[str], + List[bytes], await self._execute_command(RequestType.HRandField, [key, str(count)]), ) - async def hrandfield_withvalues(self, key: str, count: int) -> List[List[str]]: + async def hrandfield_withvalues( + self, key: TEncodable, count: int + ) -> List[List[bytes]]: """ Retrieves up to `count` random field names along with their values from the hash value stored at `key`. See https://valkey.io/commands/hrandfield for more details. Args: - key (str): The key of the hash. + key (TEncodable): The key of the hash. count (int): The number of field names to return. If `count` is positive, returns unique elements. If `count` is negative, allows for duplicates elements. Returns: - List[List[str]]: A list of `[field_name, value]` lists, where `field_name` is a random field name from the + List[List[bytes]]: A list of `[field_name, value]` lists, where `field_name` is a random field name from the hash and `value` is the associated value of the field name. If the hash does not exist or is empty, the response will be an empty list. Examples: >>> await client.hrandfield_withvalues("my_hash", -3) - [["field1", "value1"], ["field1", "value1"], ["field2", "value2"]] + [[b"field1", b"value1"], [b"field1", b"value1"], [b"field2", b"value2"]] """ return cast( - List[List[str]], + List[List[bytes]], await self._execute_command( RequestType.HRandField, [key, str(count), "WITHVALUES"] ), ) - async def hstrlen(self, key: str, field: str) -> int: + async def hstrlen(self, key: TEncodable, field: TEncodable) -> int: """ Returns the string length of the value associated with `field` in the hash stored at `key`. See https://valkey.io/commands/hstrlen/ for more details. Args: - key (str): The key of the hash. - field (str): The field in the hash. + key (TEncodable): The key of the hash. + field (TEncodable): The field in the hash. Returns: int: The string length or 0 if `field` or `key` does not exist. @@ -1210,7 +1221,7 @@ async def hstrlen(self, key: str, field: str) -> int: await self._execute_command(RequestType.HStrlen, [key, field]), ) - async def lpush(self, key: str, elements: List[str]) -> int: + async def lpush(self, key: TEncodable, elements: List[TEncodable]) -> int: """ Insert all the specified values at the head of the list stored at `key`. `elements` are inserted one after the other to the head of the list, from the leftmost element @@ -1218,8 +1229,8 @@ async def lpush(self, key: str, elements: List[str]) -> int: See https://redis.io/commands/lpush/ for more details. Args: - key (str): The key of the list. - elements (List[str]): The elements to insert at the head of the list stored at `key`. + key (TEncodable): The key of the list. + elements (List[TEncodable]): The elements to insert at the head of the list stored at `key`. Returns: int: The length of the list after the push operations. @@ -1234,7 +1245,7 @@ async def lpush(self, key: str, elements: List[str]) -> int: int, await self._execute_command(RequestType.LPush, [key] + elements) ) - async def lpushx(self, key: str, elements: List[str]) -> int: + async def lpushx(self, key: TEncodable, elements: List[TEncodable]) -> int: """ Inserts all the specified values at the head of the list stored at `key`, only if `key` exists and holds a list. If `key` is not a list, this performs no operation. @@ -1242,8 +1253,8 @@ async def lpushx(self, key: str, elements: List[str]) -> int: See https://redis.io/commands/lpushx/ for more details. Args: - key (str): The key of the list. - elements (List[str]): The elements to insert at the head of the list stored at `key`. + key (TEncodable): The key of the list. + elements (List[TEncodable]): The elements to insert at the head of the list stored at `key`. Returns: int: The length of the list after the push operation. @@ -1258,55 +1269,57 @@ async def lpushx(self, key: str, elements: List[str]) -> int: int, await self._execute_command(RequestType.LPushX, [key] + elements) ) - async def lpop(self, key: str) -> Optional[str]: + async def lpop(self, key: TEncodable) -> Optional[bytes]: """ Remove and return the first elements of the list stored at `key`. 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. + key (TEncodable): The key of the list. Returns: - Optional[str]: The value of the first element. + Optional[bytes]: The value of the first element. If `key` does not exist, None will be returned. Examples: >>> await client.lpop("my_list") - "value1" + b"value1" >>> await client.lpop("non_exiting_key") None """ return cast( - Optional[str], + Optional[bytes], await self._execute_command(RequestType.LPop, [key]), ) - async def lpop_count(self, key: str, count: int) -> Optional[List[str]]: + async def lpop_count(self, key: TEncodable, count: int) -> Optional[List[bytes]]: """ 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. + key (TEncodable): 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. + Optional[List[bytes]]: A a list of popped elements will be returned depending on the list's length. If `key` does not exist, None will be returned. Examples: >>> await client.lpop_count("my_list", 2) - ["value1", "value2"] + [b"value1", b"value2"] >>> await client.lpop_count("non_exiting_key" , 3) None """ return cast( - Optional[List[str]], + Optional[List[bytes]], await self._execute_command(RequestType.LPop, [key, str(count)]), ) - async def blpop(self, keys: List[str], timeout: float) -> Optional[List[str]]: + async def blpop( + self, keys: List[TEncodable], timeout: float + ) -> Optional[List[bytes]]: """ Pops an element from the head of the first list that is non-empty, with the given keys being checked in the order that they are given. Blocks the connection when there are no elements to pop from any of the given lists. @@ -1317,25 +1330,28 @@ async def blpop(self, keys: List[str], timeout: float) -> Optional[List[str]]: 2. `BLPOP` is a client blocking command, see https://github.com/aws/glide-for-redis/wiki/General-Concepts#blocking-commands for more details and best practices. Args: - keys (List[str]): The keys of the lists to pop from. + keys (List[TEncodable]): The keys of the lists to pop from. timeout (float): The number of seconds to wait for a blocking operation to complete. A value of 0 will block indefinitely. Returns: - Optional[List[str]]: A two-element list containing the key from which the element was popped and the value of the + Optional[List[bytes]]: A two-element list containing the key from which the element was popped and the value of the popped element, formatted as `[key, value]`. If no element could be popped and the `timeout` expired, returns None. Examples: >>> await client.blpop(["list1", "list2"], 0.5) - ["list1", "element"] # "element" was popped from the head of the list with key "list1" + [b"list1", b"element"] # "element" was popped from the head of the list with key "list1" """ return cast( - Optional[List[str]], + Optional[List[bytes]], await self._execute_command(RequestType.BLPop, keys + [str(timeout)]), ) async def lmpop( - self, keys: List[str], direction: ListDirection, count: Optional[int] = None - ) -> Optional[Mapping[str, List[str]]]: + self, + keys: List[TEncodable], + direction: ListDirection, + count: Optional[int] = None, + ) -> Optional[Mapping[bytes, List[bytes]]]: """ Pops one or more elements from the first non-empty list from the provided `keys`. @@ -1344,17 +1360,17 @@ async def lmpop( See https://valkey.io/commands/lmpop/ for details. Args: - keys (List[str]): An array of keys of lists. + keys (List[TEncodable]): An array of keys of lists. direction (ListDirection): The direction based on which elements are popped from (`ListDirection.LEFT` or `ListDirection.RIGHT`). count (Optional[int]): The maximum number of popped elements. If not provided, defaults to popping a single element. Returns: - Optional[Mapping[str, List[str]]]: A map of `key` name mapped to an array of popped elements, or None if no elements could be popped. + Optional[Mapping[bytes, List[bytes]]]: A map of `key` name mapped to an array of popped elements, or None if no elements could be popped. Examples: >>> await client.lpush("testKey", ["one", "two", "three"]) >>> await client.lmpop(["testKey"], ListDirection.LEFT, 2) - {"testKey": ["three", "two"]} + {b"testKey": [b"three", b"two"]} Since: Redis version 7.0.0. """ @@ -1363,17 +1379,17 @@ async def lmpop( args += ["COUNT", str(count)] return cast( - Optional[Mapping[str, List[str]]], + Optional[Mapping[bytes, List[bytes]]], await self._execute_command(RequestType.LMPop, args), ) async def blmpop( self, - keys: List[str], + keys: List[TEncodable], direction: ListDirection, timeout: float, count: Optional[int] = None, - ) -> Optional[Mapping[str, List[str]]]: + ) -> Optional[Mapping[bytes, List[bytes]]]: """ Blocks the connection until it pops one or more elements from the first non-empty list from the provided `keys`. @@ -1386,18 +1402,18 @@ async def blmpop( See https://valkey.io/commands/blmpop/ for details. Args: - keys (List[str]): An array of keys of lists. + keys (List[TEncodable]): An array of keys of lists. direction (ListDirection): The direction based on which elements are popped from (`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. count (Optional[int]): The maximum number of popped elements. If not provided, defaults to popping a single element. Returns: - Optional[Mapping[str, List[str]]]: A map of `key` name mapped to an array of popped elements, or None if no elements could be popped and the timeout expired. + Optional[Mapping[bytes, List[bytes]]]: A map of `key` name mapped to an array of popped elements, or None if no elements could be popped and the timeout expired. Examples: >>> await client.lpush("testKey", ["one", "two", "three"]) >>> await client.blmpop(["testKey"], ListDirection.LEFT, 0.1, 2) - {"testKey": ["three", "two"]} + {b"testKey": [b"three", b"two"]} Since: Redis version 7.0.0. """ @@ -1406,11 +1422,11 @@ async def blmpop( args += ["COUNT", str(count)] return cast( - Optional[Mapping[str, List[str]]], + Optional[Mapping[bytes, List[bytes]]], await self._execute_command(RequestType.BLMPop, args), ) - async def lrange(self, key: str, start: int, end: int) -> List[str]: + async def lrange(self, key: TEncodable, start: int, end: int) -> List[bytes]: """ Retrieve the specified elements of the list stored at `key` within the given range. The offsets `start` and `end` are zero-based indexes, with 0 being the first element of the list, 1 being the next @@ -1419,26 +1435,26 @@ async def lrange(self, key: str, start: int, end: int) -> List[str]: See https://redis.io/commands/lrange/ for details. Args: - key (str): The key of the list. + key (TEncodable): The key of the list. start (int): The starting point of the range. end (int): The end of the range. Returns: - List[str]: A list of elements within the specified range. + List[bytes]: A list of elements within the specified range. If `start` exceeds the `end` of the list, or if `start` is greater than `end`, an empty list will be returned. If `end` exceeds the actual end of the list, the range will stop at the actual end of the list. If `key` does not exist an empty list will be returned. Examples: >>> await client.lrange("my_list", 0, 2) - ["value1", "value2", "value3"] + [b"value1", b"value2", b"value3"] >>> await client.lrange("my_list", -2, -1) - ["value2", "value3"] + [b"value2", b"value3"] >>> await client.lrange("non_exiting_key", 0, 2) [] """ return cast( - List[str], + List[bytes], await self._execute_command( RequestType.LRange, [key, str(start), str(end)] ), @@ -1446,9 +1462,9 @@ async def lrange(self, key: str, start: int, end: int) -> List[str]: async def lindex( self, - key: str, + key: TEncodable, index: int, - ) -> Optional[str]: + ) -> Optional[bytes]: """ Returns the element at `index` in the list stored at `key`. @@ -1459,25 +1475,25 @@ async def lindex( See https://redis.io/commands/lindex/ for more details. Args: - key (str): The key of the list. + key (TEncodable): The key of the list. index (int): The index of the element in the list to retrieve. Returns: - Optional[str]: The element at `index` in the list stored at `key`. + Optional[bytes]: The element at `index` in the list stored at `key`. If `index` is out of range or if `key` does not exist, None is returned. Examples: >>> await client.lindex("my_list", 0) - 'value1' # Returns the first element in the list stored at 'my_list'. + b'value1' # Returns the first element in the list stored at 'my_list'. >>> await client.lindex("my_list", -1) - 'value3' # Returns the last element in the list stored at 'my_list'. + b'value3' # Returns the last element in the list stored at 'my_list'. """ return cast( - Optional[str], + Optional[bytes], await self._execute_command(RequestType.LIndex, [key, str(index)]), ) - async def lset(self, key: str, index: int, element: str) -> TOK: + async def lset(self, key: TEncodable, index: int, element: TEncodable) -> TOK: """ Sets the list element at `index` to `element`. @@ -1488,9 +1504,9 @@ async def lset(self, key: str, index: int, element: str) -> TOK: See https://valkey.io/commands/lset/ for details. Args: - key (str): The key of the list. + key (TEncodable): The key of the list. index (int): The index of the element in the list to be set. - element (str): The new element to set at the specified index. + element (TEncodable): The new element to set at the specified index. Returns: TOK: A simple `OK` response. @@ -1504,7 +1520,7 @@ async def lset(self, key: str, index: int, element: str) -> TOK: await self._execute_command(RequestType.LSet, [key, str(index), element]), ) - async def rpush(self, key: str, elements: List[str]) -> int: + async def rpush(self, key: TEncodable, elements: List[TEncodable]) -> int: """ Inserts all the specified values at the tail of the list stored at `key`. `elements` are inserted one after the other to the tail of the list, from the leftmost element @@ -1512,8 +1528,8 @@ async def rpush(self, key: str, elements: List[str]) -> int: See https://redis.io/commands/rpush/ for more details. Args: - key (str): The key of the list. - elements (List[str]): The elements to insert at the tail of the list stored at `key`. + key (TEncodable): The key of the list. + elements (List[TEncodable]): The elements to insert at the tail of the list stored at `key`. Returns: int: The length of the list after the push operations. @@ -1528,7 +1544,7 @@ async def rpush(self, key: str, elements: List[str]) -> int: int, await self._execute_command(RequestType.RPush, [key] + elements) ) - async def rpushx(self, key: str, elements: List[str]) -> int: + async def rpushx(self, key: TEncodable, elements: List[TEncodable]) -> int: """ Inserts all the specified values at the tail of the list stored at `key`, only if `key` exists and holds a list. If `key` is not a list, this performs no operation. @@ -1536,8 +1552,8 @@ async def rpushx(self, key: str, elements: List[str]) -> int: See https://redis.io/commands/rpushx/ for more details. Args: - key (str): The key of the list. - elements (List[str]): The elements to insert at the tail of the list stored at `key`. + key (TEncodable): The key of the list. + elements (List[TEncodable]): The elements to insert at the tail of the list stored at `key`. Returns: int: The length of the list after the push operation. @@ -1552,55 +1568,57 @@ async def rpushx(self, key: str, elements: List[str]) -> int: int, await self._execute_command(RequestType.RPushX, [key] + elements) ) - async def rpop(self, key: str, count: Optional[int] = None) -> Optional[str]: + async def rpop(self, key: TEncodable) -> Optional[bytes]: """ Removes and returns the last elements of the list stored at `key`. 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. + key (TEncodable): The key of the list. Returns: - Optional[str]: The value of the last element. + Optional[bytes]: The value of the last element. If `key` does not exist, None will be returned. Examples: >>> await client.rpop("my_list") - "value1" + b"value1" >>> await client.rpop("non_exiting_key") None """ return cast( - Optional[str], + Optional[bytes], await self._execute_command(RequestType.RPop, [key]), ) - async def rpop_count(self, key: str, count: int) -> Optional[List[str]]: + async def rpop_count(self, key: TEncodable, count: int) -> Optional[List[bytes]]: """ 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. + key (TEncodable): 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. + Optional[List[bytes]: A list of popped elements will be returned depending on the list's length. If `key` does not exist, None will be returned. Examples: >>> await client.rpop_count("my_list", 2) - ["value1", "value2"] + [b"value1", b"value2"] >>> await client.rpop_count("non_exiting_key" , 7) None """ return cast( - Optional[List[str]], + Optional[List[bytes]], await self._execute_command(RequestType.RPop, [key, str(count)]), ) - async def brpop(self, keys: List[str], timeout: float) -> Optional[List[str]]: + async def brpop( + self, keys: List[TEncodable], timeout: float + ) -> Optional[List[bytes]]: """ Pops an element from the tail of the first list that is non-empty, with the given keys being checked in the order that they are given. Blocks the connection when there are no elements to pop from any of the given lists. @@ -1611,24 +1629,28 @@ async def brpop(self, keys: List[str], timeout: float) -> Optional[List[str]]: 2. `BRPOP` is a client blocking command, see https://github.com/aws/glide-for-redis/wiki/General-Concepts#blocking-commands for more details and best practices. Args: - keys (List[str]): The keys of the lists to pop from. + keys (List[TEncodable]): The keys of the lists to pop from. timeout (float): The number of seconds to wait for a blocking operation to complete. A value of 0 will block indefinitely. Returns: - Optional[List[str]]: A two-element list containing the key from which the element was popped and the value of the + Optional[List[bytes]]: A two-element list containing the key from which the element was popped and the value of the popped element, formatted as `[key, value]`. If no element could be popped and the `timeout` expired, returns None. Examples: >>> await client.brpop(["list1", "list2"], 0.5) - ["list1", "element"] # "element" was popped from the tail of the list with key "list1" + [b"list1", b"element"] # "element" was popped from the tail of the list with key "list1" """ return cast( - Optional[List[str]], + Optional[List[bytes]], await self._execute_command(RequestType.BRPop, keys + [str(timeout)]), ) async def linsert( - self, key: str, position: InsertPosition, pivot: str, element: str + self, + key: TEncodable, + position: InsertPosition, + pivot: TEncodable, + element: TEncodable, ) -> int: """ Inserts `element` in the list at `key` either before or after the `pivot`. @@ -1636,11 +1658,11 @@ async def linsert( See https://redis.io/commands/linsert/ for details. Args: - key (str): The key of the list. + key (TEncodable): The key of the list. position (InsertPosition): The relative position to insert into - either `InsertPosition.BEFORE` or `InsertPosition.AFTER` the `pivot`. - pivot (str): An element of the list. - element (str): The new element to insert. + pivot (TEncodable): An element of the list. + element (TEncodable): The new element to insert. Returns: int: The list length after a successful insert operation. @@ -1660,11 +1682,11 @@ async def linsert( async def lmove( self, - source: str, - destination: str, + source: TEncodable, + destination: TEncodable, where_from: ListDirection, where_to: ListDirection, - ) -> Optional[str]: + ) -> Optional[bytes]: """ 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 @@ -1675,28 +1697,28 @@ async def lmove( 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. + source (TEncodable): The key to the source list. + destination (TEncodable): 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. + Optional[bytes]: 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" + b"one" >>> updated_array1 = await client.lrange("testKey1", 0, -1) - ["two"] + [b"two"] >>> await client.lrange("testKey2", 0, -1) - ["one", "three", "four"] + [b"one", b"three", b"four"] Since: Redis version 6.2.0. """ return cast( - Optional[str], + Optional[bytes], await self._execute_command( RequestType.LMove, [source, destination, where_from.value, where_to.value], @@ -1705,12 +1727,12 @@ async def lmove( async def blmove( self, - source: str, - destination: str, + source: TEncodable, + destination: TEncodable, where_from: ListDirection, where_to: ListDirection, timeout: float, - ) -> Optional[str]: + ) -> Optional[bytes]: """ 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 @@ -1724,36 +1746,36 @@ async def blmove( 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. + source (TEncodable): The key to the source list. + destination (TEncodable): 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. + Optional[bytes]: 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" + b"one" >>> await client.lrange("testKey1", 0, -1) - ["two"] + [b"two"] >>> updated_array2 = await client.lrange("testKey2", 0, -1) - ["one", "three", "four"] + [b"one", b"three", bb"four"] Since: Redis version 6.2.0. """ return cast( - Optional[str], + Optional[bytes], 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: + async def sadd(self, key: TEncodable, members: List[TEncodable]) -> int: """ Add specified members to the set stored at `key`. Specified members that are already a member of this set are ignored. @@ -1761,8 +1783,8 @@ async def sadd(self, key: str, members: List[str]) -> int: See https://redis.io/commands/sadd/ for more details. Args: - key (str): The key where members will be added to its set. - members (List[str]): A list of members to add to the set stored at `key`. + key (TEncodable): The key where members will be added to its set. + members (List[TEncodable]): A list of members to add to the set stored at `key`. Returns: int: The number of members that were added to the set, excluding members already present. @@ -1773,15 +1795,15 @@ async def sadd(self, key: str, members: List[str]) -> int: """ return cast(int, await self._execute_command(RequestType.SAdd, [key] + members)) - async def srem(self, key: str, members: List[str]) -> int: + async def srem(self, key: TEncodable, members: List[TEncodable]) -> int: """ Remove specified members from the set stored at `key`. Specified members that are not a member of this set are ignored. See https://redis.io/commands/srem/ for details. Args: - key (str): The key from which members will be removed. - members (List[str]): A list of members to remove from the set stored at `key`. + key (TEncodable): The key from which members will be removed. + members (List[TEncodable]): A list of members to remove from the set stored at `key`. Returns: int: The number of members that were removed from the set, excluding non-existing members. @@ -1793,31 +1815,33 @@ async def srem(self, key: str, members: List[str]) -> int: """ return cast(int, await self._execute_command(RequestType.SRem, [key] + members)) - async def smembers(self, key: str) -> Set[str]: + async def smembers(self, key: TEncodable) -> Set[bytes]: """ Retrieve all the members of the set value stored at `key`. See https://redis.io/commands/smembers/ for details. Args: - key (str): The key from which to retrieve the set members. + key (TEncodable): The key from which to retrieve the set members. Returns: - Set[str]: A set of all members of the set. + Set[bytes]: A set of all members of the set. If `key` does not exist an empty set will be returned. Examples: >>> await client.smembers("my_set") - {"member1", "member2", "member3"} + {b"member1", b"member2", b"member3"} """ - return cast(Set[str], await self._execute_command(RequestType.SMembers, [key])) + return cast( + Set[bytes], await self._execute_command(RequestType.SMembers, [key]) + ) - async def scard(self, key: str) -> int: + async def scard(self, key: TEncodable) -> int: """ Retrieve the set cardinality (number of elements) of the set stored at `key`. See https://redis.io/commands/scard/ for details. Args: - key (str): The key from which to retrieve the number of set members. + key (TEncodable): The key from which to retrieve the number of set members. Returns: int: The cardinality (number of elements) of the set, or 0 if the key does not exist. @@ -1828,7 +1852,7 @@ async def scard(self, key: str) -> int: """ return cast(int, await self._execute_command(RequestType.SCard, [key])) - async def spop(self, key: str) -> Optional[str]: + async def spop(self, key: TEncodable) -> Optional[bytes]: """ Removes and returns one random member from the set stored at `key`. @@ -1836,21 +1860,23 @@ async def spop(self, key: str) -> Optional[str]: To pop multiple members, see `spop_count`. Args: - key (str): The key of the set. + key (TEncodable): The key of the set. Returns: - Optional[str]: The value of the popped member. + Optional[bytes]: The value of the popped member. If `key` does not exist, None will be returned. Examples: >>> await client.spop("my_set") - "value1" # Removes and returns a random member from the set "my_set". + b"value1" # Removes and returns a random member from the set "my_set". >>> await client.spop("non_exiting_key") None """ - return cast(Optional[str], await self._execute_command(RequestType.SPop, [key])) + return cast( + Optional[bytes], await self._execute_command(RequestType.SPop, [key]) + ) - async def spop_count(self, key: str, count: int) -> Set[str]: + async def spop_count(self, key: TEncodable, count: int) -> Set[bytes]: """ Removes and returns up to `count` random members from the set stored at `key`, depending on the set's length. @@ -1858,27 +1884,27 @@ async def spop_count(self, key: str, count: int) -> Set[str]: To pop a single member, see `spop`. Args: - key (str): The key of the set. + key (TEncodable): The key of the set. count (int): The count of the elements to pop from the set. Returns: - Set[str]: A set of popped elements will be returned depending on the set's length. + Set[bytes]: A set of popped elements will be returned depending on the set's length. If `key` does not exist, an empty set will be returned. Examples: >>> await client.spop_count("my_set", 2) - {"value1", "value2"} # Removes and returns 2 random members from the set "my_set". + {b"value1", b"value2"} # Removes and returns 2 random members from the set "my_set". >>> await client.spop_count("non_exiting_key", 2) Set() """ return cast( - Set[str], await self._execute_command(RequestType.SPop, [key, str(count)]) + Set[bytes], await self._execute_command(RequestType.SPop, [key, str(count)]) ) async def sismember( self, - key: str, - member: str, + key: TEncodable, + member: TEncodable, ) -> bool: """ Returns if `member` is a member of the set stored at `key`. @@ -1886,8 +1912,8 @@ async def sismember( See https://redis.io/commands/sismember/ for more details. Args: - key (str): The key of the set. - member (str): The member to check for existence in the set. + key (TEncodable): The key of the set. + member (TEncodable): The member to check for existence in the set. Returns: bool: True if the member exists in the set, False otherwise. @@ -1906,9 +1932,9 @@ async def sismember( async def smove( self, - source: str, - destination: str, - member: str, + source: TEncodable, + destination: TEncodable, + member: TEncodable, ) -> bool: """ Moves `member` from the set at `source` to the set at `destination`, removing it from the source set. Creates a @@ -1920,9 +1946,9 @@ async def smove( When in cluster mode, `source` and `destination` must map to the same hash slot. Args: - source (str): The key of the set to remove the element from. - destination (str): The key of the set to add the element to. - member (str): The set element to move. + source (TEncodable): The key of the set to remove the element from. + destination (TEncodable): The key of the set to add the element to. + member (TEncodable): The set element to move. Returns: bool: True on success, or False if the `source` set does not exist or the element is not a member of the source set. @@ -1938,7 +1964,7 @@ async def smove( ), ) - async def sunion(self, keys: List[str]) -> Set[str]: + async def sunion(self, keys: List[TEncodable]) -> Set[bytes]: """ Gets the union of all the given sets. @@ -1948,26 +1974,26 @@ async def sunion(self, keys: List[str]) -> Set[str]: When in cluster mode, all `keys` must map to the same hash slot. Args: - keys (List[str]): The keys of the sets. + keys (List[TEncodable]): The keys of the sets. Returns: - Set[str]: A set of members which are present in at least one of the given sets. + Set[bytes]: A set of members which are present in at least one of the given sets. If none of the sets exist, an empty set will be returned. Examples: >>> await client.sadd("my_set1", ["member1", "member2"]) >>> await client.sadd("my_set2", ["member2", "member3"]) >>> await client.sunion(["my_set1", "my_set2"]) - {"member1", "member2", "member3"} # sets "my_set1" and "my_set2" have three unique members + {b"member1", b"member2", b"member3"} # sets "my_set1" and "my_set2" have three unique members >>> await client.sunion(["my_set1", "non_existing_set"]) - {"member1", "member2"} + {b"member1", b"member2"} """ - return cast(Set[str], await self._execute_command(RequestType.SUnion, keys)) + return cast(Set[bytes], await self._execute_command(RequestType.SUnion, keys)) async def sunionstore( self, - destination: str, - keys: List[str], + destination: TEncodable, + keys: List[TEncodable], ) -> int: """ Stores the members of the union of all given sets specified by `keys` into a new set at `destination`. @@ -1978,8 +2004,8 @@ async def sunionstore( When in cluster mode, all keys in `keys` and `destination` must map to the same hash slot. Args: - destination (str): The key of the destination set. - keys (List[str]): The keys from which to retrieve the set members. + destination (TEncodable): The key of the destination set. + keys (List[TEncodable]): The keys from which to retrieve the set members. Returns: int: The number of elements in the resulting set. @@ -1995,7 +2021,7 @@ async def sunionstore( await self._execute_command(RequestType.SUnionStore, [destination] + keys), ) - async def sdiffstore(self, destination: str, keys: List[str]) -> int: + async def sdiffstore(self, destination: TEncodable, keys: List[TEncodable]) -> int: """ Stores the difference between the first set and all the successive sets in `keys` into a new set at `destination`. @@ -2006,8 +2032,8 @@ async def sdiffstore(self, destination: str, keys: List[str]) -> int: When in Cluster mode, all keys in `keys` and `destination` must map to the same hash slot. Args: - destination (str): The key of the destination set. - keys (List[str]): The keys of the sets to diff. + destination (TEncodable): The key of the destination set. + keys (List[TEncodable]): The keys of the sets to diff. Returns: int: The number of elements in the resulting set. @@ -2023,7 +2049,7 @@ async def sdiffstore(self, destination: str, keys: List[str]) -> int: await self._execute_command(RequestType.SDiffStore, [destination] + keys), ) - async def sinter(self, keys: List[str]) -> Set[str]: + async def sinter(self, keys: List[TEncodable]) -> Set[bytes]: """ Gets the intersection of all the given sets. @@ -2033,23 +2059,23 @@ async def sinter(self, keys: List[str]) -> Set[str]: When in cluster mode, all `keys` must map to the same hash slot. Args: - keys (List[str]): The keys of the sets. + keys (List[TEncodable]): The keys of the sets. Returns: - Set[str]: A set of members which are present in all given sets. + Set[bytes]: A set of members which are present in all given sets. If one or more sets do no exist, an empty set will be returned. Examples: >>> await client.sadd("my_set1", ["member1", "member2"]) >>> await client.sadd("my_set2", ["member2", "member3"]) >>> await client.sinter(["my_set1", "my_set2"]) - {"member2"} # sets "my_set1" and "my_set2" have one commom member + {b"member2"} # sets "my_set1" and "my_set2" have one commom member >>> await client.sinter([my_set1", "non_existing_set"]) None """ - return cast(Set[str], await self._execute_command(RequestType.SInter, keys)) + return cast(Set[bytes], await self._execute_command(RequestType.SInter, keys)) - async def sinterstore(self, destination: str, keys: List[str]) -> int: + async def sinterstore(self, destination: TEncodable, keys: List[TEncodable]) -> int: """ Stores the members of the intersection of all given sets specified by `keys` into a new set at `destination`. @@ -2059,8 +2085,8 @@ async def sinterstore(self, destination: str, keys: List[str]) -> int: When in Cluster mode, all `keys` and `destination` must map to the same hash slot. Args: - destination (str): The key of the destination set. - keys (List[str]): The keys from which to retrieve the set members. + destination (TEncodable): The key of the destination set. + keys (List[TEncodable]): The keys from which to retrieve the set members. Returns: int: The number of elements in the resulting set. @@ -2076,7 +2102,9 @@ async def sinterstore(self, destination: str, keys: List[str]) -> int: await self._execute_command(RequestType.SInterStore, [destination] + keys), ) - async def sintercard(self, keys: List[str], limit: Optional[int] = None) -> int: + async def sintercard( + self, keys: List[TEncodable], limit: Optional[int] = None + ) -> int: """ Gets the cardinality of the intersection of all the given sets. Optionally, a `limit` can be specified to stop the computation early if the intersection cardinality reaches the specified limit. @@ -2086,7 +2114,7 @@ async def sintercard(self, keys: List[str], limit: Optional[int] = None) -> int: See https://valkey.io/commands/sintercard for more details. Args: - keys (List[str]): A list of keys representing the sets to intersect. + keys (List[TEncodable]): A list of keys representing the sets to intersect. limit (Optional[int]): An optional limit to the maximum number of intersecting elements to count. If specified, the computation stops as soon as the cardinality reaches this limit. @@ -2102,8 +2130,8 @@ async def sintercard(self, keys: List[str], limit: Optional[int] = None) -> int: >>> await client.sintercard(["set1", "set2"], limit=1) 1 # The computation stops early as the intersection cardinality reaches the limit of 1. """ - args = [str(len(keys))] - args += keys + args: List[TEncodable] = [str(len(keys))] + args.extend(keys) if limit is not None: args += ["LIMIT", str(limit)] return cast( @@ -2111,7 +2139,7 @@ async def sintercard(self, keys: List[str], limit: Optional[int] = None) -> int: await self._execute_command(RequestType.SInterCard, args), ) - async def sdiff(self, keys: List[str]) -> Set[str]: + async def sdiff(self, keys: List[TEncodable]) -> Set[bytes]: """ Computes the difference between the first set and all the successive sets in `keys`. @@ -2121,32 +2149,34 @@ async def sdiff(self, keys: List[str]) -> Set[str]: When in cluster mode, all `keys` must map to the same hash slot. Args: - keys (List[str]): The keys of the sets to diff. + keys (List[TEncodable]): The keys of the sets to diff Returns: - Set[str]: A set of elements representing the difference between the sets. + Set[bytes]: A set of elements representing the difference between the sets. If any of the keys in `keys` do not exist, they are treated as empty sets. Examples: >>> await client.sadd("set1", ["member1", "member2"]) >>> await client.sadd("set2", ["member1"]) >>> await client.sdiff("set1", "set2") - {"member2"} # "member2" is in "set1" but not "set2" + {b"member2"} # "member2" is in "set1" but not "set2" """ return cast( - Set[str], + Set[bytes], await self._execute_command(RequestType.SDiff, keys), ) - async def smismember(self, key: str, members: List[str]) -> List[bool]: + async def smismember( + self, key: TEncodable, members: List[TEncodable] + ) -> List[bool]: """ Checks whether each member is contained in the members of the set stored at `key`. See https://valkey.io/commands/smismember for more details. Args: - key (str): The key of the set to check. - members (List[str]): A list of members to check for existence in the set. + key (TEncodable): The key of the set to check. + members (List[TEncodable]): A list of members to check for existence in the set. Returns: List[bool]: A list of bool values, each indicating if the respective member exists in the set. @@ -2161,7 +2191,7 @@ async def smismember(self, key: str, members: List[str]) -> List[bool]: await self._execute_command(RequestType.SMIsMember, [key] + members), ) - async def ltrim(self, key: str, start: int, end: int) -> TOK: + async def ltrim(self, key: TEncodable, start: int, end: int) -> TOK: """ Trim an existing list so that it will contain only the specified range of elements specified. The offsets `start` and `end` are zero-based indexes, with 0 being the first element of the list, 1 being the next @@ -2171,7 +2201,7 @@ async def ltrim(self, key: str, start: int, end: int) -> TOK: See https://redis.io/commands/ltrim/ for more details. Args: - key (str): The key of the list. + key (TEncodable): The key of the list. start (int): The starting point of the range. end (int): The end of the range. @@ -2191,7 +2221,7 @@ async def ltrim(self, key: str, start: int, end: int) -> TOK: await self._execute_command(RequestType.LTrim, [key, str(start), str(end)]), ) - async def lrem(self, key: str, count: int, element: str) -> int: + async def lrem(self, key: TEncodable, count: int, element: TEncodable) -> int: """ Removes the first `count` occurrences of elements equal to `element` from the list stored at `key`. If `count` is positive, it removes elements equal to `element` moving from head to tail. @@ -2201,9 +2231,9 @@ async def lrem(self, key: str, count: int, element: str) -> int: See https://redis.io/commands/lrem/ for more details. Args: - key (str): The key of the list. + key (TEncodable): The key of the list. count (int): The count of occurrences of elements equal to `element` to remove. - element (str): The element to remove from the list. + element (TEncodable): The element to remove from the list. Returns: int: The number of removed elements. @@ -2218,13 +2248,13 @@ async def lrem(self, key: str, count: int, element: str) -> int: await self._execute_command(RequestType.LRem, [key, str(count), element]), ) - async def llen(self, key: str) -> int: + async def llen(self, key: TEncodable) -> int: """ Get the length of the list stored at `key`. See https://redis.io/commands/llen/ for details. Args: - key (str): The key of the list. + key (TEncodable): The key of the list. Returns: int: The length of the list at the specified key. @@ -2236,7 +2266,7 @@ async def llen(self, key: str) -> int: """ return cast(int, await self._execute_command(RequestType.LLen, [key])) - async def exists(self, keys: List[str]) -> int: + async def exists(self, keys: List[TEncodable]) -> int: """ Returns the number of keys in `keys` that exist in the database. See https://redis.io/commands/exists/ for more details. @@ -2245,7 +2275,7 @@ async def exists(self, keys: List[str]) -> int: When in cluster mode, the command may route to multiple nodes when `keys` map to different hash slots. Args: - keys (List[str]): The list of keys to check. + keys (List[TEncodable]): The list of keys to check. Returns: int: The number of keys that exist. If the same existing key is mentioned in `keys` multiple times, @@ -2257,7 +2287,7 @@ async def exists(self, keys: List[str]) -> int: """ return cast(int, await self._execute_command(RequestType.Exists, keys)) - async def unlink(self, keys: List[str]) -> int: + async def unlink(self, keys: List[TEncodable]) -> int: """ Unlink (delete) multiple keys from the database. A key is ignored if it does not exist. @@ -2269,7 +2299,7 @@ async def unlink(self, keys: List[str]) -> int: When in cluster mode, the command may route to multiple nodes when `keys` map to different hash slots. Args: - keys (List[str]): The list of keys to unlink. + keys (List[TEncodable]): The list of keys to unlink. Returns: int: The number of keys that were unlinked. @@ -2281,7 +2311,10 @@ async def unlink(self, keys: List[str]) -> int: return cast(int, await self._execute_command(RequestType.Unlink, keys)) async def expire( - self, key: str, seconds: int, option: Optional[ExpireOptions] = None + self, + key: TEncodable, + seconds: int, + option: Optional[ExpireOptions] = None, ) -> bool: """ Sets a timeout on `key` in seconds. After the timeout has expired, the key will automatically be deleted. @@ -2291,7 +2324,7 @@ async def expire( See https://redis.io/commands/expire/ for more details. Args: - key (str): The key to set a timeout on. + key (TEncodable): The key to set a timeout on. seconds (int): The timeout in seconds. option (ExpireOptions, optional): The expire option. @@ -2303,13 +2336,16 @@ async def expire( >>> await client.expire("my_key", 60) True # Indicates that a timeout of 60 seconds has been set for "my_key." """ - args: List[str] = ( + args: List[TEncodable] = ( [key, str(seconds)] if option is None else [key, str(seconds), option.value] ) return cast(bool, await self._execute_command(RequestType.Expire, args)) async def expireat( - self, key: str, unix_seconds: int, option: Optional[ExpireOptions] = None + self, + key: TEncodable, + unix_seconds: int, + option: Optional[ExpireOptions] = None, ) -> bool: """ Sets a timeout on `key` using an absolute Unix timestamp (seconds since January 1, 1970) instead of specifying the @@ -2321,7 +2357,7 @@ async def expireat( See https://redis.io/commands/expireat/ for more details. Args: - key (str): The key to set a timeout on. + key (TEncodable): The key to set a timeout on. unix_seconds (int): The timeout in an absolute Unix timestamp. option (Optional[ExpireOptions]): The expire option. @@ -2341,7 +2377,10 @@ async def expireat( return cast(bool, await self._execute_command(RequestType.ExpireAt, args)) async def pexpire( - self, key: str, milliseconds: int, option: Optional[ExpireOptions] = None + self, + key: TEncodable, + milliseconds: int, + option: Optional[ExpireOptions] = None, ) -> bool: """ Sets a timeout on `key` in milliseconds. After the timeout has expired, the key will automatically be deleted. @@ -2351,7 +2390,7 @@ async def pexpire( See https://redis.io/commands/pexpire/ for more details. Args: - key (str): The key to set a timeout on. + key (TEncodable): The key to set a timeout on. milliseconds (int): The timeout in milliseconds. option (Optional[ExpireOptions]): The expire option. @@ -2371,7 +2410,10 @@ async def pexpire( return cast(bool, await self._execute_command(RequestType.PExpire, args)) async def pexpireat( - self, key: str, unix_milliseconds: int, option: Optional[ExpireOptions] = None + self, + key: TEncodable, + unix_milliseconds: int, + option: Optional[ExpireOptions] = None, ) -> bool: """ Sets a timeout on `key` using an absolute Unix timestamp in milliseconds (milliseconds since January 1, 1970) instead @@ -2383,7 +2425,7 @@ async def pexpireat( See https://redis.io/commands/pexpireat/ for more details. Args: - key (str): The key to set a timeout on. + key (TEncodable): The key to set a timeout on. unix_milliseconds (int): The timeout in an absolute Unix timestamp in milliseconds. option (Optional[ExpireOptions]): The expire option. @@ -2402,7 +2444,7 @@ async def pexpireat( ) return cast(bool, await self._execute_command(RequestType.PExpireAt, args)) - async def expiretime(self, key: str) -> int: + async def expiretime(self, key: TEncodable) -> int: """ Returns the absolute Unix timestamp (since January 1, 1970) at which the given `key` will expire, in seconds. @@ -2411,7 +2453,7 @@ async def expiretime(self, key: str) -> int: See https://valkey.io/commands/expiretime/ for details. Args: - key (str): The `key` to determine the expiration value of. + key (TEncodable): The `key` to determine the expiration value of. Returns: int: The expiration Unix timestamp in seconds, -2 if `key` does not exist or -1 if `key` exists but has no associated expire. @@ -2430,7 +2472,7 @@ async def expiretime(self, key: str) -> int: """ return cast(int, await self._execute_command(RequestType.ExpireTime, [key])) - async def pexpiretime(self, key: str) -> int: + async def pexpiretime(self, key: TEncodable) -> int: """ Returns the absolute Unix timestamp (since January 1, 1970) at which the given `key` will expire, in milliseconds. @@ -2438,7 +2480,7 @@ async def pexpiretime(self, key: str) -> int: See https://valkey.io/commands/pexpiretime/ for details. Args: - key (str): The `key` to determine the expiration value of. + key (TEncodable): The `key` to determine the expiration value of. Returns: int: The expiration Unix timestamp in milliseconds, -2 if `key` does not exist, or -1 if `key` exists but has no associated expiration. @@ -2457,13 +2499,13 @@ async def pexpiretime(self, key: str) -> int: """ return cast(int, await self._execute_command(RequestType.PExpireTime, [key])) - async def ttl(self, key: str) -> int: + async def ttl(self, key: TEncodable) -> int: """ Returns the remaining time to live of `key` that has a timeout. See https://redis.io/commands/ttl/ for more details. Args: - key (str): The key to return its timeout. + key (TEncodable): The key to return its timeout. Returns: int: TTL in seconds, -2 if `key` does not exist or -1 if `key` exists but has no associated expire. @@ -2480,14 +2522,14 @@ async def ttl(self, key: str) -> int: async def pttl( self, - key: str, + key: TEncodable, ) -> int: """ Returns the remaining time to live of `key` that has a timeout, in milliseconds. See https://redis.io/commands/pttl for more details. Args: - key (str): The key to return its timeout. + key (TEncodable): The key to return its timeout. Returns: int: TTL in milliseconds. -2 if `key` does not exist, -1 if `key` exists but has no associated expire. @@ -2505,7 +2547,7 @@ async def pttl( async def persist( self, - key: str, + key: TEncodable, ) -> bool: """ Remove the existing timeout on `key`, turning the key from volatile (a key with an expire set) to @@ -2514,7 +2556,7 @@ async def persist( See https://redis.io/commands/persist/ for more details. Args: - key (str): TThe key to remove the existing timeout on. + key (TEncodable): The key to remove the existing timeout on. Returns: bool: False if `key` does not exist or does not have an associated timeout, True if the timeout has been removed. @@ -2528,74 +2570,76 @@ async def persist( await self._execute_command(RequestType.Persist, [key]), ) - async def type(self, key: str) -> str: + async def type(self, key: TEncodable) -> bytes: """ - Returns the string representation of the type of the value stored at `key`. + Returns the bytes string representation of the type of the value stored at `key`. See https://redis.io/commands/type/ for more details. Args: - key (str): The key to check its data type. + key (TEncodable): The key to check its data type. Returns: - str: If the key exists, the type of the stored value is returned. - Otherwise, a "none" string is returned. + bytes: If the key exists, the type of the stored value is returned. + Otherwise, a b"none" bytes string is returned. Examples: >>> await client.set("key", "value") >>> await client.type("key") - 'string' + b'string' >>> await client.lpush("key", ["value"]) >>> await client.type("key") - 'list' + b'list' """ - return cast(str, await self._execute_command(RequestType.Type, [key])) + return cast(bytes, await self._execute_command(RequestType.Type, [key])) async def xadd( self, - key: str, - values: List[Tuple[str, str]], + key: TEncodable, + values: List[Tuple[TEncodable, TEncodable]], options: Optional[StreamAddOptions] = None, - ) -> Optional[str]: + ) -> Optional[bytes]: """ Adds an entry to the specified stream stored at `key`. If the `key` doesn't exist, the stream is created. See https://valkey.io/commands/xadd for more details. Args: - key (str): The key of the stream. - values (List[Tuple[str, str]]): Field-value pairs to be added to the entry. - options (Optional[StreamAddOptions]): Additional options for adding entries to the stream. Default to None. sSee `StreamAddOptions`. + key (TEncodable): The key of the stream. + values (List[Tuple[TEncodable, TEncodable]]): Field-value pairs to be added to the entry. + options (Optional[StreamAddOptions]): Additional options for adding entries to the stream. Default to None. See `StreamAddOptions`. Returns: - str: The id of the added entry, or None if `options.make_stream` is set to False and no stream with the matching `key` exists. + bytes: The id of the added entry, or None if `options.make_stream` is set to False and no stream with the matching `key` exists. Example: >>> await client.xadd("mystream", [("field", "value"), ("field2", "value2")]) - "1615957011958-0" # Example stream entry ID. + b"1615957011958-0" # Example stream entry ID. >>> await client.xadd("non_existing_stream", [(field, "foo1"), (field2, "bar1")], StreamAddOptions(id="0-1", make_stream=False)) None # The key doesn't exist, therefore, None is returned. >>> await client.xadd("non_existing_stream", [(field, "foo1"), (field2, "bar1")], StreamAddOptions(id="0-1")) - "0-1" # Returns the stream id. + b"0-1" # Returns the stream id. """ - args = [key] + args: List[TEncodable] = [key] if options: args.extend(options.to_args()) else: args.append("*") args.extend([field for pair in values for field in pair]) - return cast(Optional[str], await self._execute_command(RequestType.XAdd, args)) + return cast( + Optional[bytes], await self._execute_command(RequestType.XAdd, args) + ) - async def xdel(self, key: str, ids: List[str]) -> int: + async def xdel(self, key: TEncodable, ids: List[TEncodable]) -> int: """ Removes the specified entries by id from a stream, and returns the number of entries deleted. See https://valkey.io/commands/xdel for more details. Args: - key (str): The key of the stream. - ids (List[str]): An array of entry ids. + key (TEncodable): The key of the stream. + ids (List[TEncodable]): An array of entry ids. Returns: int: The number of entries removed from the stream. This number may be less than the number of entries in @@ -2605,6 +2649,8 @@ async def xdel(self, key: str, ids: List[str]) -> int: >>> await client.xdel("key", ["1538561698944-0", "1538561698944-1"]) 2 # Stream marked 2 entries as deleted. """ + args: List[TEncodable] = [key] + args.extend(ids) return cast( int, await self._execute_command(RequestType.XDel, [key] + ids), @@ -2612,7 +2658,7 @@ async def xdel(self, key: str, ids: List[str]) -> int: async def xtrim( self, - key: str, + key: TEncodable, options: StreamTrimOptions, ) -> int: """ @@ -2621,7 +2667,7 @@ async def xtrim( See https://valkey.io/commands/xtrim for more details. Args: - key (str): The key of the stream. + key (TEncodable): The key of the stream. options (StreamTrimOptions): Options detailing how to trim the stream. See `StreamTrimOptions`. Returns: @@ -2638,14 +2684,14 @@ async def xtrim( return cast(int, await self._execute_command(RequestType.XTrim, args)) - async def xlen(self, key: str) -> int: + async def xlen(self, key: TEncodable) -> int: """ Returns the number of entries in the stream stored at `key`. See https://valkey.io/commands/xlen for more details. Args: - key (str): The key of the stream. + key (TEncodable): The key of the stream. Returns: int: The number of entries in the stream. If `key` does not exist, returns 0. @@ -2663,18 +2709,18 @@ async def xlen(self, key: str) -> int: async def xrange( self, - key: str, + key: TEncodable, start: StreamRangeBound, end: StreamRangeBound, count: Optional[int] = None, - ) -> Optional[Mapping[str, List[List[str]]]]: + ) -> Optional[Mapping[bytes, List[List[bytes]]]]: """ Returns stream entries matching a given range of IDs. See https://valkey.io/commands/xrange for more details. Args: - key (str): The key of the stream. + key (TEncodable): The key of the stream. start (StreamRangeBound): The starting stream ID bound for the range. - Use `IdBound` to specify a stream ID. - Use `ExclusiveIdBound` to specify an exclusive bounded stream ID. @@ -2687,7 +2733,7 @@ async def xrange( If `count` is not provided, all stream entries in the range will be returned. Returns: - Optional[Mapping[str, List[List[str]]]]: A mapping of stream IDs to stream entry data, where entry data is a + Optional[Mapping[bytes, List[List[bytes]]]]: A mapping of stream IDs to stream entry data, where entry data is a list of pairings with format `[[field, entry], [field, entry], ...]`. Returns None if the range arguments are not applicable. @@ -2696,26 +2742,26 @@ async def xrange( >>> await client.xadd("mystream", [("field2", "value2"), ("field2", "value3")], StreamAddOptions(id="0-2")) >>> await client.xrange("mystream", MinId(), MaxId()) { - "0-1": [["field1", "value1"]], - "0-2": [["field2", "value2"], ["field2", "value3"]], + b"0-1": [[b"field1", b"value1"]], + b"0-2": [[b"field2", b"value2"], [b"field2", b"value3"]], } # Indicates the stream IDs and their associated field-value pairs for all stream entries in "mystream". """ - args = [key, start.to_arg(), end.to_arg()] + args: List[TEncodable] = [key, start.to_arg(), end.to_arg()] if count is not None: args.extend(["COUNT", str(count)]) return cast( - Optional[Mapping[str, List[List[str]]]], + Optional[Mapping[bytes, List[List[bytes]]]], await self._execute_command(RequestType.XRange, args), ) async def xrevrange( self, - key: str, + key: TEncodable, end: StreamRangeBound, start: StreamRangeBound, count: Optional[int] = None, - ) -> Optional[Mapping[str, List[List[str]]]]: + ) -> Optional[Mapping[bytes, List[List[bytes]]]]: """ Returns stream entries matching a given range of IDs in reverse order. Equivalent to `XRANGE` but returns the entries in reverse order. @@ -2723,7 +2769,7 @@ async def xrevrange( See https://valkey.io/commands/xrevrange for more details. Args: - key (str): The key of the stream. + key (TEncodable): The key of the stream. end (StreamRangeBound): The ending stream ID bound for the range. - Use `IdBound` to specify a stream ID. - Use `ExclusiveIdBound` to specify an exclusive bounded stream ID. @@ -2736,7 +2782,7 @@ async def xrevrange( If `count` is not provided, all stream entries in the range will be returned. Returns: - Optional[Mapping[str, List[List[str]]]]: A mapping of stream IDs to stream entry data, where entry data is a + Optional[Mapping[bytes, List[List[bytes]]]]: A mapping of stream IDs to stream entry data, where entry data is a list of pairings with format `[[field, entry], [field, entry], ...]`. Returns None if the range arguments are not applicable. @@ -2749,20 +2795,20 @@ async def xrevrange( "0-1": [["field1", "value1"]], } # Indicates the stream IDs and their associated field-value pairs for all stream entries in "mystream". """ - args = [key, end.to_arg(), start.to_arg()] + args: List[TEncodable] = [key, end.to_arg(), start.to_arg()] if count is not None: args.extend(["COUNT", str(count)]) return cast( - Optional[Mapping[str, List[List[str]]]], + Optional[Mapping[bytes, List[List[bytes]]]], await self._execute_command(RequestType.XRevRange, args), ) async def xread( self, - keys_and_ids: Mapping[str, str], + keys_and_ids: Mapping[TEncodable, TEncodable], options: Optional[StreamReadOptions] = None, - ) -> Optional[Mapping[str, Mapping[str, List[List[str]]]]]: + ) -> Optional[Mapping[bytes, Mapping[bytes, List[List[bytes]]]]]: """ Reads entries from the given streams. @@ -2772,12 +2818,12 @@ async def xread( When in cluster mode, all keys in `keys_and_ids` must map to the same hash slot. Args: - keys_and_ids (Mapping[str, str]): A mapping of keys and entry IDs to read from. The mapping is composed of a + keys_and_ids (Mapping[TEncodable, TEncodable]): A mapping of keys and entry IDs to read from. The mapping is composed of a stream's key and the ID of the entry after which the stream will be read. options (Optional[StreamReadOptions]): Options detailing how to read the stream. Returns: - Optional[Mapping[str, Mapping[str, List[List[str]]]]]: A mapping of stream keys, to a mapping of stream IDs, + Optional[Mapping[bytes, Mapping[bytes, List[List[bytes]]]]]: A mapping of stream keys, to a mapping of stream IDs, to a list of pairings with format `[[field, entry], [field, entry], ...]`. None will be returned under the following conditions: - All key-ID pairs in `keys_and_ids` have either a non-existing key or a non-existing ID, or there are no entries after the given ID. @@ -2788,29 +2834,29 @@ async def xread( >>> await client.xadd("mystream", [("field2", "value2"), ("field2", "value3")], StreamAddOptions(id="0-2")) >>> await client.xread({"mystream": "0-0"}, StreamReadOptions(block_ms=1000)) { - "mystream": { - "0-1": [["field1", "value1"]], - "0-2": [["field2", "value2"], ["field2", "value3"]], + b"mystream": { + b"0-1": [[b"field1", b"value1"]], + b"0-2": [[b"field2", b"value2"], [b"field2", b"value3"]], } } # Indicates the stream entries for "my_stream" with IDs greater than "0-0". The operation blocks up to # 1000ms if there is no stream data. """ - args = [] if options is None else options.to_args() + args: List[TEncodable] = [] if options is None else options.to_args() args.append("STREAMS") args.extend([key for key in keys_and_ids.keys()]) args.extend([value for value in keys_and_ids.values()]) return cast( - Optional[Mapping[str, Mapping[str, List[List[str]]]]], + Optional[Mapping[bytes, Mapping[bytes, List[List[bytes]]]]], await self._execute_command(RequestType.XRead, args), ) async def xgroup_create( self, - key: str, - group_name: str, - group_id: str, + key: TEncodable, + group_name: TEncodable, + group_id: TEncodable, options: Optional[StreamGroupOptions] = None, ) -> TOK: """ @@ -2819,9 +2865,9 @@ async def xgroup_create( See https://valkey.io/commands/xgroup-create for more details. Args: - key (str): The key of the stream. - group_name (str): The newly created consumer group name. - group_id (str): The stream entry ID that specifies the last delivered entry in the stream from the new + key (TEncodable): The key of the stream. + group_name (TEncodable): The newly created consumer group name. + group_id (TEncodable): The stream entry ID that specifies the last delivered entry in the stream from the new group’s perspective. The special ID "$" can be used to specify the last entry in the stream. options (Optional[StreamGroupOptions]): Options for creating the stream group. @@ -2834,7 +2880,7 @@ async def xgroup_create( # Created the consumer group "mygroup" for the stream "mystream", which will track entries created after # the most recent entry. The stream was created with length 0 if it did not already exist. """ - args = [key, group_name, group_id] + args: List[TEncodable] = [key, group_name, group_id] if options is not None: args.extend(options.to_args()) @@ -2843,15 +2889,15 @@ async def xgroup_create( await self._execute_command(RequestType.XGroupCreate, args), ) - async def xgroup_destroy(self, key: str, group_name: str) -> bool: + async def xgroup_destroy(self, key: TEncodable, group_name: TEncodable) -> bool: """ Destroys the consumer group `group_name` for the stream stored at `key`. See https://valkey.io/commands/xgroup-destroy for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name to delete. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name to delete. Returns: bool: True if the consumer group was destroyed. Otherwise, returns False. @@ -2866,7 +2912,10 @@ async def xgroup_destroy(self, key: str, group_name: str) -> bool: ) async def xgroup_create_consumer( - self, key: str, group_name: str, consumer_name: str + self, + key: TEncodable, + group_name: TEncodable, + consumer_name: TEncodable, ) -> bool: """ Creates a consumer named `consumer_name` in the consumer group `group_name` for the stream stored at `key`. @@ -2874,9 +2923,9 @@ async def xgroup_create_consumer( See https://valkey.io/commands/xgroup-createconsumer for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. - consumer_name (str): The newly created consumer. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. + consumer_name (TEncodable): The newly created consumer. Returns: bool: True if the consumer is created. Otherwise, returns False. @@ -2893,7 +2942,10 @@ async def xgroup_create_consumer( ) async def xgroup_del_consumer( - self, key: str, group_name: str, consumer_name: str + self, + key: TEncodable, + group_name: TEncodable, + consumer_name: TEncodable, ) -> int: """ Deletes a consumer named `consumer_name` in the consumer group `group_name` for the stream stored at `key`. @@ -2901,9 +2953,9 @@ async def xgroup_del_consumer( See https://valkey.io/commands/xgroup-delconsumer for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. - consumer_name (str): The consumer to delete. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. + consumer_name (TEncodable): The consumer to delete. Returns: int: The number of pending messages the `consumer` had before it was deleted. @@ -2921,10 +2973,10 @@ async def xgroup_del_consumer( async def xgroup_set_id( self, - key: str, - group_name: str, - stream_id: str, - entries_read_id: Optional[str] = None, + key: TEncodable, + group_name: TEncodable, + stream_id: TEncodable, + entries_read_id: Optional[TEncodable] = None, ) -> TOK: """ Set the last delivered ID for a consumer group. @@ -2932,10 +2984,10 @@ async def xgroup_set_id( See https://valkey.io/commands/xgroup-setid for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. - stream_id (str): The stream entry ID that should be set as the last delivered ID for the consumer group. - entries_read_id (Optional[str]): An arbitrary ID (that isn't the first ID, last ID, or the zero ID ("0-0")) + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. + stream_id (TEncodable): The stream entry ID that should be set as the last delivered ID for the consumer group. + entries_read_id (Optional[TEncodable]): An arbitrary ID (that isn't the first ID, last ID, or the zero ID ("0-0")) used to find out how many entries are between the arbitrary ID (excluding it) and the stream's last entry. This argument can only be specified if you are using Redis version 7.0.0 or above. @@ -2946,7 +2998,7 @@ async def xgroup_set_id( >>> await client.xgroup_set_id("mystream", "mygroup", "0") OK # The last delivered ID for consumer group "mygroup" was set to 0. """ - args = [key, group_name, stream_id] + args: List[TEncodable] = [key, group_name, stream_id] if entries_read_id is not None: args.extend(["ENTRIESREAD", entries_read_id]) @@ -2957,11 +3009,11 @@ async def xgroup_set_id( async def xreadgroup( self, - keys_and_ids: Mapping[str, str], - group_name: str, - consumer_name: str, + keys_and_ids: Mapping[TEncodable, TEncodable], + group_name: TEncodable, + consumer_name: TEncodable, options: Optional[StreamReadGroupOptions] = None, - ) -> Optional[Mapping[str, Mapping[str, Optional[List[List[str]]]]]]: + ) -> Optional[Mapping[bytes, Mapping[bytes, Optional[List[List[bytes]]]]]]: """ Reads entries from the given streams owned by a consumer group. @@ -2971,15 +3023,15 @@ async def xreadgroup( When in cluster mode, all keys in `keys_and_ids` must map to the same hash slot. Args: - keys_and_ids (Mapping[str, str]): A mapping of stream keys to stream entry IDs to read from. The special ">" + keys_and_ids (Mapping[TEncodable, TEncodable]): A mapping of stream keys to stream entry IDs to read from. The special ">" ID returns messages that were never delivered to any other consumer. Any other valid ID will return entries pending for the consumer with IDs greater than the one provided. - group_name (str): The consumer group name. - consumer_name (str): The consumer name. The consumer will be auto-created if it does not already exist. + group_name (TEncodable): The consumer group name. + consumer_name (TEncodable): The consumer name. The consumer will be auto-created if it does not already exist. options (Optional[StreamReadGroupOptions]): Options detailing how to read the stream. Returns: - Optional[Mapping[str, Mapping[str, Optional[List[List[str]]]]]]: A mapping of stream keys, to a mapping of + Optional[Mapping[bytes, Mapping[bytes, Optional[List[List[bytes]]]]]]: A mapping of stream keys, to a mapping of stream IDs, to a list of pairings with format `[[field, entry], [field, entry], ...]`. Returns None if the BLOCK option is given and a timeout occurs, or if there is no stream that can be served. @@ -2988,12 +3040,12 @@ async def xreadgroup( >>> await client.xgroup_create("mystream", "mygroup", "0-0") >>> await client.xreadgroup({"mystream": ">"}, "mygroup", "myconsumer", StreamReadGroupOptions(count=1)) { - "mystream": { - "1-0": [["field1", "value1"]], + b"mystream": { + b"1-0": [[b"field1", b"value1"]], } } # Read one stream entry from "mystream" using "myconsumer" in the consumer group "mygroup". """ - args = ["GROUP", group_name, consumer_name] + args: List[TEncodable] = ["GROUP", group_name, consumer_name] if options is not None: args.extend(options.to_args()) @@ -3002,15 +3054,15 @@ async def xreadgroup( args.extend([value for value in keys_and_ids.values()]) return cast( - Optional[Mapping[str, Mapping[str, Optional[List[List[str]]]]]], + Optional[Mapping[bytes, Mapping[bytes, Optional[List[List[bytes]]]]]], await self._execute_command(RequestType.XReadGroup, args), ) async def xack( self, - key: str, - group_name: str, - ids: List[str], + key: TEncodable, + group_name: TEncodable, + ids: List[TEncodable], ) -> int: """ Removes one or multiple messages from the Pending Entries List (PEL) of a stream consumer group. @@ -3020,9 +3072,9 @@ async def xack( See https://valkey.io/commands/xack for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. - ids (List[str]): The stream entry IDs to acknowledge and consume for the given consumer group. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. + ids (List[TEncodable]): The stream entry IDs to acknowledge and consume for the given consumer group. Returns: int: The number of messages that were successfully acknowledged. @@ -3039,7 +3091,8 @@ async def xack( >>> await client.xack("mystream", "mygroup", ["1-0"]) 1 # 1 pending message was acknowledged and removed from the Pending Entries List for "mygroup". """ - + args: List[TEncodable] = [key, group_name] + args.extend(ids) return cast( int, await self._execute_command(RequestType.XAck, [key, group_name] + ids), @@ -3047,20 +3100,20 @@ async def xack( async def xpending( self, - key: str, - group_name: str, - ) -> List[Union[int, str, List[List[str]], None]]: + key: TEncodable, + group_name: TEncodable, + ) -> List[Union[int, bytes, List[List[bytes]], None]]: """ Returns stream message summary information for pending messages for the given consumer group. See https://valkey.io/commands/xpending for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. Returns: - List[Union[int, str, List[List[str]], None]]: A list that includes the summary of pending messages, with the + List[Union[int, bytes, List[List[bytes]], None]]: A list that includes the summary of pending messages, with the format `[num_group_messages, start_id, end_id, [[consumer_name, num_consumer_messages]]]`, where: - `num_group_messages`: The total number of pending messages for this consumer group. - `start_id`: The smallest ID among the pending messages. @@ -3075,27 +3128,27 @@ async def xpending( [4, "1-0", "1-3", [["my_consumer1", "3"], ["my_consumer2", "1"]] """ return cast( - List[Union[int, str, List[List[str]], None]], + List[Union[int, bytes, List[List[bytes]], None]], await self._execute_command(RequestType.XPending, [key, group_name]), ) async def xpending_range( self, - key: str, - group_name: str, + key: TEncodable, + group_name: TEncodable, start: StreamRangeBound, end: StreamRangeBound, count: int, options: Optional[StreamPendingOptions] = None, - ) -> List[List[Union[str, int]]]: + ) -> List[List[Union[bytes, int]]]: """ Returns an extended form of stream message information for pending messages matching a given range of IDs. See https://valkey.io/commands/xpending for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. start (StreamRangeBound): The starting stream ID bound for the range. - Use `IdBound` to specify a stream ID. - Use `ExclusiveIdBound` to specify an exclusive bounded stream ID. @@ -3108,7 +3161,7 @@ async def xpending_range( options (Optional[StreamPendingOptions]): The stream pending options. Returns: - List[List[Union[str, int]]]: A list of lists, where each inner list is a length 4 list containing extended + List[List[Union[bytes, int]]]: A list of lists, where each inner list is a length 4 list containing extended message information with the format `[[id, consumer_name, time_elapsed, num_delivered]]`, where: - `id`: The ID of the message. - `consumer_name`: The name of the consumer that fetched the message and has still to acknowledge it. We @@ -3119,40 +3172,40 @@ async def xpending_range( Examples: >>> await client.xpending_range("my_stream", "my_group", MinId(), MaxId(), 10, StreamPendingOptions(consumer_name="my_consumer")) - [["1-0", "my_consumer", 1234, 1], ["1-1", "my_consumer", 1123, 1]] + [[b"1-0", b"my_consumer", 1234, 1], [b"1-1", b"my_consumer", 1123, 1]] # Extended stream entry information for the pending entries associated with "my_consumer". """ args = _create_xpending_range_args(key, group_name, start, end, count, options) return cast( - List[List[Union[str, int]]], + List[List[Union[bytes, int]]], await self._execute_command(RequestType.XPending, args), ) async def xautoclaim( self, - key: str, - group_name: str, - consumer_name: str, + key: TEncodable, + group_name: TEncodable, + consumer_name: TEncodable, min_idle_time_ms: int, - start: str, + start: TEncodable, count: Optional[int] = None, - ) -> List[Union[str, Mapping[str, List[List[str]]], List[str]]]: + ) -> List[Union[bytes, Mapping[bytes, List[List[bytes]]], List[bytes]]]: """ Transfers ownership of pending stream entries that match the specified criteria. See https://valkey.io/commands/xautoclaim for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. - consumer_name (str): The consumer name. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. + consumer_name (TEncodable): The consumer name. min_idle_time_ms (int): Filters the claimed entries to those that have been idle for more than the specified value. - start (str): Filters the claimed entries to those that have an ID equal or greater than the specified value. + start (TEncodable): Filters the claimed entries to those that have an ID equal or greater than the specified value. count (Optional[int]): Limits the number of claimed entries to the specified value. Returns: - List[Union[str, Mapping[str, List[List[str]]], List[str]]]: A list containing the following elements: + List[Union[bytes, Mapping[bytes, List[List[bytes]]], List[bytes]]]: A list containing the following elements: - A stream ID to be used as the start argument for the next call to `XAUTOCLAIM`. This ID is equivalent to the next ID in the stream after the entries that were scanned, or "0-0" if the entire stream was scanned. @@ -3166,11 +3219,11 @@ async def xautoclaim( # Redis version < 7.0.0: >>> await client.xautoclaim("my_stream", "my_group", "my_consumer", 3_600_000, "0-0") [ - "0-0", + b"0-0", { - "1-1": [ - ["field1", "value1"], - ["field2", "value2"], + b"1-1": [ + [b"field1", b"value1"], + [b"field2", b"value2"], ] } ] @@ -3180,14 +3233,14 @@ async def xautoclaim( # Redis version 7.0.0 and above: >>> await client.xautoclaim("my_stream", "my_group", "my_consumer", 3_600_000, "0-0") [ - "0-0", + b"0-0", { - "1-1": [ - ["field1", "value1"], - ["field2", "value2"], + b"1-1": [ + [b"field1", b"value1"], + [b"field2", b"value2"], ] }, - ["1-2"] + [b"1-2"] ] # Stream entry "1-1" was idle for over an hour and was thus claimed by "my_consumer". The entire stream # was scanned. Additionally, entry "1-2" was removed from the Pending Entries List because it no longer @@ -3195,24 +3248,30 @@ async def xautoclaim( Since: Redis version 6.2.0. """ - args = [key, group_name, consumer_name, str(min_idle_time_ms), start] + args: List[TEncodable] = [ + key, + group_name, + consumer_name, + str(min_idle_time_ms), + start, + ] if count is not None: args.extend(["COUNT", str(count)]) return cast( - List[Union[str, Mapping[str, List[List[str]]], List[str]]], + List[Union[bytes, Mapping[bytes, List[List[bytes]]], List[bytes]]], await self._execute_command(RequestType.XAutoClaim, args), ) async def xautoclaim_just_id( self, - key: str, - group_name: str, - consumer_name: str, + key: TEncodable, + group_name: TEncodable, + consumer_name: TEncodable, min_idle_time_ms: int, - start: str, + start: TEncodable, count: Optional[int] = None, - ) -> List[Union[str, List[str]]]: + ) -> List[Union[bytes, List[bytes]]]: """ Transfers ownership of pending stream entries that match the specified criteria. This command uses the JUSTID argument to further specify that the return value should contain a list of claimed IDs without their @@ -3221,16 +3280,16 @@ async def xautoclaim_just_id( See https://valkey.io/commands/xautoclaim for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. - consumer_name (str): The consumer name. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. + consumer_name (TEncodable): The consumer name. min_idle_time_ms (int): Filters the claimed entries to those that have been idle for more than the specified value. - start (str): Filters the claimed entries to those that have an ID equal or greater than the specified value. + start (TEncodable): Filters the claimed entries to those that have an ID equal or greater than the specified value. count (Optional[int]): Limits the number of claimed entries to the specified value. Returns: - List[Union[str, List[str]]]: A list containing the following elements: + List[Union[bytes, List[bytes]]]: A list containing the following elements: - A stream ID to be used as the start argument for the next call to `XAUTOCLAIM`. This ID is equivalent to the next ID in the stream after the entries that were scanned, or "0-0" if the entire stream was scanned. @@ -3242,34 +3301,40 @@ async def xautoclaim_just_id( Examples: # Redis version < 7.0.0: >>> await client.xautoclaim_just_id("my_stream", "my_group", "my_consumer", 3_600_000, "0-0") - ["0-0", ["1-1"]] + [b"0-0", [b"1-1"]] # Stream entry "1-1" was idle for over an hour and was thus claimed by "my_consumer". The entire stream # was scanned. # Redis version 7.0.0 and above: >>> await client.xautoclaim_just_id("my_stream", "my_group", "my_consumer", 3_600_000, "0-0") - ["0-0", ["1-1"], ["1-2"]] + [b"0-0", [b"1-1"], [b"1-2"]] # Stream entry "1-1" was idle for over an hour and was thus claimed by "my_consumer". The entire stream # was scanned. Additionally, entry "1-2" was removed from the Pending Entries List because it no longer # exists in the stream. Since: Redis version 6.2.0. """ - args = [key, group_name, consumer_name, str(min_idle_time_ms), start] + args: List[TEncodable] = [ + key, + group_name, + consumer_name, + str(min_idle_time_ms), + start, + ] if count is not None: args.extend(["COUNT", str(count)]) args.append("JUSTID") return cast( - List[Union[str, List[str]]], + List[Union[bytes, List[bytes]]], await self._execute_command(RequestType.XAutoClaim, args), ) async def geoadd( self, - key: str, - members_geospatialdata: Mapping[str, GeospatialData], + key: TEncodable, + members_geospatialdata: Mapping[TEncodable, GeospatialData], existing_options: Optional[ConditionalChange] = None, changed: bool = False, ) -> int: @@ -3280,8 +3345,8 @@ async def geoadd( See https://valkey.io/commands/geoadd for more details. Args: - key (str): The key of the sorted set. - members_geospatialdata (Mapping[str, GeospatialData]): A mapping of member names to their corresponding positions. See `GeospatialData`. + key (TEncodable): The key of the sorted set. + members_geospatialdata (Mapping[TEncodable, GeospatialData]): A mapping of member names to their corresponding positions. See `GeospatialData`. The command will report an error when the user attempts to index coordinates outside the specified ranges. existing_options (Optional[ConditionalChange]): Options for handling existing members. - NX: Only add new elements. @@ -3319,9 +3384,9 @@ async def geoadd( async def geodist( self, - key: str, - member1: str, - member2: str, + key: TEncodable, + member1: TEncodable, + member2: TEncodable, unit: Optional[GeoUnit] = None, ) -> Optional[float]: """ @@ -3330,9 +3395,9 @@ async def geodist( See https://valkey.io/commands/geodist for more details. Args: - key (str): The key of the sorted set. - member1 (str): The name of the first member. - member2 (str): The name of the second member. + key (TEncodable): The key of the sorted set. + member1 (TEncodable): The name of the first member. + member2 (TEncodable): The name of the second member. unit (Optional[GeoUnit]): The unit of distance measurement. See `GeoUnit`. If not specified, the default unit is `METERS`. @@ -3358,35 +3423,37 @@ async def geodist( await self._execute_command(RequestType.GeoDist, args), ) - async def geohash(self, key: str, members: List[str]) -> List[Optional[str]]: + async def geohash( + self, key: TEncodable, members: List[TEncodable] + ) -> List[Optional[bytes]]: """ - Returns the GeoHash strings representing the positions of all the specified members in the sorted set stored at + Returns the GeoHash bytes strings representing the positions of all the specified members in the sorted set stored at `key`. See https://valkey.io/commands/geohash for more details. Args: - key (str): The key of the sorted set. - members (List[str]): The list of members whose GeoHash strings are to be retrieved. + key (TEncodable): The key of the sorted set. + members (List[TEncodable]): The list of members whose GeoHash bytes strings are to be retrieved. Returns: - List[Optional[str]]: A list of GeoHash strings representing the positions of the specified members stored at `key`. + List[Optional[bytes]]: A list of GeoHash bytes strings representing the positions of the specified members stored at `key`. If a member does not exist in the sorted set, a None value is returned for that member. Examples: >>> await client.geoadd("my_geo_sorted_set", {"Palermo": GeospatialData(13.361389, 38.115556), "Catania": GeospatialData(15.087269, 37.502669)}) >>> await client.geohash("my_geo_sorted_set", ["Palermo", "Catania", "some city]) - ["sqc8b49rny0", "sqdtr74hyu0", None] # Indicates the GeoHash strings for the specified members. + ["sqc8b49rny0", "sqdtr74hyu0", None] # Indicates the GeoHash bytes strings for the specified members. """ return cast( - List[Optional[str]], + List[Optional[bytes]], await self._execute_command(RequestType.GeoHash, [key] + members), ) async def geopos( self, - key: str, - members: List[str], + key: TEncodable, + members: List[TEncodable], ) -> List[Optional[List[float]]]: """ Returns the positions (longitude and latitude) of all the given members of a geospatial index in the sorted set stored at @@ -3395,8 +3462,8 @@ async def geopos( See https://valkey.io/commands/geopos for more details. Args: - key (str): The key of the sorted set. - members (List[str]): The members for which to get the positions. + key (TEncodable): The key of the sorted set. + members (List[TEncodable]): The members for which to get the positions. Returns: List[Optional[List[float]]]: A list of positions (longitude and latitude) corresponding to the given members. @@ -3414,23 +3481,23 @@ async def geopos( async def geosearch( self, - key: str, - search_from: Union[str, GeospatialData], - seach_by: Union[GeoSearchByRadius, GeoSearchByBox], + key: TEncodable, + search_from: Union[str, bytes, GeospatialData], + search_by: Union[GeoSearchByRadius, GeoSearchByBox], order_by: Optional[OrderBy] = None, count: Optional[GeoSearchCount] = None, with_coord: bool = False, with_dist: bool = False, with_hash: bool = False, - ) -> List[Union[str, List[Union[str, float, int, List[float]]]]]: + ) -> List[Union[bytes, List[Union[bytes, float, int, List[float]]]]]: """ Searches for members in a sorted set stored at `key` representing geospatial data within a circular or rectangular area. See https://valkey.io/commands/geosearch/ for more details. Args: - key (str): The key of the sorted set representing geospatial data. - search_from (Union[str, GeospatialData]): The location to search from. Can be specified either as a member + key (TEncodable): The key of the sorted set representing geospatial data. + search_from (Union[str, bytes, GeospatialData]): The location to search from. Can be specified either as a member from the sorted set or as a geospatial data (see `GeospatialData`). search_by (Union[GeoSearchByRadius, GeoSearchByBox]): The search criteria. For circular area search, see `GeoSearchByRadius`. @@ -3447,9 +3514,9 @@ async def geosearch( with_hash (bool): Whether to include geohash of the returned items. Defaults to False. Returns: - List[Union[str, List[Union[str, float, int, List[float]]]]]: By default, returns a list of members (locations) names. + List[Union[bytes, List[Union[bytes, float, int, List[float]]]]]: By default, returns a list of members (locations) names. If any of `with_coord`, `with_dist` or `with_hash` are True, returns an array of arrays, we're each sub array represents a single item in the following order: - (str): The member (location) name. + (bytes): The member (location) name. (float): The distance from the center as a floating point number, in the same unit specified in the radius, if `with_dist` is set to True. (int): The Geohash integer, if `with_hash` is set to True. List[float]: The coordinates as a two item [longitude,latitude] array, if `with_coord` is set to True. @@ -3462,19 +3529,19 @@ async def geosearch( >>> await client.geosearch("my_geo_sorted_set", GeospatialData(15, 37), GeoSearchByBox(400, 400, GeoUnit.KILOMETERS), OrderBy.DESC, with_coord=true, with_dist=true, with_hash=true) [ [ - "Catania", + b"Catania", [56.4413, 3479447370796909, [15.087267458438873, 37.50266842333162]], ], [ - "Palermo", + b"Palermo", [190.4424, 3479099956230698, [13.361389338970184, 38.1155563954963]], ], [ - "edge2", + b"edge2", [279.7403, 3481342659049484, [17.241510450839996, 38.78813451624225]], ], [ - "edge1", + b"edge1", [279.7405, 3479273021651468, [12.75848776102066, 38.78813451624225]], ], ] # Returns locations within the square box of 400 km, with the center being a specific point, from nearest to farthest with the dist, hash and coords. @@ -3484,7 +3551,7 @@ async def geosearch( args = _create_geosearch_args( [key], search_from, - seach_by, + search_by, order_by, count, with_coord, @@ -3493,15 +3560,15 @@ async def geosearch( ) return cast( - List[Union[str, List[Union[str, float, int, List[float]]]]], + List[Union[bytes, List[Union[bytes, float, int, List[float]]]]], await self._execute_command(RequestType.GeoSearch, args), ) async def geosearchstore( self, - destination: str, - source: str, - search_from: Union[str, GeospatialData], + destination: TEncodable, + source: TEncodable, + search_from: Union[str, bytes, GeospatialData], search_by: Union[GeoSearchByRadius, GeoSearchByBox], count: Optional[GeoSearchCount] = None, store_dist: bool = False, @@ -3515,20 +3582,20 @@ async def geosearchstore( Note: When in cluster mode, both `source` and `destination` must map to the same hash slot. - Args: - destination (str): The key to store the search results. - source (str): The key of the sorted set representing geospatial data to search from. - search_from (Union[str, GeospatialData]): The location to search from. Can be specified either as a member - from the sorted set or as a geospatial data (see `GeospatialData`). - search_by (Union[GeoSearchByRadius, GeoSearchByBox]): The search criteria. - For circular area search, see `GeoSearchByRadius`. - For rectangular area search, see `GeoSearchByBox`. - count (Optional[GeoSearchCount]): Specifies the maximum number of results to store. See `GeoSearchCount`. - If not specified, stores all results. - store_dist (bool): Determines what is stored as the sorted set score. Defaults to False. - - If set to False, the geohash of the location will be stored as the sorted set score. - - If set to True, the distance from the center of the shape (circle or box) will be stored as the sorted set score. - The distance is represented as a floating-point number in the same unit specified for that shape. + Args: + destination (TEncodable): The key to store the search results. + source (TEncodable): The key of the sorted set representing geospatial data to search from. + search_from (Union[str, bytes, GeospatialData]): The location to search from. Can be specified either as a member + from the sorted set or as a geospatial data (see `GeospatialData`). + search_by (Union[GeoSearchByRadius, GeoSearchByBox]): The search criteria. + For circular area search, see `GeoSearchByRadius`. + For rectangular area search, see `GeoSearchByBox`. + count (Optional[GeoSearchCount]): Specifies the maximum number of results to store. See `GeoSearchCount`. + If not specified, stores all results. + store_dist (bool): Determines what is stored as the sorted set score. Defaults to False. + - If set to False, the geohash of the location will be stored as the sorted set score. + - If set to True, the distance from the center of the shape (circle or box) will be stored as the sorted set score. + The distance is represented as a floating-point number in the same unit specified for that shape. Returns: int: The number of elements in the resulting sorted set stored at `destination`. @@ -3538,11 +3605,11 @@ async def geosearchstore( >>> await client.geosearchstore("my_dest_sorted_set", "my_geo_sorted_set", "Catania", GeoSearchByRadius(175, GeoUnit.MILES)) 2 # Number of elements stored in "my_dest_sorted_set". >>> await client.zrange_withscores("my_dest_sorted_set", RangeByIndex(0, -1)) - {"Palermo": 3479099956230698.0, "Catania": 3479447370796909.0} # The elements within te search area, with their geohash as score. + {b"Palermo": 3479099956230698.0, b"Catania": 3479447370796909.0} # The elements within te search area, with their geohash as score. >>> await client.geosearchstore("my_dest_sorted_set", "my_geo_sorted_set", GeospatialData(15, 37), GeoSearchByBox(400, 400, GeoUnit.KILOMETERS), store_dist=True) 2 # Number of elements stored in "my_dest_sorted_set", with distance as score. >>> await client.zrange_withscores("my_dest_sorted_set", RangeByIndex(0, -1)) - {"Catania": 56.4412578701582, "Palermo": 190.44242984775784} # The elements within te search area, with the distance as score. + {b"Catania": 56.4412578701582, b"Palermo": 190.44242984775784} # The elements within te search area, with the distance as score. Since: Redis version 6.2.0. """ @@ -3565,8 +3632,8 @@ async def geosearchstore( async def zadd( self, - key: str, - members_scores: Mapping[str, float], + key: TEncodable, + members_scores: Mapping[TEncodable, float], existing_options: Optional[ConditionalChange] = None, update_condition: Optional[UpdateOptions] = None, changed: bool = False, @@ -3578,8 +3645,8 @@ async def zadd( See https://redis.io/commands/zadd/ for more details. Args: - key (str): The key of the sorted set. - members_scores (Mapping[str, float]): A mapping of members to their corresponding scores. + key (TEncodable): The key of the sorted set. + members_scores (Mapping[TEncodable, float]): A mapping of members to their corresponding scores. existing_options (Optional[ConditionalChange]): Options for handling existing members. - NX: Only add new elements. - XX: Only update existing elements. @@ -3627,8 +3694,8 @@ async def zadd( async def zadd_incr( self, - key: str, - member: str, + key: TEncodable, + member: TEncodable, increment: float, existing_options: Optional[ConditionalChange] = None, update_condition: Optional[UpdateOptions] = None, @@ -3641,8 +3708,8 @@ async def zadd_incr( See https://redis.io/commands/zadd/ for more details. Args: - key (str): The key of the sorted set. - member (str): A member in the sorted set to increment. + key (TEncodable): The key of the sorted set. + member (TEncodable): A member in the sorted set to increment. increment (float): The score to increment the member. existing_options (Optional[ConditionalChange]): Options for handling the member's existence. - NX: Only increment a member that doesn't exist. @@ -3683,14 +3750,14 @@ async def zadd_incr( await self._execute_command(RequestType.ZAdd, args), ) - async def zcard(self, key: str) -> int: + async def zcard(self, key: TEncodable) -> int: """ Returns the cardinality (number of elements) of the sorted set stored at `key`. See https://redis.io/commands/zcard/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. Returns: int: The number of elements in the sorted set. @@ -3706,7 +3773,7 @@ async def zcard(self, key: str) -> int: async def zcount( self, - key: str, + key: TEncodable, min_score: Union[InfBound, ScoreBoundary], max_score: Union[InfBound, ScoreBoundary], ) -> int: @@ -3716,7 +3783,7 @@ async def zcount( See https://redis.io/commands/zcount/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. min_score (Union[InfBound, ScoreBoundary]): The minimum score to count from. Can be an instance of InfBound representing positive/negative infinity, or ScoreBoundary representing a specific score and inclusivity. @@ -3752,7 +3819,9 @@ async def zcount( ), ) - async def zincrby(self, key: str, increment: float, member: str) -> float: + async def zincrby( + self, key: TEncodable, increment: float, member: TEncodable + ) -> float: """ Increments the score of `member` in the sorted set stored at `key` by `increment`. If `member` does not exist in the sorted set, it is added with `increment` as its score. @@ -3761,9 +3830,9 @@ async def zincrby(self, key: str, increment: float, member: str) -> float: See https://valkey.io/commands/zincrby/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. increment (float): The score increment. - member (str): A member of the sorted set. + member (TEncodable): A member of the sorted set. Returns: float: The new score of `member`. @@ -3785,8 +3854,8 @@ async def zincrby(self, key: str, increment: float, member: str) -> float: ) async def zpopmax( - self, key: str, count: Optional[int] = None - ) -> Mapping[str, float]: + self, key: TEncodable, count: Optional[int] = None + ) -> Mapping[bytes, float]: """ Removes and returns the members with the highest scores from the sorted set stored at `key`. If `count` is provided, up to `count` members with the highest scores are removed and returned. @@ -3795,30 +3864,30 @@ async def zpopmax( See https://redis.io/commands/zpopmax for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. count (Optional[int]): Specifies the quantity of members to pop. If not specified, pops one member. If `count` is higher than the sorted set's cardinality, returns all members and their scores, ordered from highest to lowest. Returns: - Mapping[str, float]: A map of the removed members and their scores, ordered from the one with the highest score to the one with the lowest. + Mapping[bytes, float]: A map of the removed members and their scores, ordered from the one with the highest score to the one with the lowest. If `key` doesn't exist, it will be treated as an empy sorted set and the command returns an empty map. Examples: >>> await client.zpopmax("my_sorted_set") - {'member1': 10.0} # Indicates that 'member1' with a score of 10.0 has been removed from the sorted set. + {b'member1': 10.0} # Indicates that 'member1' with a score of 10.0 has been removed from the sorted set. >>> await client.zpopmax("my_sorted_set", 2) - {'member2': 8.0, 'member3': 7.5} # Indicates that 'member2' with a score of 8.0 and 'member3' with a score of 7.5 have been removed from the sorted set. + {b'member2': 8.0, b'member3': 7.5} # Indicates that 'member2' with a score of 8.0 and 'member3' with a score of 7.5 have been removed from the sorted set. """ return cast( - Mapping[str, float], + Mapping[bytes, float], await self._execute_command( RequestType.ZPopMax, [key, str(count)] if count else [key] ), ) async def bzpopmax( - self, keys: List[str], timeout: float - ) -> Optional[List[Union[str, float]]]: + self, keys: List[TEncodable], timeout: float + ) -> Optional[List[Union[bytes, float]]]: """ Pops the member with the highest score from the first non-empty sorted set, with the given keys being checked in the order that they are given. Blocks the connection when there are no members to remove from any of the given @@ -3833,28 +3902,28 @@ async def bzpopmax( See https://valkey.io/commands/bzpopmax for more details. Args: - keys (List[str]): The keys of the sorted sets. + keys (List[TEncodable]): The keys of the sorted sets. timeout (float): The number of seconds to wait for a blocking operation to complete. A value of 0 will block indefinitely. Returns: - Optional[List[Union[str, float]]]: An array containing the key where the member was popped out, the member itself, + Optional[List[Union[bytes, float]]]: An array containing the key where the member was popped out, the member itself, and the member score. If no member could be popped and the `timeout` expired, returns None. Examples: >>> await client.zadd("my_sorted_set1", {"member1": 10.0, "member2": 5.0}) 2 # Two elements have been added to the sorted set at "my_sorted_set1". >>> await client.bzpopmax(["my_sorted_set1", "my_sorted_set2"], 0.5) - ['my_sorted_set1', 'member1', 10.0] # "member1" with a score of 10.0 has been removed from "my_sorted_set1". + [b'my_sorted_set1', b'member1', 10.0] # "member1" with a score of 10.0 has been removed from "my_sorted_set1". """ return cast( - Optional[List[Union[str, float]]], + Optional[List[Union[bytes, float]]], await self._execute_command(RequestType.BZPopMax, keys + [str(timeout)]), ) async def zpopmin( - self, key: str, count: Optional[int] = None - ) -> Mapping[str, float]: + self, key: TEncodable, count: Optional[int] = None + ) -> Mapping[bytes, float]: """ Removes and returns the members with the lowest scores from the sorted set stored at `key`. If `count` is provided, up to `count` members with the lowest scores are removed and returned. @@ -3863,30 +3932,29 @@ async def zpopmin( See https://redis.io/commands/zpopmin for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. count (Optional[int]): Specifies the quantity of members to pop. If not specified, pops one member. If `count` is higher than the sorted set's cardinality, returns all members and their scores. Returns: - Mapping[str, float]: A map of the removed members and their scores, ordered from the one with the lowest score to the one with the highest. + Mapping[bytes, float]: A map of the removed members and their scores, ordered from the one with the lowest score to the one with the highest. If `key` doesn't exist, it will be treated as an empy sorted set and the command returns an empty map. Examples: >>> await client.zpopmin("my_sorted_set") - {'member1': 5.0} # Indicates that 'member1' with a score of 5.0 has been removed from the sorted set. + {b'member1': 5.0} # Indicates that 'member1' with a score of 5.0 has been removed from the sorted set. >>> await client.zpopmin("my_sorted_set", 2) - {'member3': 7.5 , 'member2': 8.0} # Indicates that 'member3' with a score of 7.5 and 'member2' with a score of 8.0 have been removed from the sorted set. + {b'member3': 7.5 , b'member2': 8.0} # Indicates that 'member3' with a score of 7.5 and 'member2' with a score of 8.0 have been removed from the sorted set. """ + args: List[TEncodable] = [key, str(count)] if count else [key] return cast( - Mapping[str, float], - await self._execute_command( - RequestType.ZPopMin, [key, str(count)] if count else [key] - ), + Mapping[bytes, float], + await self._execute_command(RequestType.ZPopMin, args), ) async def bzpopmin( - self, keys: List[str], timeout: float - ) -> Optional[List[Union[str, float]]]: + self, keys: List[TEncodable], timeout: float + ) -> Optional[List[Union[bytes, float]]]: """ Pops the member with the lowest score from the first non-empty sorted set, with the given keys being checked in the order that they are given. Blocks the connection when there are no members to remove from any of the given @@ -3901,31 +3969,32 @@ async def bzpopmin( See https://valkey.io/commands/bzpopmin for more details. Args: - keys (List[str]): The keys of the sorted sets. + keys (List[TEncodable]): The keys of the sorted sets. timeout (float): The number of seconds to wait for a blocking operation to complete. A value of 0 will block indefinitely. Returns: - Optional[List[Union[str, float]]]: An array containing the key where the member was popped out, the member itself, + Optional[List[Union[bytes, float]]]: An array containing the key where the member was popped out, the member itself, and the member score. If no member could be popped and the `timeout` expired, returns None. Examples: >>> await client.zadd("my_sorted_set1", {"member1": 10.0, "member2": 5.0}) 2 # Two elements have been added to the sorted set at "my_sorted_set1". >>> await client.bzpopmin(["my_sorted_set1", "my_sorted_set2"], 0.5) - ['my_sorted_set1', 'member2', 5.0] # "member2" with a score of 5.0 has been removed from "my_sorted_set1". + [b'my_sorted_set1', b'member2', 5.0] # "member2" with a score of 5.0 has been removed from "my_sorted_set1". """ + args: List[TEncodable] = keys + [str(timeout)] return cast( - Optional[List[Union[str, float]]], - await self._execute_command(RequestType.BZPopMin, keys + [str(timeout)]), + Optional[List[Union[bytes, float]]], + await self._execute_command(RequestType.BZPopMin, args), ) async def zrange( self, - key: str, + key: TEncodable, range_query: Union[RangeByIndex, RangeByLex, RangeByScore], reverse: bool = False, - ) -> List[str]: + ) -> List[bytes]: """ Returns the specified range of elements in the sorted set stored at `key`. @@ -3936,7 +4005,7 @@ async def zrange( To get the elements with their scores, see zrange_withscores. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. range_query (Union[RangeByIndex, RangeByLex, RangeByScore]): The range query object representing the type of range query to perform. - For range queries by index (rank), use RangeByIndex. - For range queries by lexicographical order, use RangeByLex. @@ -3944,25 +4013,25 @@ async def zrange( reverse (bool): If True, reverses the sorted set, with index 0 as the element with the highest score. Returns: - List[str]: A list of elements within the specified range. + List[bytes]: A list of elements within the specified range. If `key` does not exist, it is treated as an empty sorted set, and the command returns an empty array. Examples: >>> await client.zrange("my_sorted_set", RangeByIndex(0, -1)) - ['member1', 'member2', 'member3'] # Returns all members in ascending order. + [b'member1', b'member2', b'member3'] # Returns all members in ascending order. >>> await client.zrange("my_sorted_set", RangeByScore(start=InfBound.NEG_INF, stop=ScoreBoundary(3))) - ['member2', 'member3'] # Returns members with scores within the range of negative infinity to 3, in ascending order. + [b'member2', b'member3'] # Returns members with scores within the range of negative infinity to 3, in ascending order. """ args = _create_zrange_args(key, range_query, reverse, with_scores=False) - return cast(List[str], await self._execute_command(RequestType.ZRange, args)) + return cast(List[bytes], await self._execute_command(RequestType.ZRange, args)) async def zrange_withscores( self, - key: str, + key: TEncodable, range_query: Union[RangeByIndex, RangeByScore], reverse: bool = False, - ) -> Mapping[str, float]: + ) -> Mapping[bytes, float]: """ Returns the specified range of elements with their scores in the sorted set stored at `key`. Similar to ZRANGE but with a WITHSCORE flag. @@ -3970,32 +4039,32 @@ async def zrange_withscores( See https://redis.io/commands/zrange/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. range_query (Union[RangeByIndex, RangeByScore]): The range query object representing the type of range query to perform. - For range queries by index (rank), use RangeByIndex. - For range queries by score, use RangeByScore. reverse (bool): If True, reverses the sorted set, with index 0 as the element with the highest score. Returns: - Mapping[str , float]: A map of elements and their scores within the specified range. + Mapping[bytes , float]: A map of elements and their scores within the specified range. If `key` does not exist, it is treated as an empty sorted set, and the command returns an empty map. Examples: >>> await client.zrange_withscores("my_sorted_set", RangeByScore(ScoreBoundary(10), ScoreBoundary(20))) - {'member1': 10.5, 'member2': 15.2} # Returns members with scores between 10 and 20 with their scores. + {b'member1': 10.5, b'member2': 15.2} # Returns members with scores between 10 and 20 with their scores. >>> await client.zrange_withscores("my_sorted_set", RangeByScore(start=InfBound.NEG_INF, stop=ScoreBoundary(3))) - {'member4': -2.0, 'member7': 1.5} # Returns members with with scores within the range of negative infinity to 3, with their scores. + {b'member4': -2.0, b'member7': 1.5} # Returns members with with scores within the range of negative infinity to 3, with their scores. """ args = _create_zrange_args(key, range_query, reverse, with_scores=True) return cast( - Mapping[str, float], await self._execute_command(RequestType.ZRange, args) + Mapping[bytes, float], await self._execute_command(RequestType.ZRange, args) ) async def zrangestore( self, - destination: str, - source: str, + destination: TEncodable, + source: TEncodable, range_query: Union[RangeByIndex, RangeByLex, RangeByScore], reverse: bool = False, ) -> int: @@ -4012,8 +4081,8 @@ async def zrangestore( When in Cluster mode, `source` and `destination` must map to the same hash slot. Args: - destination (str): The key for the destination sorted set. - source (str): The key of the source sorted set. + destination (TEncodable): The key for the destination sorted set. + source (TEncodable): The key of the source sorted set. range_query (Union[RangeByIndex, RangeByLex, RangeByScore]): The range query object representing the type of range query to perform. - For range queries by index (rank), use RangeByIndex. - For range queries by lexicographical order, use RangeByLex. @@ -4035,8 +4104,8 @@ async def zrangestore( async def zrank( self, - key: str, - member: str, + key: TEncodable, + member: TEncodable, ) -> Optional[int]: """ Returns the rank of `member` in the sorted set stored at `key`, with scores ordered from low to high. @@ -4046,8 +4115,8 @@ async def zrank( To get the rank of `member` with its score, see `zrank_withscore`. Args: - key (str): The key of the sorted set. - member (str): The member whose rank is to be retrieved. + key (TEncodable): The key of the sorted set. + member (TEncodable): The member whose rank is to be retrieved. Returns: Optional[int]: The rank of `member` in the sorted set. @@ -4065,8 +4134,8 @@ async def zrank( async def zrank_withscore( self, - key: str, - member: str, + key: TEncodable, + member: TEncodable, ) -> Optional[List[Union[int, float]]]: """ Returns the rank of `member` in the sorted set stored at `key` with its score, where scores are ordered from the lowest to highest. @@ -4074,8 +4143,8 @@ async def zrank_withscore( See https://redis.io/commands/zrank for more details. Args: - key (str): The key of the sorted set. - member (str): The member whose rank is to be retrieved. + key (TEncodable): The key of the sorted set. + member (TEncodable): The member whose rank is to be retrieved. Returns: Optional[List[Union[int, float]]]: A list containing the rank and score of `member` in the sorted set. @@ -4094,7 +4163,7 @@ async def zrank_withscore( await self._execute_command(RequestType.ZRank, [key, member, "WITHSCORE"]), ) - async def zrevrank(self, key: str, member: str) -> Optional[int]: + async def zrevrank(self, key: TEncodable, member: TEncodable) -> Optional[int]: """ Returns the rank of `member` in the sorted set stored at `key`, where scores are ordered from the highest to lowest, starting from `0`. @@ -4104,8 +4173,8 @@ async def zrevrank(self, key: str, member: str) -> Optional[int]: See https://valkey.io/commands/zrevrank for more details. Args: - key (str): The key of the sorted set. - member (str): The member whose rank is to be retrieved. + key (TEncodable): The key of the sorted set. + member (TEncodable): The member whose rank is to be retrieved. Returns: Optional[int]: The rank of `member` in the sorted set, where ranks are ordered from high to low based on scores. @@ -4122,7 +4191,7 @@ async def zrevrank(self, key: str, member: str) -> Optional[int]: ) async def zrevrank_withscore( - self, key: str, member: str + self, key: TEncodable, member: TEncodable ) -> Optional[List[Union[int, float]]]: """ Returns the rank of `member` in the sorted set stored at `key` with its score, where scores are ordered from the @@ -4131,8 +4200,8 @@ async def zrevrank_withscore( See https://valkey.io/commands/zrevrank for more details. Args: - key (str): The key of the sorted set. - member (str): The member whose rank is to be retrieved. + key (TEncodable): The key of the sorted set. + member (TEncodable): The member whose rank is to be retrieved. Returns: Optional[List[Union[int, float]]]: A list containing the rank (as `int`) and score (as `float`) of `member` @@ -4155,8 +4224,8 @@ async def zrevrank_withscore( async def zrem( self, - key: str, - members: List[str], + key: TEncodable, + members: List[TEncodable], ) -> int: """ Removes the specified members from the sorted set stored at `key`. @@ -4165,8 +4234,8 @@ async def zrem( See https://redis.io/commands/zrem/ for more details. Args: - key (str): The key of the sorted set. - members (List[str]): A list of members to remove from the sorted set. + key (TEncodable): The key of the sorted set. + members (List[TEncodable]): A list of members to remove from the sorted set. Returns: int: The number of members that were removed from the sorted set, not including non-existing members. @@ -4185,7 +4254,7 @@ async def zrem( async def zremrangebyscore( self, - key: str, + key: TEncodable, min_score: Union[InfBound, ScoreBoundary], max_score: Union[InfBound, ScoreBoundary], ) -> int: @@ -4195,7 +4264,7 @@ async def zremrangebyscore( See https://redis.io/commands/zremrangebyscore/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. min_score (Union[InfBound, ScoreBoundary]): The minimum score to remove from. Can be an instance of InfBound representing positive/negative infinity, or ScoreBoundary representing a specific score and inclusivity. @@ -4233,7 +4302,7 @@ async def zremrangebyscore( async def zremrangebylex( self, - key: str, + key: TEncodable, min_lex: Union[InfBound, LexBoundary], max_lex: Union[InfBound, LexBoundary], ) -> int: @@ -4244,7 +4313,7 @@ async def zremrangebylex( See https://redis.io/commands/zremrangebylex/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. min_lex (Union[InfBound, LexBoundary]): The minimum bound of the lexicographical range. Can be an instance of `InfBound` representing positive/negative infinity, or `LexBoundary` representing a specific lex and inclusivity. @@ -4279,7 +4348,7 @@ async def zremrangebylex( async def zremrangebyrank( self, - key: str, + key: TEncodable, start: int, end: int, ) -> int: @@ -4291,7 +4360,7 @@ async def zremrangebyrank( See https://valkey.io/commands/zremrangebyrank/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. start (int): The starting point of the range. end (int): The end of the range. @@ -4316,7 +4385,7 @@ async def zremrangebyrank( async def zlexcount( self, - key: str, + key: TEncodable, min_lex: Union[InfBound, LexBoundary], max_lex: Union[InfBound, LexBoundary], ) -> int: @@ -4326,7 +4395,7 @@ async def zlexcount( See https://redis.io/commands/zlexcount/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. min_lex (Union[InfBound, LexBoundary]): The minimum lexicographical value to count from. Can be an instance of InfBound representing positive/negative infinity, or LexBoundary representing a specific lexicographical value and inclusivity. @@ -4359,15 +4428,15 @@ async def zlexcount( ), ) - async def zscore(self, key: str, member: str) -> Optional[float]: + async def zscore(self, key: TEncodable, member: TEncodable) -> Optional[float]: """ Returns the score of `member` in the sorted set stored at `key`. See https://redis.io/commands/zscore/ for more details. Args: - key (str): The key of the sorted set. - member (str): The member whose score is to be retrieved. + key (TEncodable): The key of the sorted set. + member (TEncodable): The member whose score is to be retrieved. Returns: Optional[float]: The score of the member. @@ -4387,8 +4456,8 @@ async def zscore(self, key: str, member: str) -> Optional[float]: async def zmscore( self, - key: str, - members: List[str], + key: TEncodable, + members: List[TEncodable], ) -> List[Optional[float]]: """ Returns the scores associated with the specified `members` in the sorted set stored at `key`. @@ -4396,8 +4465,8 @@ async def zmscore( See https://valkey.io/commands/zmscore for more details. Args: - key (str): The key of the sorted set. - members (List[str]): A list of members in the sorted set. + key (TEncodable): The key of the sorted set. + members (List[TEncodable]): A list of members in the sorted set. Returns: List[Optional[float]]: A list of scores corresponding to `members`. @@ -4412,7 +4481,7 @@ async def zmscore( await self._execute_command(RequestType.ZMScore, [key] + members), ) - async def zdiff(self, keys: List[str]) -> List[str]: + async def zdiff(self, keys: List[TEncodable]) -> List[bytes]: """ Returns the difference between the first sorted set and all the successive sorted sets. To get the elements with their scores, see `zdiff_withscores`. @@ -4422,10 +4491,10 @@ async def zdiff(self, keys: List[str]) -> List[str]: See https://valkey.io/commands/zdiff for more details. Args: - keys (List[str]): The keys of the sorted sets. + keys (List[TEncodable]): The keys of the sorted sets. Returns: - List[str]: A list of elements representing the difference between the sorted sets. + List[bytes]: A list of elements representing the difference between the sorted sets. If the first key does not exist, it is treated as an empty sorted set, and the command returns an empty list. @@ -4434,14 +4503,16 @@ async def zdiff(self, keys: List[str]) -> List[str]: >>> await client.zadd("sorted_set2", {"element2": 2.0}) >>> await client.zadd("sorted_set3", {"element3": 3.0}) >>> await client.zdiff("sorted_set1", "sorted_set2", "sorted_set3") - ["element1"] # Indicates that "element1" is in "sorted_set1" but not "sorted_set2" or "sorted_set3". + [b"element1"] # Indicates that "element1" is in "sorted_set1" but not "sorted_set2" or "sorted_set3". """ + args: List[TEncodable] = [str(len(keys))] + args.extend(keys) return cast( - List[str], - await self._execute_command(RequestType.ZDiff, [str(len(keys))] + keys), + List[bytes], + await self._execute_command(RequestType.ZDiff, args), ) - async def zdiff_withscores(self, keys: List[str]) -> Mapping[str, float]: + async def zdiff_withscores(self, keys: List[TEncodable]) -> Mapping[bytes, float]: """ Returns the difference between the first sorted set and all the successive sorted sets, with the associated scores. When in Cluster mode, all keys must map to the same hash slot. @@ -4449,10 +4520,10 @@ async def zdiff_withscores(self, keys: List[str]) -> Mapping[str, float]: See https://valkey.io/commands/zdiff for more details. Args: - keys (List[str]): The keys of the sorted sets. + keys (List[TEncodable]): The keys of the sorted sets. Returns: - Mapping[str, float]: A mapping of elements and their scores representing the difference between the sorted + Mapping[bytes, float]: A mapping of elements and their scores representing the difference between the sorted sets. If the first `key` does not exist, it is treated as an empty sorted set, and the command returns an empty list. @@ -4462,16 +4533,16 @@ async def zdiff_withscores(self, keys: List[str]) -> Mapping[str, float]: >>> await client.zadd("sorted_set2", {"element2": 2.0}) >>> await client.zadd("sorted_set3", {"element3": 3.0}) >>> await client.zdiff_withscores("sorted_set1", "sorted_set2", "sorted_set3") - {"element1": 1.0} # Indicates that "element1" is in "sorted_set1" but not "sorted_set2" or "sorted_set3". + {b"element1": 1.0} # Indicates that "element1" is in "sorted_set1" but not "sorted_set2" or "sorted_set3". """ return cast( - Mapping[str, float], + Mapping[bytes, float], await self._execute_command( RequestType.ZDiff, [str(len(keys))] + keys + ["WITHSCORES"] ), ) - async def zdiffstore(self, destination: str, keys: List[str]) -> int: + async def zdiffstore(self, destination: TEncodable, keys: List[TEncodable]) -> int: """ Calculates the difference between the first sorted set and all the successive sorted sets at `keys` and stores the difference as a sorted set to `destination`, overwriting it if it already exists. Non-existent keys are @@ -4482,8 +4553,8 @@ async def zdiffstore(self, destination: str, keys: List[str]) -> int: When in Cluster mode, all keys in `keys` and `destination` must map to the same hash slot. Args: - destination (str): The key for the resulting sorted set. - keys (List[str]): The keys of the sorted sets to compare. + destination (TEncodable): The key for the resulting sorted set. + keys (List[TEncodable]): The keys of the sorted sets to compare. Returns: int: The number of members in the resulting sorted set stored at `destination`. @@ -4507,8 +4578,8 @@ async def zdiffstore(self, destination: str, keys: List[str]) -> int: async def zinter( self, - keys: List[str], - ) -> List[str]: + keys: List[TEncodable], + ) -> List[bytes]: """ Computes the intersection of sorted sets given by the specified `keys` and returns a list of intersecting elements. To get the scores as well, see `zinter_withscores`. @@ -4519,27 +4590,29 @@ async def zinter( See https://valkey.io/commands/zinter/ for more details. Args: - keys (List[str]): The keys of the sorted sets. + keys (List[TEncodable]): The keys of the sorted sets. Returns: - List[str]: The resulting array of intersecting elements. + List[bytes]: The resulting array of intersecting elements. Examples: >>> await client.zadd("key1", {"member1": 10.5, "member2": 8.2}) >>> await client.zadd("key2", {"member1": 9.5}) >>> await client.zinter(["key1", "key2"]) - ['member1'] + [b'member1'] """ + args: List[TEncodable] = [str(len(keys))] + args.extend(keys) return cast( - List[str], - await self._execute_command(RequestType.ZInter, [str(len(keys))] + keys), + List[bytes], + await self._execute_command(RequestType.ZInter, args), ) async def zinter_withscores( self, - keys: Union[List[str], List[Tuple[str, float]]], + keys: Union[List[TEncodable], List[Tuple[TEncodable, float]]], aggregation_type: Optional[AggregationType] = None, - ) -> Mapping[str, float]: + ) -> Mapping[bytes, float]: """ Computes the intersection of sorted sets given by the specified `keys` and returns a sorted set of intersecting elements with scores. To get the elements only, see `zinter`. @@ -4550,34 +4623,34 @@ async def zinter_withscores( See https://valkey.io/commands/zinter/ for more details. Args: - keys (Union[List[str], List[Tuple[str, float]]]): The keys of the sorted sets with possible formats: - List[str] - for keys only. - List[Tuple[str, float]] - for weighted keys with score multipliers. + keys (Union[List[TEncodable], List[Tuple[TEncodable, float]]]): The keys of the sorted sets with possible formats: + List[TEncodable] - for keys only. + List[Tuple[TEncodable, float]] - for weighted keys with score multipliers. aggregation_type (Optional[AggregationType]): Specifies the aggregation strategy to apply when combining the scores of elements. See `AggregationType`. Returns: - Mapping[str, float]: The resulting sorted set with scores. + Mapping[bytes, float]: The resulting sorted set with scores. Examples: >>> await client.zadd("key1", {"member1": 10.5, "member2": 8.2}) >>> await client.zadd("key2", {"member1": 9.5}) >>> await client.zinter_withscores(["key1", "key2"]) - {'member1': 20} # "member1" with score of 20 is the result + {b'member1': 20} # "member1" with score of 20 is the result >>> await client.zinter_withscores(["key1", "key2"], AggregationType.MAX) - {'member1': 10.5} # "member1" with score of 10.5 is the result. + {b'member1': 10.5} # "member1" with score of 10.5 is the result. """ args = _create_zinter_zunion_cmd_args(keys, aggregation_type) args.append("WITHSCORES") return cast( - Mapping[str, float], + Mapping[bytes, float], await self._execute_command(RequestType.ZInter, args), ) async def zinterstore( self, - destination: str, - keys: Union[List[str], List[Tuple[str, float]]], + destination: TEncodable, + keys: Union[List[TEncodable], List[Tuple[TEncodable, float]]], aggregation_type: Optional[AggregationType] = None, ) -> int: """ @@ -4590,10 +4663,10 @@ async def zinterstore( See https://valkey.io/commands/zinterstore/ for more details. Args: - destination (str): The key of the destination sorted set. - keys (Union[List[str], List[Tuple[str, float]]]): The keys of the sorted sets with possible formats: - List[str] - for keys only. - List[Tuple[str, float]] - for weighted keys with score multipliers. + destination (TEncodable): The key of the destination sorted set. + keys (Union[List[TEncodable], List[Tuple[TEncodable, float]]]): The keys of the sorted sets with possible formats: + List[TEncodable] - for keys only. + List[Tuple[TEncodable, float]] - for weighted keys with score multipliers. aggregation_type (Optional[AggregationType]): Specifies the aggregation strategy to apply when combining the scores of elements. See `AggregationType`. @@ -4606,11 +4679,11 @@ async def zinterstore( >>> await client.zinterstore("my_sorted_set", ["key1", "key2"]) 1 # Indicates that the sorted set "my_sorted_set" contains one element. >>> await client.zrange_withscores("my_sorted_set", RangeByIndex(0, -1)) - {'member1': 20} # "member1" is now stored in "my_sorted_set" with score of 20. + {b'member1': 20} # "member1" is now stored in "my_sorted_set" with score of 20. >>> await client.zinterstore("my_sorted_set", ["key1", "key2"], AggregationType.MAX) 1 # Indicates that the sorted set "my_sorted_set" contains one element, and its score is the maximum score between the sets. >>> await client.zrange_withscores("my_sorted_set", RangeByIndex(0, -1)) - {'member1': 10.5} # "member1" is now stored in "my_sorted_set" with score of 10.5. + {b'member1': 10.5} # "member1" is now stored in "my_sorted_set" with score of 10.5. """ args = _create_zinter_zunion_cmd_args(keys, aggregation_type, destination) return cast( @@ -4620,8 +4693,8 @@ async def zinterstore( async def zunion( self, - keys: List[str], - ) -> List[str]: + keys: List[TEncodable], + ) -> List[bytes]: """ Computes the union of sorted sets given by the specified `keys` and returns a list of union elements. To get the scores as well, see `zunion_withscores`. @@ -4632,27 +4705,29 @@ async def zunion( See https://valkey.io/commands/zunion/ for more details. Args: - keys (List[str]): The keys of the sorted sets. + keys (List[TEncodable]): The keys of the sorted sets. Returns: - List[str]: The resulting array of union elements. + List[bytes]: The resulting array of union elements. Examples: >>> await client.zadd("key1", {"member1": 10.5, "member2": 8.2}) >>> await client.zadd("key2", {"member1": 9.5}) >>> await client.zunion(["key1", "key2"]) - ['member1', 'member2'] + [b'member1', b'member2'] """ + args: List[TEncodable] = [str(len(keys))] + args.extend(keys) return cast( - List[str], - await self._execute_command(RequestType.ZUnion, [str(len(keys))] + keys), + List[bytes], + await self._execute_command(RequestType.ZUnion, args), ) async def zunion_withscores( self, - keys: Union[List[str], List[Tuple[str, float]]], + keys: Union[List[TEncodable], List[Tuple[TEncodable, float]]], aggregation_type: Optional[AggregationType] = None, - ) -> Mapping[str, float]: + ) -> Mapping[bytes, float]: """ Computes the union of sorted sets given by the specified `keys` and returns a sorted set of union elements with scores. To get the elements only, see `zunion`. @@ -4663,34 +4738,34 @@ async def zunion_withscores( See https://valkey.io/commands/zunion/ for more details. Args: - keys (Union[List[str], List[Tuple[str, float]]]): The keys of the sorted sets with possible formats: - List[str] - for keys only. - List[Tuple[str, float]] - for weighted keys with score multipliers. + keys (Union[List[TEncodable], List[Tuple[TEncodable, float]]]): The keys of the sorted sets with possible formats: + List[TEncodable] - for keys only. + List[Tuple[TEncodable, float]] - for weighted keys with score multipliers. aggregation_type (Optional[AggregationType]): Specifies the aggregation strategy to apply when combining the scores of elements. See `AggregationType`. Returns: - Mapping[str, float]: The resulting sorted set with scores. + Mapping[bytes, float]: The resulting sorted set with scores. Examples: >>> await client.zadd("key1", {"member1": 10.5, "member2": 8.2}) >>> await client.zadd("key2", {"member1": 9.5}) >>> await client.zunion_withscores(["key1", "key2"]) - {'member1': 20, 'member2': 8.2} + {b'member1': 20, b'member2': 8.2} >>> await client.zunion_withscores(["key1", "key2"], AggregationType.MAX) - {'member1': 10.5, 'member2': 8.2} + {b'member1': 10.5, b'member2': 8.2} """ args = _create_zinter_zunion_cmd_args(keys, aggregation_type) args.append("WITHSCORES") return cast( - Mapping[str, float], + Mapping[bytes, float], await self._execute_command(RequestType.ZUnion, args), ) async def zunionstore( self, - destination: str, - keys: Union[List[str], List[Tuple[str, float]]], + destination: TEncodable, + keys: Union[List[TEncodable], List[Tuple[TEncodable, float]]], aggregation_type: Optional[AggregationType] = None, ) -> int: """ @@ -4703,10 +4778,10 @@ async def zunionstore( See https://valkey.io/commands/zunionstore/ for more details. Args: - destination (str): The key of the destination sorted set. - keys (Union[List[str], List[Tuple[str, float]]]): The keys of the sorted sets with possible formats: - List[str] - for keys only. - List[Tuple[str, float]] - for weighted keys with score multipliers. + destination (TEncodable): The key of the destination sorted set. + keys (Union[List[TEncodable], List[Tuple[TEncodable, float]]]): The keys of the sorted sets with possible formats: + List[TEncodable] - for keys only. + List[Tuple[TEncodable, float]] - for weighted keys with score multipliers. aggregation_type (Optional[AggregationType]): Specifies the aggregation strategy to apply when combining the scores of elements. See `AggregationType`. @@ -4719,11 +4794,11 @@ async def zunionstore( >>> await client.zunionstore("my_sorted_set", ["key1", "key2"]) 2 # Indicates that the sorted set "my_sorted_set" contains two elements. >>> await client.zrange_withscores("my_sorted_set", RangeByIndex(0, -1)) - {'member1': 20, 'member2': 8.2} + {b'member1': 20, b'member2': 8.2} >>> await client.zunionstore("my_sorted_set", ["key1", "key2"], AggregationType.MAX) 2 # Indicates that the sorted set "my_sorted_set" contains two elements, and each score is the maximum score between the sets. >>> await client.zrange_withscores("my_sorted_set", RangeByIndex(0, -1)) - {'member1': 10.5, 'member2': 8.2} + {b'member1': 10.5, b'member2': 8.2} """ args = _create_zinter_zunion_cmd_args(keys, aggregation_type, destination) return cast( @@ -4731,62 +4806,64 @@ async def zunionstore( await self._execute_command(RequestType.ZUnionStore, args), ) - async def zrandmember(self, key: str) -> Optional[str]: + async def zrandmember(self, key: TEncodable) -> Optional[bytes]: """ Returns a random member from the sorted set stored at 'key'. See https://valkey.io/commands/zrandmember for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. Returns: - Optional[str]: A random member from the sorted set. + Optional[bytes]: A random member from the sorted set. If the sorted set does not exist or is empty, the response will be None. Examples: >>> await client.zadd("my_sorted_set", {"member1": 1.0, "member2": 2.0}) >>> await client.zrandmember("my_sorted_set") - "member1" # "member1" is a random member of "my_sorted_set". + b"member1" # "member1" is a random member of "my_sorted_set". >>> await client.zrandmember("non_existing_sorted_set") None # "non_existing_sorted_set" is not an existing key, so None was returned. """ + args: List[TEncodable] = [key] return cast( - Optional[str], + Optional[bytes], await self._execute_command(RequestType.ZRandMember, [key]), ) - async def zrandmember_count(self, key: str, count: int) -> List[str]: + async def zrandmember_count(self, key: TEncodable, count: int) -> List[bytes]: """ Retrieves up to the absolute value of `count` random members from the sorted set stored at 'key'. See https://valkey.io/commands/zrandmember for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. count (int): The number of members to return. If `count` is positive, returns unique members. If `count` is negative, allows for duplicates members. Returns: - List[str]: A list of members from the sorted set. + List[bytes]: A list of members from the sorted set. If the sorted set does not exist or is empty, the response will be an empty list. Examples: >>> await client.zadd("my_sorted_set", {"member1": 1.0, "member2": 2.0}) >>> await client.zrandmember("my_sorted_set", -3) - ["member1", "member1", "member2"] # "member1" and "member2" are random members of "my_sorted_set". + [b"member1", b"member1", b"member2"] # "member1" and "member2" are random members of "my_sorted_set". >>> await client.zrandmember("non_existing_sorted_set", 3) [] # "non_existing_sorted_set" is not an existing key, so an empty list was returned. """ + args: List[TEncodable] = [key, str(count)] return cast( - List[str], - await self._execute_command(RequestType.ZRandMember, [key, str(count)]), + List[bytes], + await self._execute_command(RequestType.ZRandMember, args), ) async def zrandmember_withscores( - self, key: str, count: int - ) -> List[List[Union[str, float]]]: + self, key: TEncodable, count: int + ) -> List[List[Union[bytes, float]]]: """ Retrieves up to the absolute value of `count` random members along with their scores from the sorted set stored at 'key'. @@ -4794,33 +4871,35 @@ async def zrandmember_withscores( See https://valkey.io/commands/zrandmember for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. count (int): The number of members to return. If `count` is positive, returns unique members. If `count` is negative, allows for duplicates members. Returns: - List[List[Union[str, float]]]: A list of `[member, score]` lists, where `member` is a random member from + List[List[Union[bytes, float]]]: A list of `[member, score]` lists, where `member` is a random member from the sorted set and `score` is the associated score. If the sorted set does not exist or is empty, the response will be an empty list. Examples: >>> await client.zadd("my_sorted_set", {"member1": 1.0, "member2": 2.0}) >>> await client.zrandmember_withscores("my_sorted_set", -3) - [["member1", 1.0], ["member1", 1.0], ["member2", 2.0]] # "member1" and "member2" are random members of "my_sorted_set", and have scores of 1.0 and 2.0, respectively. + [[b"member1", 1.0], [b"member1", 1.0], [b"member2", 2.0]] # "member1" and "member2" are random members of "my_sorted_set", and have scores of 1.0 and 2.0, respectively. >>> await client.zrandmember_withscores("non_existing_sorted_set", 3) [] # "non_existing_sorted_set" is not an existing key, so an empty list was returned. """ + args: List[TEncodable] = [key, str(count), "WITHSCORES"] return cast( - List[List[Union[str, float]]], - await self._execute_command( - RequestType.ZRandMember, [key, str(count), "WITHSCORES"] - ), + List[List[Union[bytes, float]]], + await self._execute_command(RequestType.ZRandMember, args), ) async def zmpop( - self, keys: List[str], filter: ScoreFilter, count: Optional[int] = None - ) -> Optional[List[Union[str, Mapping[str, float]]]]: + self, + keys: List[TEncodable], + filter: ScoreFilter, + count: Optional[int] = None, + ) -> Optional[List[Union[bytes, Mapping[bytes, float]]]]: """ Pops a member-score pair from the first non-empty sorted set, with the given keys being checked in the order that they are given. @@ -4836,13 +4915,13 @@ async def zmpop( When in cluster mode, all `keys` must map to the same hash slot. Args: - keys (List[str]): The keys of the sorted sets. - modifier (ScoreFilter): The element pop criteria - either ScoreFilter.MIN or ScoreFilter.MAX to pop + keys (List[TEncodable]): The keys of the sorted sets. + filter (ScoreFilter): The element pop criteria - either ScoreFilter.MIN or ScoreFilter.MAX to pop members with the lowest/highest scores accordingly. count (Optional[int]): The number of elements to pop. Returns: - Optional[List[Union[str, Mapping[str, float]]]]: A two-element list containing the key name of the set from + Optional[List[Union[bytes, Mapping[bytes, float]]]]: A two-element list containing the key name of the set from which elements were popped, and a member-score mapping of the popped elements. If no members could be popped, returns None. @@ -4850,26 +4929,26 @@ async def zmpop( >>> await client.zadd("zSet1", {"one": 1.0, "two": 2.0, "three": 3.0}) >>> await client.zadd("zSet2", {"four": 4.0}) >>> await client.zmpop(["zSet1", "zSet2"], ScoreFilter.MAX, 2) - ['zSet1', {'three': 3.0, 'two': 2.0}] # "three" with score 3.0 and "two" with score 2.0 were popped from "zSet1". + [b'zSet1', {b'three': 3.0, b'two': 2.0}] # "three" with score 3.0 and "two" with score 2.0 were popped from "zSet1". Since: Redis version 7.0.0. """ - args = [str(len(keys))] + keys + [filter.value] + args: List[TEncodable] = [str(len(keys))] + keys + [filter.value] if count is not None: - args = args + ["COUNT", str(count)] + args.extend(["COUNT", str(count)]) return cast( - Optional[List[Union[str, Mapping[str, float]]]], + Optional[List[Union[bytes, Mapping[bytes, float]]]], await self._execute_command(RequestType.ZMPop, args), ) async def bzmpop( self, - keys: List[str], + keys: List[TEncodable], modifier: ScoreFilter, timeout: float, count: Optional[int] = None, - ) -> Optional[List[Union[str, Mapping[str, float]]]]: + ) -> Optional[List[Union[bytes, Mapping[bytes, float]]]]: """ Pops a member-score pair from the first non-empty sorted set, with the given keys being checked in the order that they are given. Blocks the connection when there are no members to pop from any of the given sorted sets. @@ -4887,7 +4966,7 @@ async def bzmpop( 2. `BZMPOP` is a client blocking command, see https://github.com/aws/glide-for-redis/wiki/General-Concepts#blocking-commands for more details and best practices. Args: - keys (List[str]): The keys of the sorted sets. + keys (List[TEncodable]): The keys of the sorted sets. modifier (ScoreFilter): The element pop criteria - either ScoreFilter.MIN or ScoreFilter.MAX to pop members with the lowest/highest scores accordingly. timeout (float): The number of seconds to wait for a blocking operation to complete. A value of 0 will @@ -4895,7 +4974,7 @@ async def bzmpop( count (Optional[int]): The number of elements to pop. Returns: - Optional[List[Union[str, Mapping[str, float]]]]: A two-element list containing the key name of the set from + Optional[List[Union[bytes, Mapping[bytes, float]]]]: A two-element list containing the key name of the set from which elements were popped, and a member-score mapping of the popped elements. If no members could be popped and the timeout expired, returns None. @@ -4903,7 +4982,7 @@ async def bzmpop( >>> await client.zadd("zSet1", {"one": 1.0, "two": 2.0, "three": 3.0}) >>> await client.zadd("zSet2", {"four": 4.0}) >>> await client.bzmpop(["zSet1", "zSet2"], ScoreFilter.MAX, 0.5, 2) - ['zSet1', {'three': 3.0, 'two': 2.0}] # "three" with score 3.0 and "two" with score 2.0 were popped from "zSet1". + [b'zSet1', {b'three': 3.0, b'two': 2.0}] # "three" with score 3.0 and "two" with score 2.0 were popped from "zSet1". Since: Redis version 7.0.0. """ @@ -4912,11 +4991,13 @@ async def bzmpop( args = args + ["COUNT", str(count)] return cast( - Optional[List[Union[str, Mapping[str, float]]]], + Optional[List[Union[bytes, Mapping[bytes, float]]]], await self._execute_command(RequestType.BZMPop, args), ) - async def zintercard(self, keys: List[str], limit: Optional[int] = None) -> int: + async def zintercard( + self, keys: List[TEncodable], limit: Optional[int] = None + ) -> int: """ Returns the cardinality of the intersection of the sorted sets specified by `keys`. When provided with the optional `limit` argument, if the intersection cardinality reaches `limit` partway through the computation, the @@ -4925,7 +5006,7 @@ async def zintercard(self, keys: List[str], limit: Optional[int] = None) -> int: See https://valkey.io/commands/zintercard for more details. Args: - keys (List[str]): The keys of the sorted sets to intersect. + keys (List[TEncodable]): The keys of the sorted sets to intersect. limit (Optional[int]): An optional argument that can be used to specify a maximum number for the intersection cardinality. If limit is not supplied, or if it is set to 0, there will be no limit. @@ -4957,8 +5038,8 @@ async def zintercard(self, keys: List[str], limit: Optional[int] = None) -> int: async def invoke_script( self, script: Script, - keys: Optional[List[Union[str, bytes]]] = None, - args: Optional[List[Union[str, bytes]]] = None, + keys: Optional[List[TEncodable]] = None, + args: Optional[List[TEncodable]] = None, ) -> TResult: """ Invokes a Lua script with its keys and arguments. @@ -4971,8 +5052,8 @@ async def invoke_script( Args: script (Script): The Lua script to execute. - keys (List[Union[str, bytes]]): The keys that are used in the script. - args (List[Union[str, bytes]]): The arguments for the script. + keys (Optional[List[TEncodable]]): The keys that are used in the script. + args (Optional[List[TEncodable]]): The arguments for the script. Returns: TResult: a value that depends on the script that was executed. @@ -4980,11 +5061,11 @@ async def invoke_script( Examples: >>> lua_script = Script("return { KEYS[1], ARGV[1] }") >>> await invoke_script(lua_script, keys=["foo"], args=["bar"] ); - ["foo", "bar"] + [b"foo", b"bar"] """ return await self._execute_script(script.get_hash(), keys, args) - async def pfadd(self, key: str, elements: List[str]) -> int: + async def pfadd(self, key: TEncodable, elements: List[TEncodable]) -> int: """ Adds all elements to the HyperLogLog data structure stored at the specified `key`. Creates a new structure if the `key` does not exist. @@ -4993,8 +5074,8 @@ async def pfadd(self, key: str, elements: List[str]) -> int: See https://redis.io/commands/pfadd/ for more details. Args: - key (str): The key of the HyperLogLog data structure to add elements into. - elements (List[str]): A list of members to add to the HyperLogLog stored at `key`. + key (TEncodable): The key of the HyperLogLog data structure to add elements into. + elements (List[TEncodable]): A list of members to add to the HyperLogLog stored at `key`. Returns: int: If the HyperLogLog is newly created, or if the HyperLogLog approximated cardinality is @@ -5011,7 +5092,7 @@ async def pfadd(self, key: str, elements: List[str]) -> int: await self._execute_command(RequestType.PfAdd, [key] + elements), ) - async def pfcount(self, keys: List[str]) -> int: + async def pfcount(self, keys: List[TEncodable]) -> int: """ Estimates the cardinality of the data stored in a HyperLogLog structure for a single key or calculates the combined cardinality of multiple keys by merging their HyperLogLogs temporarily. @@ -5022,7 +5103,7 @@ async def pfcount(self, keys: List[str]) -> int: When in Cluster mode, all `keys` must map to the same hash slot. Args: - keys (List[str]): The keys of the HyperLogLog data structures to be analyzed. + keys (List[TEncodable]): The keys of the HyperLogLog data structures to be analyzed. Returns: int: The approximated cardinality of given HyperLogLog data structures. @@ -5037,7 +5118,9 @@ async def pfcount(self, keys: List[str]) -> int: await self._execute_command(RequestType.PfCount, keys), ) - async def pfmerge(self, destination: str, source_keys: List[str]) -> TOK: + async def pfmerge( + self, destination: TEncodable, source_keys: List[TEncodable] + ) -> TOK: """ Merges multiple HyperLogLog values into a unique value. If the destination variable exists, it is treated as one of the source HyperLogLog data sets, otherwise a new HyperLogLog is created. @@ -5048,8 +5131,8 @@ async def pfmerge(self, destination: str, source_keys: List[str]) -> TOK: When in Cluster mode, all keys in `source_keys` and `destination` must map to the same hash slot. Args: - destination (str): The key of the destination HyperLogLog where the merged data sets will be stored. - source_keys (List[str]): The keys of the HyperLogLog structures to be merged. + destination (TEncodable): The key of the destination HyperLogLog where the merged data sets will be stored. + source_keys (List[TEncodable]): The keys of the HyperLogLog structures to be merged. Returns: OK: A simple OK response. @@ -5069,7 +5152,9 @@ async def pfmerge(self, destination: str, source_keys: List[str]) -> TOK: ), ) - async def bitcount(self, key: str, options: Optional[OffsetOptions] = None) -> int: + async def bitcount( + self, key: TEncodable, options: Optional[OffsetOptions] = None + ) -> int: """ Counts the number of set bits (population counting) in the string stored at `key`. The `options` argument can optionally be provided to count the number of bits in a specific string interval. @@ -5077,7 +5162,7 @@ async def bitcount(self, key: str, options: Optional[OffsetOptions] = None) -> i See https://valkey.io/commands/bitcount for more details. Args: - key (str): The key for the string to count the set bits of. + key (TEncodable): The key for the string to count the set bits of. options (Optional[OffsetOptions]): The offset options. Returns: @@ -5095,16 +5180,16 @@ async def bitcount(self, key: str, options: Optional[OffsetOptions] = None) -> i >>> await client.bitcount("my_key3", OffsetOptions(-1, -1, BitmapIndexType.BIT)) 1 # Indicates that the last bit of the string stored at "my_key3" is set. """ - args = [key] + args: List[TEncodable] = [key] if options is not None: - args = args + options.to_args() + args.extend(options.to_args()) return cast( int, await self._execute_command(RequestType.BitCount, args), ) - async def setbit(self, key: str, offset: int, value: int) -> int: + async def setbit(self, key: TEncodable, offset: int, value: int) -> int: """ Sets or clears the bit at `offset` in the string value stored at `key`. The `offset` is a zero-based index, with `0` being the first element of the list, `1` being the next element, and so on. The `offset` must be less @@ -5114,7 +5199,7 @@ async def setbit(self, key: str, offset: int, value: int) -> int: See https://valkey.io/commands/setbit for more details. Args: - key (str): The key of the string. + key (TEncodable): The key of the string. offset (int): The index of the bit to be set. value (int): The bit value to set at `offset`. The value must be `0` or `1`. @@ -5132,7 +5217,7 @@ async def setbit(self, key: str, offset: int, value: int) -> int: ), ) - async def getbit(self, key: str, offset: int) -> int: + async def getbit(self, key: TEncodable, offset: int) -> int: """ Returns the bit value at `offset` in the string value stored at `key`. `offset` should be greater than or equal to zero. @@ -5140,7 +5225,7 @@ async def getbit(self, key: str, offset: int) -> int: See https://valkey.io/commands/getbit for more details. Args: - key (str): The key of the string. + key (TEncodable): The key of the string. offset (int): The index of the bit to return. Returns: @@ -5156,7 +5241,9 @@ async def getbit(self, key: str, offset: int) -> int: await self._execute_command(RequestType.GetBit, [key, str(offset)]), ) - async def bitpos(self, key: str, bit: int, start: Optional[int] = None) -> int: + async def bitpos( + self, key: TEncodable, bit: int, start: Optional[int] = None + ) -> int: """ Returns the position of the first bit matching the given `bit` value. The optional starting offset `start` is a zero-based index, with `0` being the first byte of the list, `1` being the next byte and so on. @@ -5166,7 +5253,7 @@ async def bitpos(self, key: str, bit: int, start: Optional[int] = None) -> int: See https://valkey.io/commands/bitpos for more details. Args: - key (str): The key of the string. + key (TEncodable): The key of the string. bit (int): The bit value to match. Must be `0` or `1`. start (Optional[int]): The starting offset. @@ -5189,7 +5276,7 @@ async def bitpos(self, key: str, bit: int, start: Optional[int] = None) -> int: async def bitpos_interval( self, - key: str, + key: TEncodable, bit: int, start: int, end: int, @@ -5209,7 +5296,7 @@ async def bitpos_interval( See https://valkey.io/commands/bitpos for more details. Args: - key (str): The key of the string. + key (TEncodable): The key of the string. bit (int): The bit value to match. Must be `0` or `1`. start (int): The starting offset. end (int): The ending offset. @@ -5239,7 +5326,10 @@ async def bitpos_interval( ) async def bitop( - self, operation: BitwiseOperation, destination: str, keys: List[str] + self, + operation: BitwiseOperation, + destination: TEncodable, + keys: List[TEncodable], ) -> int: """ Perform a bitwise operation between multiple keys (containing string values) and store the result in the @@ -5252,8 +5342,8 @@ async def bitop( Args: operation (BitwiseOperation): The bitwise operation to perform. - destination (str): The key that will store the resulting string. - keys (List[str]): The list of keys to perform the bitwise operation on. + destination (TEncodable): The key that will store the resulting string. + keys (List[TEncodable]): The list of keys to perform the bitwise operation on. Returns: int: The size of the string stored in `destination`. @@ -5274,7 +5364,7 @@ async def bitop( ) async def bitfield( - self, key: str, subcommands: List[BitFieldSubCommands] + self, key: TEncodable, subcommands: List[BitFieldSubCommands] ) -> List[Optional[int]]: """ Reads or modifies the array of bits representing the string that is held at `key` based on the specified @@ -5283,7 +5373,7 @@ async def bitfield( See https://valkey.io/commands/bitfield for more details. Args: - key (str): The key of the string. + key (TEncodable): The key of the string. subcommands (List[BitFieldSubCommands]): The subcommands to be performed on the binary value of the string at `key`, which could be any of the following: - `BitFieldGet` @@ -5312,7 +5402,7 @@ async def bitfield( ) async def bitfield_read_only( - self, key: str, subcommands: List[BitFieldGet] + self, key: TEncodable, subcommands: List[BitFieldGet] ) -> List[int]: """ Reads the array of bits representing the string that is held at `key` based on the specified `subcommands`. @@ -5320,7 +5410,7 @@ async def bitfield_read_only( See https://valkey.io/commands/bitfield_ro for more details. Args: - key (str): The key of the string. + key (TEncodable): The key of the string. subcommands (List[BitFieldGet]): The "GET" subcommands to be performed. Returns: @@ -5339,36 +5429,36 @@ async def bitfield_read_only( await self._execute_command(RequestType.BitFieldReadOnly, args), ) - async def object_encoding(self, key: str) -> Optional[str]: + async def object_encoding(self, key: TEncodable) -> Optional[bytes]: """ Returns the internal encoding for the Redis object stored at `key`. See https://valkey.io/commands/object-encoding for more details. Args: - key (str): The `key` of the object to get the internal encoding of. + key (TEncodable): The `key` of the object to get the internal encoding of. Returns: - Optional[str]: If `key` exists, returns the internal encoding of the object stored at - `key` as a string. Otherwise, returns None. + Optional[bytes]: If `key` exists, returns the internal encoding of the object stored at + `key` as a bytes string. Otherwise, returns None. Examples: >>> await client.object_encoding("my_hash") - "listpack" # The hash stored at "my_hash" has an internal encoding of "listpack". + b"listpack" # The hash stored at "my_hash" has an internal encoding of "listpack". """ return cast( - Optional[str], + Optional[bytes], await self._execute_command(RequestType.ObjectEncoding, [key]), ) - async def object_freq(self, key: str) -> Optional[int]: + async def object_freq(self, key: TEncodable) -> Optional[int]: """ Returns the logarithmic access frequency counter of a Redis object stored at `key`. See https://valkey.io/commands/object-freq for more details. Args: - key (str): The key of the object to get the logarithmic access frequency counter of. + key (TEncodable): The key of the object to get the logarithmic access frequency counter of. Returns: Optional[int]: If `key` exists, returns the logarithmic access frequency counter of the object stored at `key` as an @@ -5383,14 +5473,14 @@ async def object_freq(self, key: str) -> Optional[int]: await self._execute_command(RequestType.ObjectFreq, [key]), ) - async def object_idletime(self, key: str) -> Optional[int]: + async def object_idletime(self, key: TEncodable) -> Optional[int]: """ Returns the time in seconds since the last access to the value stored at `key`. See https://valkey.io/commands/object-idletime for more details. Args: - key (str): The key of the object to get the idle time of. + key (TEncodable): The key of the object to get the idle time of. Returns: Optional[int]: If `key` exists, returns the idle time in seconds. Otherwise, returns None. @@ -5404,14 +5494,14 @@ async def object_idletime(self, key: str) -> Optional[int]: await self._execute_command(RequestType.ObjectIdleTime, [key]), ) - async def object_refcount(self, key: str) -> Optional[int]: + async def object_refcount(self, key: TEncodable) -> Optional[int]: """ Returns the reference count of the object stored at `key`. See https://valkey.io/commands/object-refcount for more details. Args: - key (str): The key of the object to get the reference count of. + key (TEncodable): The key of the object to get the reference count of. Returns: Optional[int]: If `key` exists, returns the reference count of the object stored at `key` as an integer. @@ -5426,74 +5516,75 @@ async def object_refcount(self, key: str) -> Optional[int]: await self._execute_command(RequestType.ObjectRefCount, [key]), ) - async def srandmember(self, key: str) -> Optional[str]: + async def srandmember(self, key: TEncodable) -> Optional[bytes]: """ Returns a random element from the set value stored at 'key'. See https://valkey.io/commands/srandmember for more details. Args: - key (str): The key from which to retrieve the set member. + key (TEncodable): The key from which to retrieve the set member. Returns: - str: A random element from the set, or None if 'key' does not exist. + Optional[bytes]: A random element from the set, or None if 'key' does not exist. Examples: >>> await client.sadd("my_set", {"member1": 1.0, "member2": 2.0}) - >>> await client.srandmember("my_set") - "member1" # "member1" is a random member of "my_set". + >>> await client.srandmember(b"my_set") + b"member1" # "member1" is a random member of "my_set". >>> await client.srandmember("non_existing_set") - None # "non_existing_set" is not an existing key, so None was returned. + None # "non_existing_set" is not an existing key, so None was returned. """ + args: List[TEncodable] = [key] return cast( - Optional[str], - await self._execute_command(RequestType.SRandMember, [key]), + Optional[bytes], + await self._execute_command(RequestType.SRandMember, args), ) - async def srandmember_count(self, key: str, count: int) -> List[str]: + async def srandmember_count(self, key: TEncodable, count: int) -> List[bytes]: """ Returns one or more random elements from the set value stored at 'key'. See https://valkey.io/commands/srandmember for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. count (int): The number of members to return. If `count` is positive, returns unique members. If `count` is negative, allows for duplicates members. Returns: - List[str]: A list of members from the set. + List[bytes]: A list of members from the set. If the set does not exist or is empty, the response will be an empty list. Examples: >>> await client.sadd("my_set", {"member1": 1.0, "member2": 2.0}) >>> await client.srandmember("my_set", -3) - ["member1", "member1", "member2"] # "member1" and "member2" are random members of "my_set". + [b"member1", b"member1", b"member2"] # "member1" and "member2" are random members of "my_set". >>> await client.srandmember("non_existing_set", 3) [] # "non_existing_set" is not an existing key, so an empty list was returned. """ return cast( - List[str], + List[bytes], await self._execute_command(RequestType.SRandMember, [key, str(count)]), ) async def getex( self, - key: str, + key: TEncodable, expiry: Optional[ExpiryGetEx] = None, - ) -> Optional[str]: + ) -> Optional[bytes]: """ Get the value of `key` and optionally set its expiration. `GETEX` is similar to `GET`. See https://valkey.io/commands/getex for more details. Args: - key (str): The key to get. - expiry (Optional[ExpirySet], optional): set expiriation to the given key. + key (TEncodable): The key to get. + expiry (Optional[ExpiryGetEx], optional): set expiriation to the given key. Equivalent to [`EX` | `PX` | `EXAT` | `PXAT` | `PERSIST`] in the Redis API. Returns: - Optional[str]: + Optional[bytes]: If `key` exists, return the value stored at `key` If `key` does not exist, return `None` @@ -5501,11 +5592,11 @@ async def getex( >>> await client.set("key", "value") 'OK' >>> await client.getex("key") - 'value' + b'value' >>> await client.getex("key", ExpiryGetEx(ExpiryTypeGetEx.SEC, 1)) - 'value' + b'value' >>> time.sleep(1) - >>> await client.getex("key") + >>> await client.getex(b"key") None Since: Redis version 6.2.0. @@ -5514,28 +5605,28 @@ async def getex( if expiry is not None: args.extend(expiry.get_cmd_args()) return cast( - Optional[str], + Optional[bytes], await self._execute_command(RequestType.GetEx, args), ) async def sscan( self, - key: str, - cursor: str, - match: Optional[str] = None, + key: TEncodable, + cursor: TEncodable, + match: Optional[TEncodable] = None, count: Optional[int] = None, - ) -> List[Union[str, List[str]]]: + ) -> List[Union[bytes, List[bytes]]]: """ Iterates incrementally over a set. See https://valkey.io/commands/sscan for more details. Args: - key (str): The key of the set. - cursor (str): The cursor that points to the next iteration of results. A value of "0" indicates the start of + key (TEncodable): The key of the set. + cursor (TEncodable): The cursor that points to the next iteration of results. A value of "0" indicates the start of the search. - match (Optional[str]): The match filter is applied to the result of the command and will only include - strings that match the pattern specified. If the set is large enough for scan commands to return only a + match (Optional[TEncodable]): The match filter is applied to the result of the command and will only include + strings or byte strings that match the pattern specified. If the set is large enough for scan commands to return only a subset of the set then there could be a case where the result is empty although there are items that match the pattern specified. This is due to the default `COUNT` being `10` which indicates that it will only fetch and match `10` items from the list. @@ -5544,7 +5635,7 @@ async def sscan( as compact single-allocation packed encoding. Returns: - List[Union[str, List[str]]]: An `Array` of the `cursor` and the subset of the set held by `key`. + List[Union[bytes, List[bytes]]]: An `Array` of the `cursor` and the subset of the set held by `key`. The first element is always the `cursor` for the next iteration of results. `0` will be the `cursor` returned on the last iteration of the set. The second element is always an `Array` of the subset of the set held in `key`. @@ -5561,41 +5652,41 @@ async def sscan( ... break ... result_cursor = new_cursor Cursor: 48 - Members: ['3', '118', '120', '86', '76', '13', '61', '111', '55', '45'] - Cursor: 24 - Members: ['38', '109', '11', '119', '34', '24', '40', '57', '20', '17'] - Cursor: 0 - Members: ['47', '122', '1', '53', '10', '14', '80'] + Members: [b'3', b'118', b'120', b'86', b'76', b'13', b'61', b'111', b'55', b'45'] + Cursor: 24 + Members: [b'38', b'109', b'11', b'119', b'34', b'24', b'40', b'57', b'20', b'17'] + Cursor: 0 + Members: [b'47', b'122', b'1', b'53', b'10', b'14', b'80'] """ - args = [key, cursor] + args: List[TEncodable] = [key, cursor] if match is not None: args += ["MATCH", match] if count is not None: args += ["COUNT", str(count)] return cast( - List[Union[str, List[str]]], + List[Union[bytes, List[bytes]]], await self._execute_command(RequestType.SScan, args), ) async def zscan( self, - key: str, - cursor: str, - match: Optional[str] = None, + key: TEncodable, + cursor: TEncodable, + match: Optional[TEncodable] = None, count: Optional[int] = None, - ) -> List[Union[str, List[str]]]: + ) -> List[Union[bytes, List[bytes]]]: """ Iterates incrementally over a sorted set. See https://valkey.io/commands/zscan for more details. Args: - key (str): The key of the sorted set. - cursor (str): The cursor that points to the next iteration of results. A value of "0" indicates the start of + key (TEncodable): The key of the sorted set. + cursor (TEncodable): The cursor that points to the next iteration of results. A value of "0" indicates the start of the search. - match (Optional[str]): The match filter is applied to the result of the command and will only include - strings that match the pattern specified. If the sorted set is large enough for scan commands to return + match (Optional[TEncodable]): The match filter is applied to the result of the command and will only include + strings or byte strings that match the pattern specified. If the sorted set is large enough for scan commands to return only a subset of the sorted set then there could be a case where the result is empty although there are items that match the pattern specified. This is due to the default `COUNT` being `10` which indicates that it will only fetch and match `10` items from the list. @@ -5604,7 +5695,7 @@ async def zscan( represent the results as compact single-allocation packed encoding. Returns: - List[Union[str, List[str]]]: An `Array` of the `cursor` and the subset of the sorted set held by `key`. + List[Union[bytes, List[bytes]]]: An `Array` of the `cursor` and the subset of the sorted set held by `key`. The first element is always the `cursor` for the next iteration of results. `0` will be the `cursor` returned on the last iteration of the sorted set. The second element is always an `Array` of the subset of the sorted set held in `key`. The `Array` in the second element is always a flattened series of @@ -5621,42 +5712,42 @@ async def zscan( ... if new_cursor == "0": ... break ... result_cursor = new_cursor - Cursor: 123 - Members: ['value 163', '163', 'value 114', '114', 'value 25', '25', 'value 82', '82', 'value 64', '64'] - Cursor: 47 - Members: ['value 39', '39', 'value 127', '127', 'value 43', '43', 'value 139', '139', 'value 211', '211'] - Cursor: 0 - Members: ['value 55', '55', 'value 24', '24', 'value 90', '90', 'value 113', '113'] - """ - args = [key, cursor] + Cursor: 123 + Members: [b'value 163', b'163', b'value 114', b'114', b'value 25', b'25', b'value 82', b'82', b'value 64', b'64'] + Cursor: 47 + Members: [b'value 39', b'39', b'value 127', b'127', b'value 43', b'43', b'value 139', b'139', b'value 211', b'211'] + Cursor: 0 + Members: [b'value 55', b'55', b'value 24', b'24', b'value 90', b'90', b'value 113', b'113'] + """ + args: List[TEncodable] = [key, cursor] if match is not None: args += ["MATCH", match] if count is not None: args += ["COUNT", str(count)] return cast( - List[Union[str, List[str]]], + List[Union[bytes, List[bytes]]], await self._execute_command(RequestType.ZScan, args), ) async def hscan( self, - key: str, - cursor: str, - match: Optional[str] = None, + key: TEncodable, + cursor: TEncodable, + match: Optional[TEncodable] = None, count: Optional[int] = None, - ) -> List[Union[str, List[str]]]: + ) -> List[Union[bytes, List[bytes]]]: """ Iterates incrementally over a hash. See https://valkey.io/commands/hscan for more details. Args: - key (str): The key of the set. - cursor (str): The cursor that points to the next iteration of results. A value of "0" indicates the start of + key (TEncodable): The key of the set. + cursor (TEncodable): The cursor that points to the next iteration of results. A value of "0" indicates the start of the search. - match (Optional[str]): The match filter is applied to the result of the command and will only include - strings that match the pattern specified. If the hash is large enough for scan commands to return only a + match (Optional[TEncodable]): The match filter is applied to the result of the command and will only include + strings or byte strings that match the pattern specified. If the hash is large enough for scan commands to return only a subset of the hash then there could be a case where the result is empty although there are items that match the pattern specified. This is due to the default `COUNT` being `10` which indicates that it will only fetch and match `10` items from the list. @@ -5665,7 +5756,7 @@ async def hscan( as compact single-allocation packed encoding. Returns: - List[Union[str, List[str]]]: An `Array` of the `cursor` and the subset of the hash held by `key`. + List[Union[bytes, List[bytes]]]: An `Array` of the `cursor` and the subset of the hash held by `key`. The first element is always the `cursor` for the next iteration of results. `0` will be the `cursor` returned on the last iteration of the hash. The second element is always an `Array` of the subset of the hash held in `key`. The `Array` in the second element is always a flattened series of `String` pairs, @@ -5682,55 +5773,50 @@ async def hscan( ... if new_cursor == "0": ... break ... result_cursor = new_cursor - Cursor: 31 - Members: ['field 79', 'value 79', 'field 20', 'value 20', 'field 115', 'value 115'] - Cursor: 39 - Members: ['field 63', 'value 63', 'field 293', 'value 293', 'field 162', 'value 162'] - Cursor: 0 - Members: ['field 420', 'value 420', 'field 221', 'value 221'] - """ - args = [key, cursor] + Cursor: 1 + Members: [b'field 79', b'value 79', b'field 20', b'value 20', b'field 115', b'value 115'] + Cursor: 39 + Members: [b'field 63', b'value 63', b'field 293', b'value 293', b'field 162', b'value 162'] + Cursor: 0 + Members: [b'field 420', b'value 420', b'field 221', b'value 221'] + """ + args: List[TEncodable] = [key, cursor] if match is not None: args += ["MATCH", match] if count is not None: args += ["COUNT", str(count)] return cast( - List[Union[str, List[str]]], + List[Union[bytes, List[bytes]]], await self._execute_command(RequestType.HScan, args), ) async def fcall( self, - function: str, - keys: Optional[List[str]] = None, - arguments: Optional[List[str]] = None, + function: TEncodable, + keys: Optional[List[TEncodable]] = None, + arguments: Optional[List[TEncodable]] = None, ) -> TResult: """ Invokes a previously loaded function. See https://redis.io/commands/fcall/ for more details. - When in cluster mode, all keys in `keys` must map to the same hash slot. - Args: - function (str): The function name. - keys (Optional[List[str]]): A list of keys accessed by the function. To ensure the correct + function (TEncodable): The function name. + keys (Optional[List[TEncodable]]): A list of keys accessed by the function. To ensure the correct execution of functions, both in standalone and clustered deployments, all names of keys that a function accesses must be explicitly provided as `keys`. - arguments (Optional[List[str]]): A list of `function` arguments. `Arguments` + arguments (Optional[List[TEncodable]]): A list of `function` arguments. `Arguments` should not represent names of keys. - Returns: TResult: The invoked function's return value. - Example: >>> await client.fcall("Deep_Thought") - 'new_value' # Returns the function's return value. - + b'new_value' # Returns the function's return value. Since: Redis version 7.0.0. """ - args = [] + args: List[TEncodable] = [] if keys is not None: args.extend([function, str(len(keys))] + keys) else: @@ -5744,9 +5830,9 @@ async def fcall( async def fcall_ro( self, - function: str, - keys: Optional[List[str]] = None, - arguments: Optional[List[str]] = None, + function: TEncodable, + keys: Optional[List[TEncodable]] = None, + arguments: Optional[List[TEncodable]] = None, ) -> TResult: """ Invokes a previously loaded read-only function. @@ -5756,11 +5842,11 @@ async def fcall_ro( When in cluster mode, all keys in `keys` must map to the same hash slot. Args: - function (str): The function name. - keys (List[str]): An `array` of keys accessed by the function. To ensure the correct + function (TEncodable): The function name. + keys (List[TEncodable]): An `array` of keys accessed by the function. To ensure the correct execution of functions, all names of keys that a function accesses must be explicitly provided as `keys`. - arguments (List[str]): An `array` of `function` arguments. `arguments` should not + arguments (List[TEncodable]): An `array` of `function` arguments. `arguments` should not represent names of keys. Returns: @@ -5773,7 +5859,7 @@ async def fcall_ro( Since: Redis version 7.0.0. """ - args = [] + args: List[TEncodable] = [] if keys is not None: args.extend([function, str(len(keys))] + keys) else: @@ -5785,7 +5871,7 @@ async def fcall_ro( await self._execute_command(RequestType.FCallReadOnly, args), ) - async def watch(self, keys: List[str]) -> TOK: + async def watch(self, keys: List[TEncodable]) -> TOK: """ Marks the given keys to be watched for conditional execution of a transaction. Transactions will only execute commands if the watched keys are not modified before execution of the @@ -5797,7 +5883,7 @@ async def watch(self, keys: List[str]) -> TOK: When in cluster mode, the command may route to multiple nodes when `keys` map to different hash slots. Args: - keys (List[str]): The keys to watch. + keys (List[TEncodable]): The keys to watch. Returns: TOK: A simple "OK" response. @@ -5829,14 +5915,14 @@ class PubSubMsg: Describes the incoming pubsub message Attributes: - message (str): Incoming message. - channel (str): Name of an channel that triggered the message. - pattern (Optional[str]): Pattern that triggered the message. + message (TEncodable): Incoming message. + channel (TEncodable): Name of an channel that triggered the message. + pattern (Optional[TEncodable]): Pattern that triggered the message. """ - message: str - channel: str - pattern: Optional[str] + message: TEncodable + channel: TEncodable + pattern: Optional[TEncodable] async def get_pubsub_message(self) -> PubSubMsg: """ @@ -5874,9 +5960,9 @@ def try_get_pubsub_message(self) -> Optional[PubSubMsg]: async def lcs( self, - key1: str, - key2: str, - ) -> str: + key1: TEncodable, + key2: TEncodable, + ) -> bytes: """ Returns the longest common subsequence between strings stored at key1 and key2. @@ -5889,32 +5975,32 @@ async def lcs( See https://valkey.io/commands/lcs for more details. Args: - key1 (str): The key that stores the first string. - key2 (str): The key that stores the second string. + key1 (TEncodable): The key that stores the first string. + key2 (TEncodable): The key that stores the second string. Returns: - A String containing the longest common subsequence between the 2 strings. + A Bytes String containing the longest common subsequence between the 2 strings. An empty String is returned if the keys do not exist or have no common subsequences. Examples: >>> await client.mset({"testKey1" : "abcd", "testKey2": "axcd"}) - 'OK' + b'OK' >>> await client.lcs("testKey1", "testKey2") - 'acd' + b'acd' Since: Redis version 7.0.0. """ - args = [key1, key2] + args: List[TEncodable] = [key1, key2] return cast( - str, + bytes, await self._execute_command(RequestType.LCS, args), ) async def lcs_len( self, - key1: str, - key2: str, + key1: TEncodable, + key2: TEncodable, ) -> int: """ Returns the length of the longest common subsequence between strings stored at key1 and key2. @@ -5928,8 +6014,8 @@ async def lcs_len( See https://valkey.io/commands/lcs for more details. Args: - key1 (str): The key that stores the first string. - key2 (str): The key that stores the second string. + key1 (TEncodable): The key that stores the first string value. + key2 (TEncodable): The key that stores the second string value. Returns: The length of the longest common subsequence between the 2 strings. @@ -5938,11 +6024,11 @@ async def lcs_len( >>> await client.mset({"testKey1" : "abcd", "testKey2": "axcd"}) 'OK' >>> await client.lcs_len("testKey1", "testKey2") - 3 # the length of the longest common subsequence between these 2 strings ("acd") is 3. + 3 # the length of the longest common subsequence between these 2 strings (b"acd") is 3. Since: Redis version 7.0.0. """ - args = [key1, key2, "LEN"] + args: List[TEncodable] = [key1, key2, "LEN"] return cast( int, @@ -5951,11 +6037,11 @@ async def lcs_len( async def lcs_idx( self, - key1: str, - key2: str, + key1: TEncodable, + key2: TEncodable, min_match_len: Optional[int] = None, with_match_len: Optional[bool] = False, - ) -> Mapping[str, Union[list[list[Union[list[int], int]]], int]]: + ) -> Mapping[bytes, Union[list[list[Union[list[int], int]]], int]]: """ Returns the indices and length of the longest common subsequence between strings stored at key1 and key2. @@ -5968,8 +6054,8 @@ async def lcs_idx( See https://valkey.io/commands/lcs for more details. Args: - key1 (str): The key that stores the first string. - key2 (str): The key that stores the second string. + key1 (TEncodable): The key that stores the first string value. + key2 (TEncodable): The key that stores the second string value. min_match_len (Optional[int]): The minimum length of matches to include in the result. with_match_len (Optional[bool]): If True, include the length of the substring matched for each substring. @@ -5987,49 +6073,49 @@ async def lcs_idx( 'OK' >>> await client.lcs_idx("testKey1", "testKey2") { - 'matches': [ + b'matches': [ [ - [4, 7], # starting and ending indices of the subsequence "1234" in "abcd1234" (testKey1) - [5, 8], # starting and ending indices of the subsequence "1234" in "bcdef1234" (testKey2) + [4, 7], # starting and ending indices of the subsequence b"1234" in b"abcd1234" (testKey1) + [5, 8], # starting and ending indices of the subsequence b"1234" in b"bcdef1234" (testKey2) ], [ - [1, 3], # starting and ending indices of the subsequence "bcd" in "abcd1234" (testKey1) - [0, 2], # starting and ending indices of the subsequence "bcd" in "bcdef1234" (testKey2) + [1, 3], # starting and ending indices of the subsequence b"bcd" in b"abcd1234" (testKey1) + [0, 2], # starting and ending indices of the subsequence b"bcd" in b"bcdef1234" (testKey2) ], ], - 'len': 7 # length of the entire longest common subsequence + b'len': 7 # length of the entire longest common subsequence } >>> await client.lcs_idx("testKey1", "testKey2", min_match_len=4) { - 'matches': [ + b'matches': [ [ [4, 7], [5, 8], ], # the other match with a length of 3 is excluded ], - 'len': 7 + b'len': 7 } >>> await client.lcs_idx("testKey1", "testKey2", with_match_len=True) { - 'matches': [ + b'matches': [ [ [4, 7], [5, 8], - 4, # length of this match ("1234") + 4, # length of this match (b"1234") ], [ [1, 3], [0, 2], - 3, # length of this match ("bcd") + 3, # length of this match (b"bcd") ], ], - 'len': 7 + b'len': 7 } Since: Redis version 7.0.0. """ - args = [key1, key2, "IDX"] + args: List[TEncodable] = [key1, key2, "IDX"] if min_match_len is not None: args.extend(["MINMATCHLEN", str(min_match_len)]) @@ -6038,14 +6124,14 @@ async def lcs_idx( args.append("WITHMATCHLEN") return cast( - Mapping[str, Union[list[list[Union[list[int], int]]], int]], + Mapping[bytes, Union[list[list[Union[list[int], int]]], int]], await self._execute_command(RequestType.LCS, args), ) async def lpos( self, - key: str, - element: str, + key: TEncodable, + element: TEncodable, rank: Optional[int] = None, count: Optional[int] = None, max_len: Optional[int] = None, @@ -6057,8 +6143,8 @@ async def lpos( See https://valkey.io/commands/lpos for more details. Args: - key (str): The name of the list. - element (str): The value to search for within the list. + key (TEncodable): The name of the list. + element (TEncodable): The value to search for within the list. rank (Optional[int]): The rank of the match to return. count (Optional[int]): The number of matches wanted. A `count` of 0 returns all the matches. max_len (Optional[int]): The maximum number of comparisons to make between the element and the items @@ -6084,7 +6170,7 @@ async def lpos( Since: Redis version 6.0.6. """ - args = [key, element] + args: List[TEncodable] = [key, element] if rank is not None: args.extend(["RANK", str(rank)]) diff --git a/python/python/glide/async_commands/redis_modules/json.py b/python/python/glide/async_commands/redis_modules/json.py index 5ed6d96302..3a2a5691a2 100644 --- a/python/python/glide/async_commands/redis_modules/json.py +++ b/python/python/glide/async_commands/redis_modules/json.py @@ -11,14 +11,14 @@ 'OK' # Indicates successful setting of the value at path '$' in the key stored at `doc`. >>> json_get = await redisJson.get(client, "doc", "$") # Returns the value at path '$' in the JSON document stored at `doc` as JSON string. >>> print(json_get) - "[{\"a\":1.0,\"b\":2}]" - >>> json.loads(json_get) + b"[{\"a\":1.0,\"b\":2}]" + >>> json.loads(str(json_get)) [{"a": 1.0, "b" :2}] # JSON object retrieved from the key `doc` using json.loads() """ from typing import List, Optional, Union, cast from glide.async_commands.core import ConditionalChange -from glide.constants import TOK, TJsonResponse +from glide.constants import TOK, TEncodable, TJsonResponse from glide.glide_client import TGlideClient from glide.protobuf.redis_request_pb2 import RequestType @@ -56,9 +56,9 @@ def get_options(self) -> List[str]: async def set( client: TGlideClient, - key: str, - path: str, - value: str, + key: TEncodable, + path: TEncodable, + value: TEncodable, set_condition: Optional[ConditionalChange] = None, ) -> Optional[TOK]: """ @@ -68,10 +68,10 @@ async def set( Args: client (TGlideClient): The Redis client to execute the command. - key (str): The key of the JSON document. - path (str): Represents the path within the JSON document where the value will be set. + key (TEncodable): The key of the JSON document. + path (TEncodable): Represents the path within the JSON document where the value will be set. The key will be modified only if `value` is added as the last child in the specified `path`, or if the specified `path` acts as the parent of a new child being added. - value (set): The value to set at the specific path, in JSON formatted str. + value (TEncodable): The value to set at the specific path, in JSON formatted bytes or str. set_condition (Optional[ConditionalChange]): Set the value only if the given condition is met (within the key or path). Equivalent to [`XX` | `NX`] in the Redis API. Defaults to None. @@ -96,10 +96,10 @@ async def set( async def get( client: TGlideClient, - key: str, - paths: Optional[Union[str, List[str]]] = None, + key: TEncodable, + paths: Optional[Union[TEncodable, List[TEncodable]]] = None, options: Optional[JsonGetOptions] = None, -) -> Optional[str]: +) -> Optional[bytes]: """ Retrieves the JSON value at the specified `paths` stored at `key`. @@ -107,42 +107,42 @@ async def get( Args: client (TGlideClient): The Redis client to execute the command. - key (str): The key of the JSON document. - paths (Optional[Union[str, List[str]]]): The path or list of paths within the JSON document. Default is root `$`. - options (Optional[JsonGetOptions]): Options for formatting the string representation of the JSON data. See `JsonGetOptions`. + key (TEncodable): The key of the JSON document. + paths (Optional[Union[TEncodable, List[TEncodable]]]): The path or list of paths within the JSON document. Default is root `$`. + options (Optional[JsonGetOptions]): Options for formatting the byte representation of the JSON data. See `JsonGetOptions`. Returns: - str: A bulk string representation of the returned value. + bytes: A bytes representation of the returned value. If `key` doesn't exists, returns None. Examples: >>> from glide import json as redisJson >>> import json >>> json_str = await redisJson.get(client, "doc", "$") - >>> json.loads(json_str) # Parse JSON string to Python data + >>> json.loads(str(json_str)) # Parse JSON string to Python data [{"a": 1.0, "b" :2}] # JSON object retrieved from the key `doc` using json.loads() >>> await redisJson.get(client, "doc", "$") - "[{\"a\":1.0,\"b\":2}]" # Returns the value at path '$' in the JSON document stored at `doc`. + b"[{\"a\":1.0,\"b\":2}]" # Returns the value at path '$' in the JSON document stored at `doc`. >>> await redisJson.get(client, "doc", ["$.a", "$.b"], json.JsonGetOptions(indent=" ", newline="\n", space=" ")) - "{\n \"$.a\": [\n 1.0\n ],\n \"$.b\": [\n 2\n ]\n}" # Returns the values at paths '$.a' and '$.b' in the JSON document stored at `doc`, with specified formatting options. + b"{\n \"$.a\": [\n 1.0\n ],\n \"$.b\": [\n 2\n ]\n}" # Returns the values at paths '$.a' and '$.b' in the JSON document stored at `doc`, with specified formatting options. >>> await redisJson.get(client, "doc", "$.non_existing_path") - "[]" # Returns an empty array since the path '$.non_existing_path' does not exist in the JSON document stored at `doc`. + b"[]" # Returns an empty array since the path '$.non_existing_path' does not exist in the JSON document stored at `doc`. """ args = ["JSON.GET", key] if options: args.extend(options.get_options()) if paths: - if isinstance(paths, str): + if isinstance(paths, (str, bytes)): paths = [paths] args.extend(paths) - return cast(str, await client.custom_command(args)) + return cast(bytes, await client.custom_command(args)) async def delete( client: TGlideClient, - key: str, - path: Optional[str] = None, + key: TEncodable, + path: Optional[TEncodable] = None, ) -> int: """ Deletes the JSON value at the specified `path` within the JSON document stored at `key`. @@ -151,8 +151,8 @@ async def delete( Args: client (TGlideClient): The Redis client to execute the command. - key (str): The key of the JSON document. - path (Optional[str]): Represents the path within the JSON document where the value will be deleted. + key (TEncodable): The key of the JSON document. + path (Optional[TEncodable]): Represents the path within the JSON document where the value will be deleted. If None, deletes the entire JSON document at `key`. Defaults to None. Returns: @@ -178,8 +178,8 @@ async def delete( async def forget( client: TGlideClient, - key: str, - path: Optional[str] = None, + key: TEncodable, + path: Optional[TEncodable] = None, ) -> Optional[int]: """ Deletes the JSON value at the specified `path` within the JSON document stored at `key`. @@ -188,8 +188,8 @@ async def forget( Args: client (TGlideClient): The Redis client to execute the command. - key (str): The key of the JSON document. - path (Optional[str]): Represents the path within the JSON document where the value will be deleted. + key (TEncodable): The key of the JSON document. + path (Optional[TEncodable]): Represents the path within the JSON document where the value will be deleted. If None, deletes the entire JSON document at `key`. Defaults to None. Returns: @@ -216,8 +216,8 @@ async def forget( async def toggle( client: TGlideClient, - key: str, - path: str, + key: TEncodable, + path: TEncodable, ) -> TJsonResponse[bool]: """ Toggles a Boolean value stored at the specified `path` within the JSON document stored at `key`. @@ -226,8 +226,8 @@ async def toggle( Args: client (TGlideClient): The Redis client to execute the command. - key (str): The key of the JSON document. - path (str): The JSONPath to specify. + key (TEncodable): The key of the JSON document. + path (TEncodable): The JSONPath to specify. Returns: TJsonResponse[bool]: For JSONPath (`path` starts with `$`), returns a list of boolean replies for every possible path, with the toggled boolean value, diff --git a/python/python/glide/async_commands/sorted_set.py b/python/python/glide/async_commands/sorted_set.py index 2fa7d851f9..4a86aa3d11 100644 --- a/python/python/glide/async_commands/sorted_set.py +++ b/python/python/glide/async_commands/sorted_set.py @@ -1,9 +1,10 @@ # Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 from enum import Enum -from typing import List, Optional, Tuple, Union +from typing import List, Optional, Tuple, Union, cast from glide.async_commands.command_args import Limit, OrderBy +from glide.constants import TEncodable class InfBound(Enum): @@ -278,12 +279,12 @@ def to_args(self) -> List[str]: def _create_zrange_args( - key: str, + key: TEncodable, range_query: Union[RangeByLex, RangeByScore, RangeByIndex], reverse: bool, with_scores: bool, - destination: Optional[str] = None, -) -> List[str]: + destination: Optional[TEncodable] = None, +) -> List[TEncodable]: args = [destination] if destination else [] args += [key, str(range_query.start), str(range_query.stop)] @@ -308,32 +309,35 @@ def _create_zrange_args( def separate_keys( - keys: Union[List[str], List[Tuple[str, float]]] -) -> Tuple[List[str], List[str]]: + keys: Union[List[TEncodable], List[Tuple[TEncodable, float]]] +) -> Tuple[List[TEncodable], List[TEncodable]]: """ - Returns seperate lists of keys and weights in case of weighted keys. + Returns separate lists of keys and weights in case of weighted keys. """ if not keys: return [], [] - key_list: List[str] = [] - weight_list: List[str] = [] + key_list: List[TEncodable] = [] + weight_list: List[TEncodable] = [] if isinstance(keys[0], tuple): - key_list = [item[0] for item in keys] - weight_list = [str(item[1]) for item in keys] + for item in keys: + key = item[0] + weight = item[1] + key_list.append(cast(TEncodable, key)) + weight_list.append(cast(TEncodable, str(weight))) else: - key_list = keys # type: ignore + key_list.extend(cast(List[TEncodable], keys)) return key_list, weight_list def _create_zinter_zunion_cmd_args( - keys: Union[List[str], List[Tuple[str, float]]], + keys: Union[List[TEncodable], List[Tuple[TEncodable, float]]], aggregation_type: Optional[AggregationType] = None, - destination: Optional[str] = None, -) -> List[str]: - args = [] + destination: Optional[TEncodable] = None, +) -> List[TEncodable]: + args: List[TEncodable] = [] if destination: args.append(destination) @@ -342,11 +346,11 @@ def _create_zinter_zunion_cmd_args( only_keys, weights = separate_keys(keys) - args += only_keys + args.extend(only_keys) if weights: args.append("WEIGHTS") - args += weights + args.extend(weights) if aggregation_type: args.append("AGGREGATE") @@ -356,27 +360,29 @@ def _create_zinter_zunion_cmd_args( def _create_geosearch_args( - keys: List[str], - search_from: Union[str, GeospatialData], - seach_by: Union[GeoSearchByRadius, GeoSearchByBox], + keys: List[TEncodable], + search_from: Union[str, bytes, GeospatialData], + search_by: Union[GeoSearchByRadius, GeoSearchByBox], order_by: Optional[OrderBy] = None, count: Optional[GeoSearchCount] = None, with_coord: bool = False, with_dist: bool = False, with_hash: bool = False, store_dist: bool = False, -) -> List[str]: - args = keys - if isinstance(search_from, str): - args += ["FROMMEMBER", search_from] +) -> List[TEncodable]: + args: List[TEncodable] = keys + if isinstance(search_from, str | bytes): + args.extend(["FROMMEMBER", search_from]) else: - args += [ - "FROMLONLAT", - str(search_from.longitude), - str(search_from.latitude), - ] + args.extend( + [ + "FROMLONLAT", + str(search_from.longitude), + str(search_from.latitude), + ] + ) - args += seach_by.to_args() + args.extend(search_by.to_args()) if order_by: args.append(order_by.value) diff --git a/python/python/glide/async_commands/standalone_commands.py b/python/python/glide/async_commands/standalone_commands.py index 4c0ee234aa..76851ab2c6 100644 --- a/python/python/glide/async_commands/standalone_commands.py +++ b/python/python/glide/async_commands/standalone_commands.py @@ -12,12 +12,12 @@ _build_sort_args, ) from glide.async_commands.transaction import BaseTransaction, Transaction -from glide.constants import OK, TOK, TResult +from glide.constants import OK, TOK, TEncodable, TResult from glide.protobuf.redis_request_pb2 import RequestType class StandaloneCommands(CoreCommands): - async def custom_command(self, command_args: List[str]) -> TResult: + async def custom_command(self, command_args: List[TEncodable]) -> TResult: """ Executes a single command, without checking inputs. See the [Glide for Redis Wiki](https://github.com/aws/glide-for-redis/wiki/General-Concepts#custom-command) @@ -27,7 +27,7 @@ async def custom_command(self, command_args: List[str]) -> TResult: connection.customCommand(["CLIENT", "LIST","TYPE", "PUBSUB"]) Args: - command_args (List[str]): List of strings of the command's arguments. + command_args (List[TEncodable]): List of the command's arguments, where each argument is either a string or bytes. Every part of the command, including the command name and subcommands, should be added as a separate value in args. Returns: @@ -51,7 +51,9 @@ async def info( Returns: bytes: Returns bytes containing the information for the sections requested. """ - args = [section.value for section in sections] if sections else [] + args: List[TEncodable] = ( + [section.value for section in sections] if sections else [] + ) return cast(bytes, await self._execute_command(RequestType.Info, args)) async def exec( @@ -119,57 +121,56 @@ async def client_id( """ return cast(int, await self._execute_command(RequestType.ClientId, [])) - async def ping(self, message: Optional[str] = None) -> str: + async def ping(self, message: Optional[TEncodable] = None) -> bytes: """ Ping the Redis server. See https://redis.io/commands/ping/ for more details. Args: - message (Optional[str]): An optional message to include in the PING command. If not provided, - the server will respond with "PONG". If provided, the server will respond with a copy of the message. + message (Optional[TEncodable]): An optional message to include in the PING command. If not provided, + the server will respond with b"PONG". If provided, the server will respond with a copy of the message. Returns: - str: "PONG" if `message` is not provided, otherwise return a copy of `message`. + bytes: b"PONG" if `message` is not provided, otherwise return a copy of `message`. Examples: >>> await client.ping() - "PONG" + b"PONG" >>> await client.ping("Hello") - "Hello" + b"Hello" """ argument = [] if message is None else [message] - return cast(str, await self._execute_command(RequestType.Ping, argument)) + return cast(bytes, await self._execute_command(RequestType.Ping, argument)) - async def config_get(self, parameters: List[str]) -> Dict[str, str]: + async def config_get(self, parameters: List[TEncodable]) -> Dict[bytes, bytes]: """ Get the values of configuration parameters. See https://redis.io/commands/config-get/ for details. Args: - parameters (List[str]): A list of configuration parameter names to retrieve values for. + parameters (List[TEncodable]): A list of configuration parameter names to retrieve values for. Returns: - Dict[str, str]: A dictionary of values corresponding to the configuration parameters. + Dict[bytes, bytes]: A dictionary of values corresponding to the configuration parameters. Examples: >>> await client.config_get(["timeout"] , RandomNode()) - {'timeout': '1000'} - >>> await client.config_get(["timeout" , "maxmemory"]) - {'timeout': '1000', "maxmemory": "1GB"} - + {b'timeout': b'1000'} + >>> await client.config_get([b"timeout" , "maxmemory"]) + {b'timeout': b'1000', b'maxmemory': b'1GB'} """ return cast( - Dict[str, str], + Dict[bytes, bytes], await self._execute_command(RequestType.ConfigGet, parameters), ) - async def config_set(self, parameters_map: Mapping[str, str]) -> TOK: + async def config_set(self, parameters_map: Mapping[TEncodable, TEncodable]) -> TOK: """ Set configuration parameters to the specified values. See https://redis.io/commands/config-set/ for details. Args: - parameters_map (Mapping[str, str]): A map consisting of configuration + parameters_map (Mapping[TEncodable, TEncodable]): A map consisting of configuration parameters and their respective values to set. Returns: @@ -177,28 +178,28 @@ async def config_set(self, parameters_map: Mapping[str, str]) -> TOK: Examples: >>> config_set({"timeout": "1000", "maxmemory": "1GB"}) - OK + OK """ - parameters: List[str] = [] + parameters: List[TEncodable] = [] for pair in parameters_map.items(): parameters.extend(pair) return cast(TOK, await self._execute_command(RequestType.ConfigSet, parameters)) - async def client_getname(self) -> Optional[str]: + async def client_getname(self) -> Optional[bytes]: """ Get the name of the primary's connection. See https://redis.io/commands/client-getname/ for more details. Returns: - Optional[str]: Returns the name of the client connection as a string if a name is set, + Optional[bytes]: Returns the name of the client connection as a byte string if a name is set, or None if no name is assigned. Examples: >>> await client.client_getname() - 'Connection Name' + b'Connection Name' """ return cast( - Optional[str], await self._execute_command(RequestType.ClientGetName, []) + Optional[bytes], await self._execute_command(RequestType.ClientGetName, []) ) async def dbsize(self) -> int: @@ -215,47 +216,49 @@ async def dbsize(self) -> int: """ return cast(int, await self._execute_command(RequestType.DBSize, [])) - async def echo(self, message: str) -> str: + async def echo(self, message: TEncodable) -> bytes: """ Echoes the provided `message` back. See https://redis.io/commands/echo for more details. Args: - message (str): The message to be echoed back. + message (TEncodable): The message to be echoed back. Returns: - str: The provided `message`. + bytes: The provided `message`. Examples: >>> await client.echo("Glide-for-Redis") - 'Glide-for-Redis' + b'Glide-for-Redis' """ - return cast(str, await self._execute_command(RequestType.Echo, [message])) + return cast(bytes, await self._execute_command(RequestType.Echo, [message])) - async def function_load(self, library_code: str, replace: bool = False) -> str: + async def function_load( + self, library_code: TEncodable, replace: bool = False + ) -> bytes: """ Loads a library to Redis. See https://valkey.io/docs/latest/commands/function-load/ for more details. Args: - library_code (str): The source code that implements the library. + library_code (TEncodable): The source code that implements the library. replace (bool): Whether the given library should overwrite a library with the same name if it already exists. Returns: - str: The library name that was loaded. + bytes: The library name that was loaded. Examples: >>> code = "#!lua name=mylib \n redis.register_function('myfunc', function(keys, args) return args[1] end)" >>> await client.function_load(code, True) - "mylib" + b"mylib" Since: Redis 7.0.0. """ return cast( - str, + bytes, await self._execute_command( RequestType.FunctionLoad, ["REPLACE", library_code] if replace else [library_code], @@ -288,14 +291,14 @@ async def function_flush(self, mode: Optional[FlushMode] = None) -> TOK: ), ) - async def function_delete(self, library_name: str) -> TOK: + async def function_delete(self, library_name: TEncodable) -> TOK: """ Deletes a library and all its functions. See https://valkey.io/docs/latest/commands/function-delete/ for more details. Args: - library_code (str): The libary name to delete + library_code (TEncodable): The library name to delete Returns: TOK: A simple `OK`. @@ -314,23 +317,23 @@ async def function_delete(self, library_name: str) -> TOK: ), ) - async def time(self) -> List[str]: + async def time(self) -> List[bytes]: """ Returns the server time. See https://redis.io/commands/time/ for more details. Returns: - List[str]: The current server time as a two items `array`: + List[bytes]: The current server time as a two items `array`: A Unix timestamp and the amount of microseconds already elapsed in the current second. The returned `array` is in a [Unix timestamp, Microseconds already elapsed] format. Examples: >>> await client.time() - ['1710925775', '913580'] + [b'1710925775', b'913580'] """ return cast( - List[str], + List[bytes], await self._execute_command(RequestType.Time, []), ) @@ -345,21 +348,21 @@ async def lastsave(self) -> int: Examples: >>> await client.lastsave() - 1710925775 # Unix time of the last DB save + 1710925775 # Unix time of the last DB save """ return cast( int, await self._execute_command(RequestType.LastSave, []), ) - async def move(self, key: str, db_index: int) -> bool: + async def move(self, key: TEncodable, db_index: int) -> bool: """ Move `key` from the currently selected database to the database specified by `db_index`. See https://valkey.io/commands/move/ for more details. Args: - key (str): The key to move. + key (TEncodable): The key to move. db_index (int): The index of the database to move `key` to. Returns: @@ -377,13 +380,13 @@ async def move(self, key: str, db_index: int) -> bool: async def sort( self, - key: str, - by_pattern: Optional[str] = None, + key: TEncodable, + by_pattern: Optional[TEncodable] = None, limit: Optional[Limit] = None, - get_patterns: Optional[List[str]] = None, + get_patterns: Optional[List[TEncodable]] = None, order: Optional[OrderBy] = None, alpha: Optional[bool] = None, - ) -> List[Optional[str]]: + ) -> List[Optional[bytes]]: """ 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. @@ -392,8 +395,8 @@ async def sort( See https://valkey.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 external keys instead of by the elements stored at the key themselves. + key (TEncodable): The key of the list, set, or sorted set to be sorted. + by_pattern (Optional[TEncodable]): 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 @@ -402,7 +405,7 @@ async def sort( 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_pattern (Optional[str]): A pattern used to retrieve external keys' values, instead of the elements at `key`. + get_patterns (Optional[List[TEncodable]]): 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` @@ -417,34 +420,34 @@ async def sort( 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. + List[Optional[bytes]]: Returns a list of sorted elements. Examples: - >>> await client.lpush("mylist", 3, 1, 2) + >>> await client.lpush("mylist", [b"3", b"1", b"2"]) >>> await client.sort("mylist") - ['1', '2', '3'] + [b'1', b'2', b'3'] >>> await client.sort("mylist", order=OrderBy.DESC) - ['3', '2', '1'] - >>> await client.lpush("mylist2", 2, 1, 2, 3, 3, 1) + [b'3', b'2', b'1'] + >>> 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) - >>> await client.lpush("user_ids", 2, 1) + [b'2', b'2', b'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'] + [b'Bob', b'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) + return cast(List[Optional[bytes]], result) async def sort_store( self, - key: str, - destination: str, - by_pattern: Optional[str] = None, + key: TEncodable, + destination: TEncodable, + by_pattern: Optional[TEncodable] = None, limit: Optional[Limit] = None, - get_patterns: Optional[List[str]] = None, + get_patterns: Optional[List[TEncodable]] = None, order: Optional[OrderBy] = None, alpha: Optional[bool] = None, ) -> int: @@ -456,9 +459,9 @@ async def sort_store( See https://valkey.io/commands/sort for more details. 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. + key (TEncodable): The key of the list, set, or sorted set to be sorted. + destination (TEncodable): The key where the sorted result will be stored. + by_pattern (Optional[TEncodable]): 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 @@ -467,7 +470,7 @@ async def sort_store( 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_pattern (Optional[str]): A pattern used to retrieve external keys' values, instead of the elements at `key`. + get_patterns (Optional[List[TEncodable]]): 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` @@ -485,11 +488,11 @@ async def sort_store( int: The number of elements in the sorted key stored at `store`. Examples: - >>> await client.lpush("mylist", 3, 1, 2) + >>> 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. + 3 # Indicates that the sorted list "sorted_list" contains three elements. >>> await client.lrange("sorted_list", 0, -1) - ['1', '2', '3'] + [b'1', b'2', b'3'] """ args = _build_sort_args( key, by_pattern, limit, get_patterns, order, alpha, store=destination @@ -497,14 +500,14 @@ async def sort_store( result = await self._execute_command(RequestType.Sort, args) return cast(int, result) - async def publish(self, message: str, channel: str) -> int: + async def publish(self, message: TEncodable, channel: TEncodable) -> int: """ Publish a message on pubsub channel. See https://valkey.io/commands/publish for more details. Args: - message (str): Message to publish - channel (str): Channel to publish the message on. + message (TEncodable): Message to publish + channel (TEncodable): Channel to publish the message on. Returns: int: Number of subscriptions in primary node that received the message. @@ -514,8 +517,9 @@ async def publish(self, message: str, channel: str) -> int: >>> await client.publish("Hi all!", "global-channel") 1 # This message was posted to 1 subscription which is configured on primary node """ - result = await self._execute_command(RequestType.Publish, [channel, message]) - return cast(int, result) + return cast( + int, await self._execute_command(RequestType.Publish, [channel, message]) + ) async def flushall(self, flush_mode: Optional[FlushMode] = None) -> TOK: """ @@ -527,13 +531,13 @@ async def flushall(self, flush_mode: Optional[FlushMode] = None) -> TOK: flush_mode (Optional[FlushMode]): The flushing mode, could be either `SYNC` or `ASYNC`. Returns: - TOK: OK. + TOK: A simple OK response. Examples: - >>> await client.flushall(FlushMode.ASYNC) - OK # This command never fails. + >>> await client.flushall(FlushMode.ASYNC) + OK # This command never fails. """ - args = [] + args: List[TEncodable] = [] if flush_mode is not None: args.append(flush_mode.value) @@ -552,15 +556,15 @@ async def flushdb(self, flush_mode: Optional[FlushMode] = None) -> TOK: flush_mode (Optional[FlushMode]): The flushing mode, could be either `SYNC` or `ASYNC`. Returns: - TOK: OK. + TOK: A simple OK response. Examples: - >>> await client.flushdb() - OK # The keys of the currently selected database were deleted. - >>> await client.flushdb(FlushMode.ASYNC) - OK # The keys of the currently selected database were deleted asynchronously. + >>> await client.flushdb() + OK # The keys of the currently selected database were deleted. + >>> await client.flushdb(FlushMode.ASYNC) + OK # The keys of the currently selected database were deleted asynchronously. """ - args = [] + args: List[TEncodable] = [] if flush_mode is not None: args.append(flush_mode.value) @@ -571,8 +575,8 @@ async def flushdb(self, flush_mode: Optional[FlushMode] = None) -> TOK: async def copy( self, - source: str, - destination: str, + source: TEncodable, + destination: TEncodable, destinationDB: Optional[int] = None, replace: Optional[bool] = None, ) -> bool: @@ -585,8 +589,8 @@ async def copy( See https://valkey.io/commands/copy for more details. Args: - source (str): The key to the source value. - destination (str): The key where the value should be copied to. + source (TEncodable): The key to the source value. + destination (TEncodable): The key where the value should be copied to. destinationDB (Optional[int]): The alternative logical database index for the destination key. replace (Optional[bool]): If the destination key should be removed before copying the value to it. @@ -595,15 +599,15 @@ async def copy( Examples: >>> await client.set("source", "sheep") - >>> await client.copy("source", "destination", 1, False) + >>> await client.copy(b"source", b"destination", 1, False) True # Source was copied >>> await client.select(1) >>> await client.get("destination") - "sheep" + b"sheep" Since: Redis version 6.2.0. """ - args = [source, destination] + args: List[TEncodable] = [source, destination] if destinationDB is not None: args.extend(["DB", str(destinationDB)]) if replace is True: @@ -617,7 +621,7 @@ async def lolwut( self, version: Optional[int] = None, parameters: Optional[List[int]] = None, - ) -> str: + ) -> bytes: """ Displays a piece of generative computer art and the Redis version. @@ -630,40 +634,40 @@ async def lolwut( For version `6`, those are number of columns and number of lines. Returns: - str: A piece of generative computer art along with the current Redis version. + bytes: A piece of generative computer art along with the current Redis version. Examples: >>> await client.lolwut(6, [40, 20]); - "Redis ver. 7.2.3" # Indicates the current Redis version + b"Redis ver. 7.2.3" # Indicates the current Redis version >>> await client.lolwut(5, [30, 5, 5]); - "Redis ver. 7.2.3" # Indicates the current Redis version + b"Redis ver. 7.2.3" # Indicates the current Redis version """ - args = [] + args: List[TEncodable] = [] if version is not None: args.extend(["VERSION", str(version)]) if parameters: for var in parameters: args.extend(str(var)) return cast( - str, + bytes, await self._execute_command(RequestType.Lolwut, args), ) - async def random_key(self) -> Optional[str]: + async def random_key(self) -> Optional[bytes]: """ Returns a random existing key name from the currently selected database. See https://valkey.io/commands/randomkey for more details. Returns: - Optional[str]: A random existing key name from the currently selected database. + Optional[bytes]: A random existing key name from the currently selected database. Examples: >>> await client.random_key() - "random_key_name" # "random_key_name" is a random existing key name from the currently selected database. + b"random_key_name" # "random_key_name" is a random existing key name from the currently selected database. """ return cast( - Optional[str], + Optional[bytes], await self._execute_command(RequestType.RandomKey, []), ) @@ -691,7 +695,7 @@ async def wait( >>> await client.wait(1, 1000); // return 1 when a replica is reached or 0 if 1000ms is reached. """ - args = [str(numreplicas), str(timeout)] + args: List[TEncodable] = [str(numreplicas), str(timeout)] return cast( int, await self._execute_command(RequestType.Wait, args), diff --git a/python/python/glide/async_commands/stream.py b/python/python/glide/async_commands/stream.py index 8a25337066..4eff0ab2b4 100644 --- a/python/python/glide/async_commands/stream.py +++ b/python/python/glide/async_commands/stream.py @@ -4,6 +4,8 @@ from abc import ABC, abstractmethod from typing import List, Optional, Union +from glide.constants import TEncodable + class StreamTrimOptions(ABC): """ @@ -14,7 +16,7 @@ class StreamTrimOptions(ABC): def __init__( self, exact: bool, - threshold: Union[str, int], + threshold: Union[TEncodable, int], method: str, limit: Optional[int] = None, ): @@ -24,7 +26,7 @@ def __init__( Args: exact (bool): If `true`, the stream will be trimmed exactly. Otherwise the stream will be trimmed in a near-exact manner, which is more efficient. - threshold (Union[str, int]): Threshold for trimming. + threshold (Union[TEncodable, int]): Threshold for trimming. method (str): Method for trimming (e.g., MINID, MAXLEN). limit (Optional[int]): Max number of entries to be trimmed. Defaults to None. Note: If `exact` is set to `True`, `limit` cannot be specified. @@ -60,14 +62,14 @@ class TrimByMinId(StreamTrimOptions): Stream trim option to trim by minimum ID. """ - def __init__(self, exact: bool, threshold: str, limit: Optional[int] = None): + def __init__(self, exact: bool, threshold: TEncodable, limit: Optional[int] = None): """ Initialize trim option by minimum ID. Args: exact (bool): If `true`, the stream will be trimmed exactly. Otherwise the stream will be trimmed in a near-exact manner, which is more efficient. - threshold (str): Threshold for trimming by minimum ID. + threshold (TEncodable): Threshold for trimming by minimum ID. limit (Optional[int]): Max number of entries to be trimmed. Defaults to None. Note: If `exact` is set to `True`, `limit` cannot be specified. """ @@ -100,7 +102,7 @@ class StreamAddOptions: def __init__( self, - id: Optional[str] = None, + id: Optional[TEncodable] = None, make_stream: bool = True, trim: Optional[StreamTrimOptions] = None, ): @@ -108,7 +110,7 @@ def __init__( Initialize stream add options. Args: - id (Optional[str]): ID for the new entry. If set, the new entry will be added with this ID. If not specified, '*' is used. + id (Optional[TEncodable]): ID for the new entry. If set, the new entry will be added with this ID. If not specified, '*' is used. make_stream (bool, optional): If set to False, a new stream won't be created if no stream matches the given key. trim (Optional[StreamTrimOptions]): If set, the add operation will also trim the older entries in the stream. See `StreamTrimOptions`. """ @@ -116,14 +118,14 @@ def __init__( self.make_stream = make_stream self.trim = trim - def to_args(self) -> List[str]: + def to_args(self) -> List[TEncodable]: """ Convert options to arguments for Redis command. Returns: List[str]: List of arguments for Redis command. """ - option_args = [] + option_args: List[TEncodable] = [] if not self.make_stream: option_args.append("NOMKSTREAM") if self.trim: @@ -140,7 +142,7 @@ class StreamRangeBound(ABC): """ @abstractmethod - def to_arg(self) -> str: + def to_arg(self) -> TEncodable: """ Returns the stream range bound as a string argument to be used in the `XRANGE` or `XREVRANGE` commands. """ @@ -188,7 +190,7 @@ def from_timestamp(timestamp: int) -> IdBound: """ return IdBound(str(timestamp)) - def __init__(self, stream_id: str): + def __init__(self, stream_id: TEncodable): """ Creates a stream ID boundary for a range search. @@ -197,7 +199,7 @@ def __init__(self, stream_id: str): """ self.stream_id = stream_id - def to_arg(self) -> str: + def to_arg(self) -> TEncodable: return self.stream_id @@ -222,16 +224,18 @@ def from_timestamp(timestamp: int) -> ExclusiveIdBound: """ return ExclusiveIdBound(str(timestamp)) - def __init__(self, stream_id: str): + def __init__(self, stream_id: TEncodable): """ Creates a stream ID boundary for a range search. Args: - stream_id (str): The stream ID. + stream_id (TEncodable): The stream ID. """ + if isinstance(stream_id, bytes): + stream_id = stream_id.decode("utf-8") self.stream_id = f"{self.EXCLUSIVE_BOUND_REDIS_API}{stream_id}" - def to_arg(self) -> str: + def to_arg(self) -> TEncodable: return self.stream_id @@ -251,14 +255,14 @@ def __init__(self, block_ms: Optional[int] = None, count: Optional[int] = None): self.block_ms = block_ms self.count = count - def to_args(self) -> List[str]: + def to_args(self) -> List[TEncodable]: """ Returns the options as a list of string arguments to be used in the `XREAD` command. Returns: - List[str]: The options as a list of arguments for the `XREAD` command. + List[TEncodable]: The options as a list of arguments for the `XREAD` command. """ - args = [] + args: List[TEncodable] = [] if self.block_ms is not None: args.extend([self.READ_BLOCK_REDIS_API, str(self.block_ms)]) @@ -273,7 +277,7 @@ class StreamGroupOptions: ENTRIES_READ_REDIS_API = "ENTRIESREAD" def __init__( - self, make_stream: bool = False, entries_read_id: Optional[str] = None + self, make_stream: bool = False, entries_read_id: Optional[TEncodable] = None ): """ Options for creating stream consumer groups. Can be used as an optional argument to `XGROUP CREATE`. @@ -281,21 +285,21 @@ def __init__( Args: make_stream (bool): If set to True and the stream doesn't exist, this creates a new stream with a length of 0. - entries_read_id: (Optional[str]): An arbitrary ID (that isn't the first ID, last ID, or the zero ID ("0-0")) + entries_read_id: (Optional[TEncodable]): An arbitrary ID (that isn't the first ID, last ID, or the zero ID ("0-0")) used to find out how many entries are between the arbitrary ID (excluding it) and the stream's last entry. This option can only be specified if you are using Redis version 7.0.0 or above. """ self.make_stream = make_stream self.entries_read_id = entries_read_id - def to_args(self) -> List[str]: + def to_args(self) -> List[TEncodable]: """ Returns the options as a list of string arguments to be used in the `XGROUP CREATE` command. Returns: - List[str]: The options as a list of arguments for the `XGROUP CREATE` command. + List[TEncodable]: The options as a list of arguments for the `XGROUP CREATE` command. """ - args = [] + args: List[TEncodable] = [] if self.make_stream is True: args.append(self.MAKE_STREAM_REDIS_API) @@ -325,14 +329,14 @@ def __init__( super().__init__(block_ms=block_ms, count=count) self.no_ack = no_ack - def to_args(self) -> List[str]: + def to_args(self) -> List[TEncodable]: """ Returns the options as a list of string arguments to be used in the `XREADGROUP` command. Returns: - List[str]: The options as a list of arguments for the `XREADGROUP` command. + List[TEncodable]: The options as a list of arguments for the `XREADGROUP` command. """ - args = super().to_args() + args: List[TEncodable] = super().to_args() if self.no_ack: args.append(self.READ_NOACK_REDIS_API) @@ -345,7 +349,7 @@ class StreamPendingOptions: def __init__( self, min_idle_time_ms: Optional[int] = None, - consumer_name: Optional[str] = None, + consumer_name: Optional[TEncodable] = None, ): """ Options for `XPENDING` that can be used to filter returned items by minimum idle time and consumer name. @@ -353,20 +357,20 @@ def __init__( Args: min_idle_time_ms (Optional[int]): Filters pending entries by their minimum idle time in milliseconds. This option can only be specified if you are using Redis version 6.2.0 or above. - consumer_name (Optional[str]): Filters pending entries by consumer name. + consumer_name (Optional[TEncodable]): Filters pending entries by consumer name. """ self.min_idle_time = min_idle_time_ms self.consumer_name = consumer_name def _create_xpending_range_args( - key: str, - group_name: str, + key: TEncodable, + group_name: TEncodable, start: StreamRangeBound, end: StreamRangeBound, count: int, options: Optional[StreamPendingOptions], -) -> List[str]: +) -> List[TEncodable]: args = [key, group_name] if options is not None and options.min_idle_time is not None: args.extend([options.IDLE_TIME_REDIS_API, str(options.min_idle_time)]) diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index 3b6d479532..fedf1885c8 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -52,6 +52,7 @@ StreamTrimOptions, _create_xpending_range_args, ) +from glide.constants import TEncodable from glide.protobuf.redis_request_pb2 import RequestType TTransaction = TypeVar("TTransaction", bound="BaseTransaction") @@ -73,11 +74,13 @@ class BaseTransaction: """ def __init__(self) -> None: - self.commands: List[Tuple[RequestType.ValueType, List[str]]] = [] + self.commands: List[Tuple[RequestType.ValueType, List[TEncodable]]] = [] self.lock = threading.Lock() def append_command( - self: TTransaction, request_type: RequestType.ValueType, args: List[str] + self: TTransaction, + request_type: RequestType.ValueType, + args: List[TEncodable], ) -> TTransaction: self.lock.acquire() try: @@ -90,34 +93,36 @@ def clear(self): with self.lock: self.commands.clear() - def get(self: TTransaction, key: str) -> TTransaction: + def get(self: TTransaction, key: TEncodable) -> TTransaction: """ Get the value associated with the given key, or null if no such value exists. See https://redis.io/commands/get/ for details. Args: - key (str): The key to retrieve from the database. + key (TEncodable): The key to retrieve from the database. Command response: - Optional[str]: If the key exists, returns the value of the key as a string. Otherwise, return None. + Optional[bytes]: If the key exists, returns the value of the key as a bytes string. Otherwise, return None. """ return self.append_command(RequestType.Get, [key]) - def getdel(self: TTransaction, key: str) -> TTransaction: + def getdel(self: TTransaction, key: TEncodable) -> TTransaction: """ - Gets a string value associated with the given `key` and deletes the key. + Gets a value associated with the given string `key` and deletes the key. See https://valkey.io/commands/getdel for more details. Args: - key (str): The `key` to retrieve from the database. + key (TEncodable): The `key` to retrieve from the database. Command response: - Optional[str]: If `key` exists, returns the `value` of `key`. Otherwise, returns `None`. + Optional[bytes]: If `key` exists, returns the `value` of `key`. Otherwise, returns `None`. """ return self.append_command(RequestType.GetDel, [key]) - def getrange(self: TTransaction, key: str, start: int, end: int) -> TTransaction: + def getrange( + self: TTransaction, key: TEncodable, start: int, end: int + ) -> TTransaction: """ Returns the substring of the string value stored at `key`, determined by the offsets `start` and `end` (both are inclusive). Negative offsets can be used in order to provide an offset starting from the end of the string. @@ -129,19 +134,19 @@ def getrange(self: TTransaction, key: str, start: int, end: int) -> TTransaction See https://valkey.io/commands/getrange/ for more details. Args: - key (str): The key of the string. + key (TEncodable): The key of the string. start (int): The starting offset. end (int): The ending offset. Commands response: - str: A substring extracted from the value stored at `key`. + bytes: A substring extracted from the value stored at `key`. """ return self.append_command(RequestType.GetRange, [key, str(start), str(end)]) def set( self: TTransaction, - key: str, - value: str, + key: TEncodable, + value: TEncodable, conditional_set: Union[ConditionalChange, None] = None, expiry: Union[ExpirySet, None] = None, return_old_value: bool = False, @@ -155,21 +160,21 @@ def set( connection.set("foo", "bar", conditional_set=ConditionalChange.ONLY_IF_EXISTS, expiry=Expiry(ExpiryType.SEC, 5)) Args: - key (str): the key to store. - value (str): the value to store with the given key. + key (TEncodable): the key to store. + value (TEncodable): the value to store with the given key. conditional_set (Optional[ConditionalChange], optional): set the key only if the given condition is met. Equivalent to [`XX` | `NX`] in the Redis API. Defaults to None. expiry (Optional[ExpirySet], optional): set expiriation to the given key. Equivalent to [`EX` | `PX` | `EXAT` | `PXAT` | `KEEPTTL`] in the Redis API. Defaults to None. - return_old_value (bool, optional): Return the old string stored at key, or None if key did not exist. + return_old_value (bool, optional): Return the old value stored at key, or None if key did not exist. An error is returned and SET aborted if the value stored at key is not a string. Equivalent to `GET` in the Redis API. Defaults to False. Command response: - Optional[str]: + Optional[bytes]: If the value is successfully set, return OK. If value isn't set because of only_if_exists or only_if_does_not_exist conditions, return None. - If return_old_value is set, return the old value as a string. + If return_old_value is set, return the old value as a bytes string. """ args = [key, value] if conditional_set: @@ -183,13 +188,13 @@ def set( args.extend(expiry.get_cmd_args()) return self.append_command(RequestType.Set, args) - def strlen(self: TTransaction, key: str) -> TTransaction: + def strlen(self: TTransaction, key: TEncodable) -> TTransaction: """ Get the length of the string value stored at `key`. See https://redis.io/commands/strlen/ for more details. Args: - key (str): The key to return its length. + key (TEncodable): The key to return its length. Commands response: int: The length of the string value stored at `key`. @@ -197,7 +202,9 @@ def strlen(self: TTransaction, key: str) -> TTransaction: """ return self.append_command(RequestType.Strlen, [key]) - def rename(self: TTransaction, key: str, new_key: str) -> TTransaction: + def rename( + self: TTransaction, key: TEncodable, new_key: TEncodable + ) -> TTransaction: """ Renames `key` to `new_key`. If `newkey` already exists it is overwritten. @@ -206,30 +213,34 @@ def rename(self: TTransaction, key: str, new_key: str) -> TTransaction: See https://redis.io/commands/rename/ for more details. Args: - key (str) : The key to rename. - new_key (str) : The new name of the key. + key (TEncodable) : The key to rename. + new_key (TEncodable) : The new name of the key. Command response: OK: If the `key` was successfully renamed, return "OK". If `key` does not exist, the transaction fails with an error. """ return self.append_command(RequestType.Rename, [key, new_key]) - def renamenx(self: TTransaction, key: str, new_key: str) -> TTransaction: + def renamenx( + self: TTransaction, key: TEncodable, new_key: TEncodable + ) -> TTransaction: """ Renames `key` to `new_key` if `new_key` does not yet exist. See https://valkey.io/commands/renamenx for more details. Args: - key (str): The key to rename. - new_key (str): The new key name. + key (TEncodable): The key to rename. + new_key (TEncodable): The new key name. Command response: bool: True if `key` was renamed to `new_key`, or False if `new_key` already exists. """ return self.append_command(RequestType.RenameNX, [key, new_key]) - def custom_command(self: TTransaction, command_args: List[str]) -> TTransaction: + def custom_command( + self: TTransaction, command_args: List[TEncodable] + ) -> TTransaction: """ Executes a single command, without checking inputs. See the [Glide for Redis Wiki](https://github.com/aws/glide-for-redis/wiki/General-Concepts#custom-command) @@ -240,7 +251,7 @@ def custom_command(self: TTransaction, command_args: List[str]) -> TTransaction: transaction.customCommand(["CLIENT", "LIST","TYPE", "PUBSUB"]) Args: - command_args (List[str]): List of strings of the command's arguments. + command_args (List[TEncodable]): List of command arguments. Every part of the command, including the command name and subcommands, should be added as a separate value in args. Command response: @@ -248,7 +259,7 @@ def custom_command(self: TTransaction, command_args: List[str]) -> TTransaction: """ return self.append_command(RequestType.CustomCommand, command_args) - def append(self: TTransaction, key: str, value: str) -> TTransaction: + def append(self: TTransaction, key: TEncodable, value: TEncodable) -> TTransaction: """ Appends a value to a key. If `key` does not exist it is created and set as an empty string, so `APPEND` will be similar to SET in this special case. @@ -256,8 +267,8 @@ def append(self: TTransaction, key: str, value: str) -> TTransaction: See https://redis.io/commands/append for more details. Args: - key (str): The key to which the value will be appended. - value (str): The value to append. + key (TEncodable): The key to which the value will be appended. + value (TEncodable): The value to append. Commands response: int: The length of the string after appending the value. @@ -277,52 +288,55 @@ def info( information to retrieve. When no parameter is provided, the default option is assumed. Command response: - str: Returns a string containing the information for the sections requested. + bytes: Returns a bytes string containing the information for the sections requested. """ - args = [section.value for section in sections] if sections else [] + args: List[TEncodable] = ( + [section.value for section in sections] if sections else [] + ) return self.append_command(RequestType.Info, args) - def delete(self: TTransaction, keys: List[str]) -> TTransaction: + def delete(self: TTransaction, keys: List[TEncodable]) -> TTransaction: """ Delete one or more keys from the database. A key is ignored if it does not exist. See https://redis.io/commands/del/ for details. Args: - keys (List[str]): A list of keys to be deleted from the database. + keys (List[TEncodable]): A list of keys to be deleted from the database. Command response: int: The number of keys that were deleted. """ return self.append_command(RequestType.Del, keys) - def config_get(self: TTransaction, parameters: List[str]) -> TTransaction: + def config_get(self: TTransaction, parameters: List[TEncodable]) -> TTransaction: """ Get the values of configuration parameters. See https://redis.io/commands/config-get/ for details. Args: - parameters (List[str]): A list of configuration parameter names to retrieve values for. + parameters (List[TEncodable]): A list of configuration parameter names to retrieve values for. Command response: - Dict[str, str]: A dictionary of values corresponding to the configuration parameters. + Dict[bytes, bytes]: A dictionary of values corresponding to the configuration parameters. """ return self.append_command(RequestType.ConfigGet, parameters) def config_set( - self: TTransaction, parameters_map: Mapping[str, str] + self: TTransaction, + parameters_map: Mapping[TEncodable, TEncodable], ) -> TTransaction: """ Set configuration parameters to the specified values. See https://redis.io/commands/config-set/ for details. Args: - parameters_map (Mapping[str, str]): A map consisting of configuration + parameters_map (Mapping[TEncodable, TEncodable]): A map consisting of configuration parameters and their respective values to set. Command response: OK: Returns OK if all configurations have been successfully set. Otherwise, the transaction fails with an error. """ - parameters: List[str] = [] + parameters: List[TEncodable] = [] for pair in parameters_map.items(): parameters.extend(pair) return self.append_command(RequestType.ConfigSet, parameters) @@ -337,23 +351,27 @@ def config_resetstat(self: TTransaction) -> TTransaction: """ return self.append_command(RequestType.ConfigResetStat, []) - def mset(self: TTransaction, key_value_map: Mapping[str, str]) -> TTransaction: + def mset( + self: TTransaction, key_value_map: Mapping[TEncodable, TEncodable] + ) -> TTransaction: """ Set multiple keys to multiple values in a single atomic operation. See https://redis.io/commands/mset/ for more details. Args: - parameters (Mapping[str, str]): A map of key value pairs. + parameters (Mapping[TEncodable, TEncodable]): A map of key value pairs. Command response: OK: a simple OK response. """ - parameters: List[str] = [] + parameters: List[TEncodable] = [] for pair in key_value_map.items(): parameters.extend(pair) return self.append_command(RequestType.MSet, parameters) - def msetnx(self: TTransaction, key_value_map: Mapping[str, str]) -> TTransaction: + def msetnx( + self: TTransaction, key_value_map: Mapping[TEncodable, TEncodable] + ) -> TTransaction: """ Sets multiple keys to values if the key does not exist. The operation is atomic, and if one or more keys already exist, the entire operation fails. @@ -361,38 +379,38 @@ def msetnx(self: TTransaction, key_value_map: Mapping[str, str]) -> TTransaction See https://valkey.io/commands/msetnx/ for more details. Args: - key_value_map (Mapping[str, str]): A key-value map consisting of keys and their respective values to set. + key_value_map (Mapping[TEncodable, TEncodable]): A key-value map consisting of keys and their respective values to set. Commands response: bool: True if all keys were set. False if no key was set. """ - parameters: List[str] = [] + parameters: List[TEncodable] = [] for pair in key_value_map.items(): parameters.extend(pair) return self.append_command(RequestType.MSetNX, parameters) - def mget(self: TTransaction, keys: List[str]) -> TTransaction: + def mget(self: TTransaction, keys: List[TEncodable]) -> TTransaction: """ Retrieve the values of multiple keys. See https://redis.io/commands/mget/ for more details. Args: - keys (List[str]): A list of keys to retrieve values for. + keys (List[TEncodable]): A list of keys to retrieve values for. Command response: - List[Optional[str]]: A list of values corresponding to the provided keys. If a key is not found, + List[Optional[bytes]]: A list of values corresponding to the provided keys. If a key is not found, its corresponding value in the list will be None. """ return self.append_command(RequestType.MGet, keys) - def touch(self: TTransaction, keys: List[str]) -> TTransaction: + def touch(self: TTransaction, keys: List[TEncodable]) -> TTransaction: """ Updates the last access time of specified keys. See https://valkey.io/commands/touch/ for details. Args: - keys (List[str]): The keys to update last access time. + keys (List[TEncodable]): The keys to update last access time. Commands response: int: The number of keys that were updated, a key is ignored if it doesn't exist. @@ -419,7 +437,7 @@ def client_id(self: TTransaction) -> TTransaction: """ return self.append_command(RequestType.ClientId, []) - def incr(self: TTransaction, key: str) -> TTransaction: + def incr(self: TTransaction, key: TEncodable) -> TTransaction: """ Increments the number stored at `key` by one. If `key` does not exist, it is set to 0 before performing the @@ -427,21 +445,21 @@ def incr(self: TTransaction, key: str) -> TTransaction: See https://redis.io/commands/incr/ for more details. Args: - key (str): The key to increment its value. + key (TEncodable): The key to increment its value. Command response: int: the value of `key` after the increment. """ return self.append_command(RequestType.Incr, [key]) - def incrby(self: TTransaction, key: str, amount: int) -> TTransaction: + def incrby(self: TTransaction, key: TEncodable, amount: int) -> TTransaction: """ Increments the number stored at `key` by `amount`. If the key does not exist, it is set to 0 before performing the operation. See https://redis.io/commands/incrby/ for more details. Args: - key (str): The key to increment its value. + key (TEncodable): The key to increment its value. amount (int) : The amount to increment. Command response: @@ -449,7 +467,7 @@ def incrby(self: TTransaction, key: str, amount: int) -> TTransaction: """ return self.append_command(RequestType.IncrBy, [key, str(amount)]) - def incrbyfloat(self: TTransaction, key: str, amount: float) -> TTransaction: + def incrbyfloat(self: TTransaction, key: TEncodable, amount: float) -> TTransaction: """ Increment the string representing a floating point number stored at `key` by `amount`. By using a negative increment value, the value stored at the `key` is decremented. @@ -457,7 +475,7 @@ def incrbyfloat(self: TTransaction, key: str, amount: float) -> TTransaction: See https://redis.io/commands/incrbyfloat/ for more details. Args: - key (str): The key to increment its value. + key (TEncodable): The key to increment its value. amount (float) : The amount to increment. Command response: @@ -465,43 +483,43 @@ def incrbyfloat(self: TTransaction, key: str, amount: float) -> TTransaction: """ return self.append_command(RequestType.IncrByFloat, [key, str(amount)]) - def ping(self: TTransaction, message: Optional[str] = None) -> TTransaction: + def ping(self: TTransaction, message: Optional[TEncodable] = None) -> TTransaction: """ Ping the Redis server. See https://redis.io/commands/ping/ for more details. Args: - message (Optional[str]): An optional message to include in the PING command. If not provided, + message (Optional[TEncodable]): An optional message to include in the PING command. If not provided, the server will respond with "PONG". If provided, the server will respond with a copy of the message. Command response: - str: "PONG" if `message` is not provided, otherwise return a copy of `message`. + bytes: b"PONG" if `message` is not provided, otherwise return a copy of `message`. """ argument = [] if message is None else [message] return self.append_command(RequestType.Ping, argument) - def decr(self: TTransaction, key: str) -> TTransaction: + def decr(self: TTransaction, key: TEncodable) -> TTransaction: """ Decrements the number stored at `key` by one. If the key does not exist, it is set to 0 before performing the operation. See https://redis.io/commands/decr/ for more details. Args: - key (str): The key to decrement its value. + key (TEncodable): The key to decrement its value. Command response: int: the value of `key` after the decrement. """ return self.append_command(RequestType.Decr, [key]) - def decrby(self: TTransaction, key: str, amount: int) -> TTransaction: + def decrby(self: TTransaction, key: TEncodable, amount: int) -> TTransaction: """ Decrements the number stored at `key` by `amount`. If the key does not exist, it is set to 0 before performing the operation. See https://redis.io/commands/decrby/ for more details. Args: - key (str): The key to decrement its value. + key (TEncodable): The key to decrement its value. amount (int) : The amount to decrement. Command response: @@ -509,7 +527,12 @@ def decrby(self: TTransaction, key: str, amount: int) -> TTransaction: """ return self.append_command(RequestType.DecrBy, [key, str(amount)]) - def setrange(self: TTransaction, key: str, offset: int, value: str) -> TTransaction: + def setrange( + self: TTransaction, + key: TEncodable, + offset: int, + value: TEncodable, + ) -> TTransaction: """ Overwrites part of the string stored at `key`, starting at the specified `offset`, for the entire length of `value`. @@ -520,55 +543,57 @@ def setrange(self: TTransaction, key: str, offset: int, value: str) -> TTransact See https://valkey.io/commands/setrange for more details. Args: - key (str): The key of the string to update. + key (TEncodable): The key of the string to update. offset (int): The position in the string where `value` should be written. - value (str): The string written with `offset`. + value (TEncodable): The value written with `offset`. Command response: - int: The length of the string stored at `key` after it was modified. + int: The length of the value stored at `key` after it was modified. """ return self.append_command(RequestType.SetRange, [key, str(offset), value]) def hset( - self: TTransaction, key: str, field_value_map: Mapping[str, str] + self: TTransaction, + key: TEncodable, + field_value_map: Mapping[TEncodable, TEncodable], ) -> TTransaction: """ Sets the specified fields to their respective values in the hash stored at `key`. See https://redis.io/commands/hset/ for more details. Args: - key (str): The key of the hash. - field_value_map (Mapping[str, str]): A field-value map consisting of fields and their corresponding values + key (TEncodable): The key of the hash. + field_value_map (Mapping[TEncodable, TEncodable]): A field-value map consisting of fields and their corresponding values to be set in the hash stored at the specified key. Command response: int: The number of fields that were added to the hash. """ - field_value_list: List[str] = [key] + field_value_list: List[TEncodable] = [key] for pair in field_value_map.items(): field_value_list.extend(pair) return self.append_command(RequestType.HSet, field_value_list) - def hget(self: TTransaction, key: str, field: str) -> TTransaction: + def hget(self: TTransaction, key: TEncodable, field: TEncodable) -> TTransaction: """ Retrieves the value associated with `field` in the hash stored at `key`. See https://redis.io/commands/hget/ for more details. Args: - key (str): The key of the hash. - field (str): The field whose value should be retrieved. + key (TEncodable): The key of the hash. + field (TEncodable): The field whose value should be retrieved. Command response: - Optional[str]: The value associated `field` in the hash. + Optional[bytes]: The value associated `field` in the hash. Returns None if `field` is not presented in the hash or `key` does not exist. """ return self.append_command(RequestType.HGet, [key, field]) def hsetnx( self: TTransaction, - key: str, - field: str, - value: str, + key: TEncodable, + field: TEncodable, + value: TEncodable, ) -> TTransaction: """ Sets `field` in the hash stored at `key` to `value`, only if `field` does not yet exist. @@ -577,16 +602,21 @@ def hsetnx( See https://redis.io/commands/hsetnx/ for more details. Args: - key (str): The key of the hash. - field (str): The field to set the value for. - value (str): The value to set. + key (TEncodable): The key of the hash. + field (TEncodable): The field to set the value for. + value (TEncodable): The value to set. Commands response: bool: True if the field was set, False if the field already existed and was not set. """ return self.append_command(RequestType.HSetNX, [key, field, value]) - def hincrby(self: TTransaction, key: str, field: str, amount: int) -> TTransaction: + def hincrby( + self: TTransaction, + key: TEncodable, + field: TEncodable, + amount: int, + ) -> TTransaction: """ Increment or decrement the value of a `field` in the hash stored at `key` by the specified amount. By using a negative increment value, the value stored at `field` in the hash stored at `key` is decremented. @@ -594,8 +624,8 @@ def hincrby(self: TTransaction, key: str, field: str, amount: int) -> TTransacti See https://redis.io/commands/hincrby/ for more details. Args: - key (str): The key of the hash. - field (str): The field in the hash stored at `key` to increment or decrement its value. + key (TEncodable): The key of the hash. + field (TEncodable): The field in the hash stored at `key` to increment or decrement its value. amount (int): The amount by which to increment or decrement the field's value. Use a negative value to decrement. @@ -605,7 +635,10 @@ def hincrby(self: TTransaction, key: str, field: str, amount: int) -> TTransacti return self.append_command(RequestType.HIncrBy, [key, field, str(amount)]) def hincrbyfloat( - self: TTransaction, key: str, field: str, amount: float + self: TTransaction, + key: TEncodable, + field: TEncodable, + amount: float, ) -> TTransaction: """ Increment or decrement the floating-point value stored at `field` in the hash stored at `key` by the specified @@ -615,8 +648,8 @@ def hincrbyfloat( See https://redis.io/commands/hincrbyfloat/ for more details. Args: - key (str): The key of the hash. - field (str): The field in the hash stored at `key` to increment or decrement its value. + key (TEncodable): The key of the hash. + field (TEncodable): The field in the hash stored at `key` to increment or decrement its value. amount (float): The amount by which to increment or decrement the field's value. Use a negative value to decrement. @@ -625,14 +658,14 @@ def hincrbyfloat( """ return self.append_command(RequestType.HIncrByFloat, [key, field, str(amount)]) - def hexists(self: TTransaction, key: str, field: str) -> TTransaction: + def hexists(self: TTransaction, key: TEncodable, field: TEncodable) -> TTransaction: """ Check if a field exists in the hash stored at `key`. See https://redis.io/commands/hexists/ for more details. Args: - key (str): The key of the hash. - field (str): The field to check in the hash stored at `key`. + key (TEncodable): The key of the hash. + field (TEncodable): The field to check in the hash stored at `key`. Command response: bool: Returns 'True' if the hash contains the specified field. If the hash does not contain the field, @@ -640,14 +673,14 @@ def hexists(self: TTransaction, key: str, field: str) -> TTransaction: """ return self.append_command(RequestType.HExists, [key, field]) - def hlen(self: TTransaction, key: str) -> TTransaction: + def hlen(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns the number of fields contained in the hash stored at `key`. See https://redis.io/commands/hlen/ for more details. Args: - key (str): The key of the hash. + key (TEncodable): The key of the hash. Command response: int: The number of fields in the hash, or 0 when the key does not exist. @@ -661,50 +694,54 @@ def client_getname(self: TTransaction) -> TTransaction: See https://redis.io/commands/client-getname/ for more details. Command response: - Optional[str]: Returns the name of the client connection as a string if a name is set, + Optional[bytes]: Returns the name of the client connection as a bytes string if a name is set, or None if no name is assigned. """ return self.append_command(RequestType.ClientGetName, []) - def hgetall(self: TTransaction, key: str) -> TTransaction: + def hgetall(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns all fields and values of the hash stored at `key`. See https://redis.io/commands/hgetall/ for details. Args: - key (str): The key of the hash. + key (TEncodable): The key of the hash. Command response: - Dict[str, str]: A dictionary of fields and their values stored in the hash. Every field name in the list is followed by + Dict[bytes, bytes]: A dictionary of fields and their values stored in the hash. Every field name in the list is followed by its value. If `key` does not exist, it returns an empty dictionary. """ return self.append_command(RequestType.HGetAll, [key]) - def hmget(self: TTransaction, key: str, fields: List[str]) -> TTransaction: + def hmget( + self: TTransaction, key: TEncodable, fields: List[TEncodable] + ) -> TTransaction: """ Retrieve the values associated with specified fields in the hash stored at `key`. See https://redis.io/commands/hmget/ for details. Args: - key (str): The key of the hash. - fields (List[str]): The list of fields in the hash stored at `key` to retrieve from the database. + key (TEncodable): The key of the hash. + fields (List[TEncodable]): The list of fields in the hash stored at `key` to retrieve from the database. Returns: - List[Optional[str]]: A list of values associated with the given fields, in the same order as they are requested. + List[Optional[bytes]]: A list of values associated with the given fields, in the same order as they are requested. For every field that does not exist in the hash, a null value is returned. If `key` does not exist, it is treated as an empty hash, and the function returns a list of null values. """ return self.append_command(RequestType.HMGet, [key] + fields) - def hdel(self: TTransaction, key: str, fields: List[str]) -> TTransaction: + def hdel( + self: TTransaction, key: TEncodable, fields: List[TEncodable] + ) -> TTransaction: """ Remove specified fields from the hash stored at `key`. See https://redis.io/commands/hdel/ for more details. Args: - key (str): The key of the hash. - fields (List[str]): The list of fields to remove from the hash stored at `key`. + key (TEncodable): The key of the hash. + fields (List[TEncodable]): The list of fields to remove from the hash stored at `key`. Returns: int: The number of fields that were removed from the hash, excluding specified but non-existing fields. @@ -712,81 +749,85 @@ def hdel(self: TTransaction, key: str, fields: List[str]) -> TTransaction: """ return self.append_command(RequestType.HDel, [key] + fields) - def hvals(self: TTransaction, key: str) -> TTransaction: + def hvals(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns all values in the hash stored at `key`. See https://redis.io/commands/hvals/ for more details. Args: - key (str): The key of the hash. + key (TEncodable): The key of the hash. Command response: - List[str]: A list of values in the hash, or an empty list when the key does not exist. + List[bytes]: A list of values in the hash, or an empty list when the key does not exist. """ return self.append_command(RequestType.HVals, [key]) - def hkeys(self: TTransaction, key: str) -> TTransaction: + def hkeys(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns all field names in the hash stored at `key`. See https://redis.io/commands/hkeys/ for more details. Args: - key (str): The key of the hash. + key (TEncodable): The key of the hash. Command response: - List[str]: A list of field names for the hash, or an empty list when the key does not exist. + List[bytes]: A list of field names for the hash, or an empty list when the key does not exist. """ return self.append_command(RequestType.HKeys, [key]) - def hrandfield(self: TTransaction, key: str) -> TTransaction: + def hrandfield(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns a random field name from the hash value stored at `key`. See https://valkey.io/commands/hrandfield for more details. Args: - key (str): The key of the hash. + key (TEncodable): The key of the hash. Command response: - Optional[str]: A random field name from the hash stored at `key`. + Optional[bytes]: A random field name from the hash stored at `key`. If the hash does not exist or is empty, None will be returned. """ return self.append_command(RequestType.HRandField, [key]) - def hrandfield_count(self: TTransaction, key: str, count: int) -> TTransaction: + def hrandfield_count( + self: TTransaction, key: TEncodable, count: int + ) -> TTransaction: """ Retrieves up to `count` random field names from the hash value stored at `key`. See https://valkey.io/commands/hrandfield for more details. Args: - key (str): The key of the hash. + key (TEncodable): The key of the hash. count (int): The number of field names to return. If `count` is positive, returns unique elements. If `count` is negative, allows for duplicates elements. Command response: - List[str]: A list of random field names from the hash. + List[bytes]: A list of random field names from the hash. If the hash does not exist or is empty, the response will be an empty list. """ return self.append_command(RequestType.HRandField, [key, str(count)]) - def hrandfield_withvalues(self: TTransaction, key: str, count: int) -> TTransaction: + def hrandfield_withvalues( + self: TTransaction, key: TEncodable, count: int + ) -> TTransaction: """ Retrieves up to `count` random field names along with their values from the hash value stored at `key`. See https://valkey.io/commands/hrandfield for more details. Args: - key (str): The key of the hash. + key (TEncodable): The key of the hash. count (int): The number of field names to return. If `count` is positive, returns unique elements. If `count` is negative, allows for duplicates elements. Command response: - List[List[str]]: A list of `[field_name, value]` lists, where `field_name` is a random field name from the + List[List[bytes]]: A list of `[field_name, value]` lists, where `field_name` is a random field name from the hash and `value` is the associated value of the field name. If the hash does not exist or is empty, the response will be an empty list. """ @@ -794,22 +835,24 @@ def hrandfield_withvalues(self: TTransaction, key: str, count: int) -> TTransact RequestType.HRandField, [key, str(count), "WITHVALUES"] ) - def hstrlen(self: TTransaction, key: str, field: str) -> TTransaction: + def hstrlen(self: TTransaction, key: TEncodable, field: TEncodable) -> TTransaction: """ Returns the string length of the value associated with `field` in the hash stored at `key`. See https://valkey.io/commands/hstrlen/ for more details. Args: - key (str): The key of the hash. - field (str): The field in the hash. + key (TEncodable): The key of the hash. + field (TEncodable): The field in the hash. Commands response: int: The string length or 0 if `field` or `key` does not exist. """ return self.append_command(RequestType.HStrlen, [key, field]) - def lpush(self: TTransaction, key: str, elements: List[str]) -> TTransaction: + def lpush( + self: TTransaction, key: TEncodable, elements: List[TEncodable] + ) -> TTransaction: """ Insert all the specified values at the head of the list stored at `key`. `elements` are inserted one after the other to the head of the list, from the leftmost element @@ -817,15 +860,17 @@ def lpush(self: TTransaction, key: str, elements: List[str]) -> TTransaction: See https://redis.io/commands/lpush/ for more details. Args: - key (str): The key of the list. - elements (List[str]): The elements to insert at the head of the list stored at `key`. + key (TEncodable): The key of the list. + elements (List[TEncodable]): The elements to insert at the head of the list stored at `key`. Command response: int: The length of the list after the push operations. """ return self.append_command(RequestType.LPush, [key] + elements) - def lpushx(self: TTransaction, key: str, elements: List[str]) -> TTransaction: + def lpushx( + self: TTransaction, key: TEncodable, elements: List[TEncodable] + ) -> TTransaction: """ Inserts all the specified values at the head of the list stored at `key`, only if `key` exists and holds a list. If `key` is not a list, this performs no operation. @@ -833,45 +878,47 @@ def lpushx(self: TTransaction, key: str, elements: List[str]) -> TTransaction: See https://redis.io/commands/lpushx/ for more details. Args: - key (str): The key of the list. - elements (List[str]): The elements to insert at the head of the list stored at `key`. + key (TEncodable): The key of the list. + elements (List[TEncodable]): The elements to insert at the head of the list stored at `key`. Command response: int: The length of the list after the push operation. """ return self.append_command(RequestType.LPushX, [key] + elements) - def lpop(self: TTransaction, key: str) -> TTransaction: + def lpop(self: TTransaction, key: TEncodable) -> TTransaction: """ Remove and return the first elements of the list stored at `key`. 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. + key (TEncodable): The key of the list. Command response: - Optional[str]: The value of the first element. + Optional[bytes]: The value of the first element. If `key` does not exist, None will be returned. """ return self.append_command(RequestType.LPop, [key]) - def lpop_count(self: TTransaction, key: str, count: int) -> TTransaction: + def lpop_count(self: TTransaction, key: TEncodable, count: int) -> TTransaction: """ 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. + key (TEncodable): The key of the list. count (int): The count of elements to pop from the list. Command response: - Optional[List[str]]: A a list of popped elements will be returned depending on the list's length. + Optional[List[bytes]]: A a list of popped elements will be returned depending on the list's length. If `key` does not exist, None will be returned. """ return self.append_command(RequestType.LPop, [key, str(count)]) - def blpop(self: TTransaction, keys: List[str], timeout: float) -> TTransaction: + def blpop( + self: TTransaction, keys: List[TEncodable], timeout: float + ) -> TTransaction: """ Pops an element from the head of the first list that is non-empty, with the given keys being checked in the order that they are given. Blocks the connection when there are no elements to pop from any of the given lists. @@ -881,18 +928,18 @@ def blpop(self: TTransaction, keys: List[str], timeout: float) -> TTransaction: BLPOP is a client blocking command, see https://github.com/aws/glide-for-redis/wiki/General-Concepts#blocking-commands for more details and best practices. Args: - keys (List[str]): The keys of the lists to pop from. + keys (List[TEncodable]): The keys of the lists to pop from. timeout (float): The number of seconds to wait for a blocking operation to complete. A value of 0 will block indefinitely. Command response: - Optional[List[str]]: A two-element list containing the key from which the element was popped and the value of the + Optional[List[bytes]]: A two-element list containing the key from which the element was popped and the value of the popped element, formatted as `[key, value]`. If no element could be popped and the `timeout` expired, returns None. """ return self.append_command(RequestType.BLPop, keys + [str(timeout)]) def lmpop( self: TTransaction, - keys: List[str], + keys: List[TEncodable], direction: ListDirection, count: Optional[int] = None, ) -> TTransaction: @@ -902,12 +949,12 @@ def lmpop( See https://valkey.io/commands/lmpop/ for details. Args: - keys (List[str]): An array of keys of lists. + keys (List[TEncodable]): An array of keys of lists. direction (ListDirection): The direction based on which elements are popped from (`ListDirection.LEFT` or `ListDirection.RIGHT`). count (Optional[int]): The maximum number of popped elements. If not provided, defaults to popping a single element. Command response: - Optional[Mapping[str, List[str]]]: A map of `key` name mapped to an array of popped elements, or None if no elements could be popped. + Optional[Mapping[bytes, List[bytes]]]: A map of `key` name mapped to an array of popped elements, or None if no elements could be popped. Since: Redis version 7.0.0. """ @@ -919,7 +966,7 @@ def lmpop( def blmpop( self: TTransaction, - keys: List[str], + keys: List[TEncodable], direction: ListDirection, timeout: float, count: Optional[int] = None, @@ -932,13 +979,13 @@ def blmpop( See https://valkey.io/commands/blmpop/ for details. Args: - keys (List[str]): An array of keys of lists. + keys (List[TEncodable]): An array of keys of lists. direction (ListDirection): The direction based on which elements are popped from (`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. count (Optional[int]): The maximum number of popped elements. If not provided, defaults to popping a single element. Command response: - Optional[Mapping[str, List[str]]]: A map of `key` name mapped to an array of popped elements, or None if no elements could be popped and the timeout expired. + Optional[Mapping[bytes, List[bytes]]]: A map of `key` name mapped to an array of popped elements, or None if no elements could be popped and the timeout expired. Since: Redis version 7.0.0. """ @@ -948,7 +995,9 @@ def blmpop( return self.append_command(RequestType.BLMPop, args) - def lrange(self: TTransaction, key: str, start: int, end: int) -> TTransaction: + def lrange( + self: TTransaction, key: TEncodable, start: int, end: int + ) -> TTransaction: """ Retrieve the specified elements of the list stored at `key` within the given range. The offsets `start` and `end` are zero-based indexes, with 0 being the first element of the list, 1 being the next @@ -957,12 +1006,12 @@ def lrange(self: TTransaction, key: str, start: int, end: int) -> TTransaction: See https://redis.io/commands/lrange/ for details. Args: - key (str): The key of the list. + key (TEncodable): The key of the list. start (int): The starting point of the range. end (int): The end of the range. Command response: - List[str]: A list of elements within the specified range. + List[byte]: A list of elements within the specified range. If `start` exceeds the `end` of the list, or if `start` is greater than `end`, an empty list will be returned. If `end` exceeds the actual end of the list, the range will stop at the actual end of the list. If `key` does not exist an empty list will be returned. @@ -971,7 +1020,7 @@ def lrange(self: TTransaction, key: str, start: int, end: int) -> TTransaction: def lindex( self: TTransaction, - key: str, + key: TEncodable, index: int, ) -> TTransaction: """ @@ -984,16 +1033,21 @@ def lindex( See https://redis.io/commands/lindex/ for more details. Args: - key (str): The key of the list. + key (TEncodable): The key of the list. index (int): The index of the element in the list to retrieve. Command response: - Optional[str]: The element at `index` in the list stored at `key`. + Optional[bytes]: The element at `index` in the list stored at `key`. If `index` is out of range or if `key` does not exist, None is returned. """ return self.append_command(RequestType.LIndex, [key, str(index)]) - def lset(self: TTransaction, key: str, index: int, element: str) -> TTransaction: + def lset( + self: TTransaction, + key: TEncodable, + index: int, + element: TEncodable, + ) -> TTransaction: """ Sets the list element at `index` to `element`. @@ -1004,24 +1058,27 @@ def lset(self: TTransaction, key: str, index: int, element: str) -> TTransaction See https://valkey.io/commands/lset/ for details. Args: - key (str): The key of the list. + key (TEncodable): The key of the list. index (int): The index of the element in the list to be set. - element (str): The new element to set at the specified index. + element (TEncodable): The new element to set at the specified index. Commands response: TOK: A simple `OK` response. """ return self.append_command(RequestType.LSet, [key, str(index), element]) - def rpush(self: TTransaction, key: str, elements: List[str]) -> TTransaction: - """Inserts all the specified values at the tail of the list stored at `key`. + def rpush( + self: TTransaction, key: TEncodable, elements: List[TEncodable] + ) -> TTransaction: + """ + Inserts all the specified values at the tail of the list stored at `key`. `elements` are inserted one after the other to the tail of the list, from the leftmost element to the rightmost element. If `key` does not exist, it is created as empty list before performing the push operations. See https://redis.io/commands/rpush/ for more details. Args: - key (str): The key of the list. - elements (List[str]): The elements to insert at the tail of the list stored at `key`. + key (TEncodable): The key of the list. + elements (List[TEncodable]): The elements to insert at the tail of the list stored at `key`. Command response: int: The length of the list after the push operations. @@ -1029,7 +1086,9 @@ def rpush(self: TTransaction, key: str, elements: List[str]) -> TTransaction: """ return self.append_command(RequestType.RPush, [key] + elements) - def rpushx(self: TTransaction, key: str, elements: List[str]) -> TTransaction: + def rpushx( + self: TTransaction, key: TEncodable, elements: List[TEncodable] + ) -> TTransaction: """ Inserts all the specified values at the tail of the list stored at `key`, only if `key` exists and holds a list. If `key` is not a list, this performs no operation. @@ -1037,45 +1096,49 @@ def rpushx(self: TTransaction, key: str, elements: List[str]) -> TTransaction: See https://redis.io/commands/rpushx/ for more details. Args: - key (str): The key of the list. - elements (List[str]): The elements to insert at the tail of the list stored at `key`. + key (TEncodable): The key of the list. + elements (List[TEncodable]): The elements to insert at the tail of the list stored at `key`. Command response: int: The length of the list after the push operation. """ return self.append_command(RequestType.RPushX, [key] + elements) - def rpop(self: TTransaction, key: str, count: Optional[int] = None) -> TTransaction: + def rpop( + self: TTransaction, key: TEncodable, count: Optional[int] = None + ) -> TTransaction: """ Removes and returns the last elements of the list stored at `key`. 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. + key (TEncodable): The key of the list. Commands response: - Optional[str]: The value of the last element. + Optional[bytes]: The value of the last element. If `key` does not exist, None will be returned. """ return self.append_command(RequestType.RPop, [key]) - def rpop_count(self: TTransaction, key: str, count: int) -> TTransaction: + def rpop_count(self: TTransaction, key: TEncodable, count: int) -> TTransaction: """ 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. + key (TEncodable): The key of the list. count (int): The count of elements to pop from the list. Commands response: - Optional[List[str]: A list of popped elements will be returned depending on the list's length. + Optional[List[bytes]: A list of popped elements will be returned depending on the list's length. If `key` does not exist, None will be returned. """ return self.append_command(RequestType.RPop, [key, str(count)]) - def brpop(self: TTransaction, keys: List[str], timeout: float) -> TTransaction: + def brpop( + self: TTransaction, keys: List[TEncodable], timeout: float + ) -> TTransaction: """ Pops an element from the tail of the first list that is non-empty, with the given keys being checked in the order that they are given. Blocks the connection when there are no elements to pop from any of the given lists. @@ -1085,17 +1148,21 @@ def brpop(self: TTransaction, keys: List[str], timeout: float) -> TTransaction: BRPOP is a client blocking command, see https://github.com/aws/glide-for-redis/wiki/General-Concepts#blocking-commands for more details and best practices. Args: - keys (List[str]): The keys of the lists to pop from. + keys (List[TEncodable]): The keys of the lists to pop from. timeout (float): The number of seconds to wait for a blocking operation to complete. A value of 0 will block indefinitely. Command response: - Optional[List[str]]: A two-element list containing the key from which the element was popped and the value of the + Optional[List[bytes]]: A two-element list containing the key from which the element was popped and the value of the popped element, formatted as `[key, value]`. If no element could be popped and the `timeout` expired, returns None. """ return self.append_command(RequestType.BRPop, keys + [str(timeout)]) def linsert( - self: TTransaction, key: str, position: InsertPosition, pivot: str, element: str + self: TTransaction, + key: TEncodable, + position: InsertPosition, + pivot: TEncodable, + element: TEncodable, ) -> TTransaction: """ Inserts `element` in the list at `key` either before or after the `pivot`. @@ -1103,11 +1170,11 @@ def linsert( See https://valkey.io/commands/linsert/ for details. Args: - key (str): The key of the list. + key (TEncodable): The key of the list. position (InsertPosition): The relative position to insert into - either `InsertPosition.BEFORE` or `InsertPosition.AFTER` the `pivot`. - pivot (str): An element of the list. - element (str): The new element to insert. + pivot (TEncodable): An element of the list. + element (TEncodable): The new element to insert. Command response: int: The list length after a successful insert operation. @@ -1120,8 +1187,8 @@ def linsert( def lmove( self: TTransaction, - source: str, - destination: str, + source: TEncodable, + destination: TEncodable, where_from: ListDirection, where_to: ListDirection, ) -> TTransaction: @@ -1133,13 +1200,13 @@ def lmove( 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. + source (TEncodable): The key to the source list. + destination (TEncodable): 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. + Optional[bytes]: The popped element, or `None` if `source` does not exist. Since: Redis version 6.2.0. """ @@ -1149,8 +1216,8 @@ def lmove( def blmove( self: TTransaction, - source: str, - destination: str, + source: TEncodable, + destination: TEncodable, where_from: ListDirection, where_to: ListDirection, timeout: float, @@ -1164,14 +1231,14 @@ def blmove( 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. + source (TEncodable): The key to the source list. + destination (TEncodable): 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. + Optional[bytes]: The popped element, or `None` if `source` does not exist or if the operation timed-out. Since: Redis version 6.2.0. """ @@ -1180,7 +1247,9 @@ def blmove( [source, destination, where_from.value, where_to.value, str(timeout)], ) - def sadd(self: TTransaction, key: str, members: List[str]) -> TTransaction: + def sadd( + self: TTransaction, key: TEncodable, members: List[TEncodable] + ) -> TTransaction: """ Add specified members to the set stored at `key`. Specified members that are already a member of this set are ignored. @@ -1188,23 +1257,25 @@ def sadd(self: TTransaction, key: str, members: List[str]) -> TTransaction: See https://redis.io/commands/sadd/ for more details. Args: - key (str): The key where members will be added to its set. - members (List[str]): A list of members to add to the set stored at key. + key (TEncodable): The key where members will be added to its set. + members (List[TEncodable]): A list of members to add to the set stored at key. Command response: int: The number of members that were added to the set, excluding members already present. """ return self.append_command(RequestType.SAdd, [key] + members) - def srem(self: TTransaction, key: str, members: List[str]) -> TTransaction: + def srem( + self: TTransaction, key: TEncodable, members: List[TEncodable] + ) -> TTransaction: """ Remove specified members from the set stored at `key`. Specified members that are not a member of this set are ignored. See https://redis.io/commands/srem/ for details. Args: - key (str): The key from which members will be removed. - members (List[str]): A list of members to remove from the set stored at key. + key (TEncodable): The key from which members will be removed. + members (List[TEncodable]): A list of members to remove from the set stored at key. Commands response: int: The number of members that were removed from the set, excluding non-existing members. @@ -1212,34 +1283,34 @@ def srem(self: TTransaction, key: str, members: List[str]) -> TTransaction: """ return self.append_command(RequestType.SRem, [key] + members) - def smembers(self: TTransaction, key: str) -> TTransaction: + def smembers(self: TTransaction, key: TEncodable) -> TTransaction: """ Retrieve all the members of the set value stored at `key`. See https://redis.io/commands/smembers/ for details. Args: - key (str): The key from which to retrieve the set members. + key (TEncodable): The key from which to retrieve the set members. Commands response: - Set[str]: A set of all members of the set. + Set[bytes]: A set of all members of the set. If `key` does not exist an empty list will be returned. """ return self.append_command(RequestType.SMembers, [key]) - def scard(self: TTransaction, key: str) -> TTransaction: + def scard(self: TTransaction, key: TEncodable) -> TTransaction: """ Retrieve the set cardinality (number of elements) of the set stored at `key`. See https://redis.io/commands/scard/ for details. Args: - key (str): The key from which to retrieve the number of set members. + key (TEncodable): The key from which to retrieve the number of set members. Commands response: int: The cardinality (number of elements) of the set, or 0 if the key does not exist. """ return self.append_command(RequestType.SCard, [key]) - def spop(self: TTransaction, key: str) -> TTransaction: + def spop(self: TTransaction, key: TEncodable) -> TTransaction: """ Removes and returns one random member from the set stored at `key`. @@ -1247,15 +1318,15 @@ def spop(self: TTransaction, key: str) -> TTransaction: To pop multiple members, see `spop_count`. Args: - key (str): The key of the set. + key (TEncodable): The key of the set. Commands response: - Optional[str]: The value of the popped member. + Optional[bytes]: The value of the popped member. If `key` does not exist, None will be returned. """ return self.append_command(RequestType.SPop, [key]) - def spop_count(self: TTransaction, key: str, count: int) -> TTransaction: + def spop_count(self: TTransaction, key: TEncodable, count: int) -> TTransaction: """ Removes and returns up to `count` random members from the set stored at `key`, depending on the set's length. @@ -1263,19 +1334,19 @@ def spop_count(self: TTransaction, key: str, count: int) -> TTransaction: To pop a single member, see `spop`. Args: - key (str): The key of the set. + key (TEncodable): The key of the set. count (int): The count of the elements to pop from the set. Commands response: - Set[str]: A set of popped elements will be returned depending on the set's length. + Set[bytes]: A set of popped elements will be returned depending on the set's length. If `key` does not exist, an empty set will be returned. """ return self.append_command(RequestType.SPop, [key, str(count)]) def sismember( self: TTransaction, - key: str, - member: str, + key: TEncodable, + member: TEncodable, ) -> TTransaction: """ Returns if `member` is a member of the set stored at `key`. @@ -1283,8 +1354,8 @@ def sismember( See https://redis.io/commands/sismember/ for more details. Args: - key (str): The key of the set. - member (str): The member to check for existence in the set. + key (TEncodable): The key of the set. + member (TEncodable): The member to check for existence in the set. Commands response: bool: True if the member exists in the set, False otherwise. @@ -1294,9 +1365,9 @@ def sismember( def smove( self: TTransaction, - source: str, - destination: str, - member: str, + source: TEncodable, + destination: TEncodable, + member: TEncodable, ) -> TTransaction: """ Moves `member` from the set at `source` to the set at `destination`, removing it from the source set. Creates a @@ -1305,34 +1376,34 @@ def smove( See https://valkey.io/commands/smove for more details. Args: - source (str): The key of the set to remove the element from. - destination (str): The key of the set to add the element to. - member (str): The set element to move. + source (TEncodable): The key of the set to remove the element from. + destination (TEncodable): The key of the set to add the element to. + member (TEncodable): The set element to move. Command response: bool: True on success, or False if the `source` set does not exist or the element is not a member of the source set. """ return self.append_command(RequestType.SMove, [source, destination, member]) - def sunion(self: TTransaction, keys: List[str]) -> TTransaction: + def sunion(self: TTransaction, keys: List[TEncodable]) -> TTransaction: """ Gets the union of all the given sets. See https://valkey.io/commands/sunion for more details. Args: - keys (List[str]): The keys of the sets. + keys (List[TEncodable]): The keys of the sets. Commands response: - Set[str]: A set of members which are present in at least one of the given sets. + Set[bytes]: A set of members which are present in at least one of the given sets. If none of the sets exist, an empty set will be returned. """ return self.append_command(RequestType.SUnion, keys) def sunionstore( self: TTransaction, - destination: str, - keys: List[str], + destination: TEncodable, + keys: List[TEncodable], ) -> TTransaction: """ Stores the members of the union of all given sets specified by `keys` into a new set at `destination`. @@ -1340,31 +1411,33 @@ def sunionstore( See https://valkey.io/commands/sunionstore for more details. Args: - destination (str): The key of the destination set. - keys (List[str]): The keys from which to retrieve the set members. + destination (TEncodable): The key of the destination set. + keys (List[TEncodable]): The keys from which to retrieve the set members. Command response: int: The number of elements in the resulting set. """ return self.append_command(RequestType.SUnionStore, [destination] + keys) - def sinter(self: TTransaction, keys: List[str]) -> TTransaction: + def sinter(self: TTransaction, keys: List[TEncodable]) -> TTransaction: """ Gets the intersection of all the given sets. See https://valkey.io/commands/sinter for more details. Args: - keys (List[str]): The keys of the sets. + keys (List[TEncodable]): The keys of the sets. Command response: - Set[str]: A set of members which are present in all given sets. + Set[bytes]: A set of members which are present in all given sets. If one or more sets do not exist, an empty set will be returned. """ return self.append_command(RequestType.SInter, keys) def sinterstore( - self: TTransaction, destination: str, keys: List[str] + self: TTransaction, + destination: TEncodable, + keys: List[TEncodable], ) -> TTransaction: """ Stores the members of the intersection of all given sets specified by `keys` into a new set at `destination`. @@ -1372,8 +1445,8 @@ def sinterstore( See https://valkey.io/commands/sinterstore for more details. Args: - destination (str): The key of the destination set. - keys (List[str]): The keys from which to retrieve the set members. + destination (TEncodable): The key of the destination set. + keys (List[TEncodable]): The keys from which to retrieve the set members. Command response: int: The number of elements in the resulting set. @@ -1381,7 +1454,7 @@ def sinterstore( return self.append_command(RequestType.SInterStore, [destination] + keys) def sintercard( - self: TTransaction, keys: List[str], limit: Optional[int] = None + self: TTransaction, keys: List[TEncodable], limit: Optional[int] = None ) -> TTransaction: """ Gets the cardinality of the intersection of all the given sets. @@ -1390,36 +1463,38 @@ def sintercard( See https://valkey.io/commands/sintercard for more details. Args: - keys (List[str]): A list of keys representing the sets to intersect. + keys (List[TEncodable]): A list of keys representing the sets to intersect. limit (Optional[int]): An optional limit to the maximum number of intersecting elements to count. If specified, the computation stops as soon as the cardinality reaches this limit. Command response: int: The number of elements in the resulting set of the intersection. """ - args = [str(len(keys))] - args += keys + args: List[TEncodable] = [str(len(keys))] + args.extend(keys) if limit is not None: - args += ["LIMIT", str(limit)] + args.extend(["LIMIT", str(limit)]) return self.append_command(RequestType.SInterCard, args) - def sdiff(self: TTransaction, keys: List[str]) -> TTransaction: + def sdiff(self: TTransaction, keys: List[TEncodable]) -> TTransaction: """ Computes the difference between the first set and all the successive sets in `keys`. See https://valkey.io/commands/sdiff for more details. Args: - keys (List[str]): The keys of the sets to diff. + keys (List[TEncodable]): The keys of the sets to diff. Command response: - Set[str]: A set of elements representing the difference between the sets. + Set[bytes]: A set of elements representing the difference between the sets. If any of the keys in `keys` do not exist, they are treated as empty sets. """ return self.append_command(RequestType.SDiff, keys) def sdiffstore( - self: TTransaction, destination: str, keys: List[str] + self: TTransaction, + destination: TEncodable, + keys: List[TEncodable], ) -> TTransaction: """ Stores the difference between the first set and all the successive sets in `keys` into a new set at @@ -1428,30 +1503,34 @@ def sdiffstore( See https://valkey.io/commands/sdiffstore for more details. Args: - destination (str): The key of the destination set. - keys (List[str]): The keys of the sets to diff. + destination (TEncodable): The key of the destination set. + keys (List[TEncodable]): The keys of the sets to diff. Command response: int: The number of elements in the resulting set. """ return self.append_command(RequestType.SDiffStore, [destination] + keys) - def smismember(self: TTransaction, key: str, members: List[str]) -> TTransaction: + def smismember( + self: TTransaction, key: TEncodable, members: List[TEncodable] + ) -> TTransaction: """ Checks whether each member is contained in the members of the set stored at `key`. See https://valkey.io/commands/smismember for more details. Args: - key (str): The key of the set to check. - members (List[str]): A list of members to check for existence in the set. + key (TEncodable): The key of the set to check. + members (List[TEncodable]): A list of members to check for existence in the set. Command response: List[bool]: A list of bool values, each indicating if the respective member exists in the set. """ return self.append_command(RequestType.SMIsMember, [key] + members) - def ltrim(self: TTransaction, key: str, start: int, end: int) -> TTransaction: + def ltrim( + self: TTransaction, key: TEncodable, start: int, end: int + ) -> TTransaction: """ Trim an existing list so that it will contain only the specified range of elements specified. The offsets `start` and `end` are zero-based indexes, with 0 being the first element of the list, 1 being the next @@ -1461,7 +1540,7 @@ def ltrim(self: TTransaction, key: str, start: int, end: int) -> TTransaction: See https://redis.io/commands/ltrim/ for more details. Args: - key (str): The key of the list. + key (TEncodable): The key of the list. start (int): The starting point of the range. end (int): The end of the range. @@ -1474,7 +1553,12 @@ def ltrim(self: TTransaction, key: str, start: int, end: int) -> TTransaction: """ return self.append_command(RequestType.LTrim, [key, str(start), str(end)]) - def lrem(self: TTransaction, key: str, count: int, element: str) -> TTransaction: + def lrem( + self: TTransaction, + key: TEncodable, + count: int, + element: TEncodable, + ) -> TTransaction: """ Removes the first `count` occurrences of elements equal to `element` from the list stored at `key`. If `count` is positive, it removes elements equal to `element` moving from head to tail. @@ -1484,9 +1568,9 @@ def lrem(self: TTransaction, key: str, count: int, element: str) -> TTransaction See https://redis.io/commands/lrem/ for more details. Args: - key (str): The key of the list. + key (TEncodable): The key of the list. count (int): The count of occurrences of elements equal to `element` to remove. - element (str): The element to remove from the list. + element (TEncodable): The element to remove from the list. Commands response: int: The number of removed elements. @@ -1494,13 +1578,13 @@ def lrem(self: TTransaction, key: str, count: int, element: str) -> TTransaction """ return self.append_command(RequestType.LRem, [key, str(count), element]) - def llen(self: TTransaction, key: str) -> TTransaction: + def llen(self: TTransaction, key: TEncodable) -> TTransaction: """ Get the length of the list stored at `key`. See https://redis.io/commands/llen/ for details. Args: - key (str): The key of the list. + key (TEncodable): The key of the list. Commands response: int: The length of the list at the specified key. @@ -1508,13 +1592,13 @@ def llen(self: TTransaction, key: str) -> TTransaction: """ return self.append_command(RequestType.LLen, [key]) - def exists(self: TTransaction, keys: List[str]) -> TTransaction: + def exists(self: TTransaction, keys: List[TEncodable]) -> TTransaction: """ Returns the number of keys in `keys` that exist in the database. See https://redis.io/commands/exists/ for more details. Args: - keys (List[str]): The list of keys to check. + keys (List[TEncodable]): The list of keys to check. Commands response: int: The number of keys that exist. If the same existing key is mentioned in `keys` multiple times, @@ -1522,7 +1606,7 @@ def exists(self: TTransaction, keys: List[str]) -> TTransaction: """ return self.append_command(RequestType.Exists, keys) - def unlink(self: TTransaction, keys: List[str]) -> TTransaction: + def unlink(self: TTransaction, keys: List[TEncodable]) -> TTransaction: """ Unlink (delete) multiple keys from the database. A key is ignored if it does not exist. @@ -1531,7 +1615,7 @@ def unlink(self: TTransaction, keys: List[str]) -> TTransaction: See https://redis.io/commands/unlink/ for more details. Args: - keys (List[str]): The list of keys to unlink. + keys (List[TEncodable]): The list of keys to unlink. Commands response: int: The number of keys that were unlinked. @@ -1540,7 +1624,7 @@ def unlink(self: TTransaction, keys: List[str]) -> TTransaction: def expire( self: TTransaction, - key: str, + key: TEncodable, seconds: int, option: Optional[ExpireOptions] = None, ) -> TTransaction: @@ -1552,7 +1636,7 @@ def expire( See https://redis.io/commands/expire/ for more details. Args: - key (str): The key to set a timeout on. + key (TEncodable): The key to set a timeout on. seconds (int): The timeout in seconds. option (Optional[ExpireOptions]): The expire option. @@ -1560,14 +1644,14 @@ def expire( bool: 'True' if the timeout was set, 'False' if the timeout was not set (e.g., the key doesn't exist or the operation is skipped due to the provided arguments). """ - args: List[str] = ( + args: List[TEncodable] = ( [key, str(seconds)] if option is None else [key, str(seconds), option.value] ) return self.append_command(RequestType.Expire, args) def expireat( self: TTransaction, - key: str, + key: TEncodable, unix_seconds: int, option: Optional[ExpireOptions] = None, ) -> TTransaction: @@ -1581,7 +1665,7 @@ def expireat( See https://redis.io/commands/expireat/ for more details. Args: - key (str): The key to set a timeout on. + key (TEncodable): The key to set a timeout on. unix_seconds (int): The timeout in an absolute Unix timestamp. option (Optional[ExpireOptions]): The expire option. @@ -1598,7 +1682,7 @@ def expireat( def pexpire( self: TTransaction, - key: str, + key: TEncodable, milliseconds: int, option: Optional[ExpireOptions] = None, ) -> TTransaction: @@ -1610,7 +1694,7 @@ def pexpire( See https://redis.io/commands/pexpire/ for more details. Args: - key (str): The key to set a timeout on. + key (TEncodable): The key to set a timeout on. milliseconds (int): The timeout in milliseconds. option (Optional[ExpireOptions]): The expire option. @@ -1627,7 +1711,7 @@ def pexpire( def pexpireat( self: TTransaction, - key: str, + key: TEncodable, unix_milliseconds: int, option: Optional[ExpireOptions] = None, ) -> TTransaction: @@ -1641,7 +1725,7 @@ def pexpireat( See https://redis.io/commands/pexpireat/ for more details. Args: - key (str): The key to set a timeout on. + key (TEncodable): The key to set a timeout on. unix_milliseconds (int): The timeout in an absolute Unix timestamp in milliseconds. option (Optional[ExpireOptions]): The expire option. @@ -1656,7 +1740,7 @@ def pexpireat( ) return self.append_command(RequestType.PExpireAt, args) - def expiretime(self: TTransaction, key: str) -> TTransaction: + def expiretime(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns the absolute Unix timestamp (since January 1, 1970) at which the given `key` will expire, in seconds. @@ -1665,7 +1749,7 @@ def expiretime(self: TTransaction, key: str) -> TTransaction: See https://valkey.io/commands/expiretime/ for details. Args: - key (str): The `key` to determine the expiration value of. + key (TEncodable): The `key` to determine the expiration value of. Commands response: int: The expiration Unix timestamp in seconds, -2 if `key` does not exist or -1 if `key` exists but has no associated expire. @@ -1674,7 +1758,7 @@ def expiretime(self: TTransaction, key: str) -> TTransaction: """ return self.append_command(RequestType.ExpireTime, [key]) - def pexpiretime(self: TTransaction, key: str) -> TTransaction: + def pexpiretime(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns the absolute Unix timestamp (since January 1, 1970) at which the given `key` will expire, in milliseconds. @@ -1682,7 +1766,7 @@ def pexpiretime(self: TTransaction, key: str) -> TTransaction: See https://valkey.io/commands/pexpiretime/ for details. Args: - key (str): The `key` to determine the expiration value of. + key (TEncodable): The `key` to determine the expiration value of. Commands response: int: The expiration Unix timestamp in milliseconds, -2 if `key` does not exist, or -1 if `key` exists but has no associated expiration. @@ -1691,13 +1775,13 @@ def pexpiretime(self: TTransaction, key: str) -> TTransaction: """ return self.append_command(RequestType.PExpireTime, [key]) - def ttl(self: TTransaction, key: str) -> TTransaction: + def ttl(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns the remaining time to live of `key` that has a timeout. See https://redis.io/commands/ttl/ for more details. Args: - key (str): The key to return its timeout. + key (TEncodable): The key to return its timeout. Commands response: int: TTL in seconds, -2 if `key` does not exist or -1 if `key` exists but has no associated expire. @@ -1706,14 +1790,14 @@ def ttl(self: TTransaction, key: str) -> TTransaction: def pttl( self: TTransaction, - key: str, + key: TEncodable, ) -> TTransaction: """ Returns the remaining time to live of `key` that has a timeout, in milliseconds. See https://redis.io/commands/pttl for more details. Args: - key (str): The key to return its timeout. + key (TEncodable): The key to return its timeout. Commands Response: int: TTL in milliseconds. -2 if `key` does not exist, -1 if `key` exists but has no associated expire. @@ -1722,7 +1806,7 @@ def pttl( def persist( self: TTransaction, - key: str, + key: TEncodable, ) -> TTransaction: """ Remove the existing timeout on `key`, turning the key from volatile (a key with an expire set) to @@ -1731,24 +1815,24 @@ def persist( See https://redis.io/commands/persist/ for more details. Args: - key (str): TThe key to remove the existing timeout on. + key (TEncodable): The key to remove the existing timeout on. Commands response: bool: False if `key` does not exist or does not have an associated timeout, True if the timeout has been removed. """ return self.append_command(RequestType.Persist, [key]) - def echo(self: TTransaction, message: str) -> TTransaction: + def echo(self: TTransaction, message: TEncodable) -> TTransaction: """ Echoes the provided `message` back. See https://redis.io/commands/echo for more details. Args: - message (str): The message to be echoed back. + message (TEncodable): The message to be echoed back. Commands response: - str: The provided `message`. + bytes: The provided `message`. """ return self.append_command(RequestType.Echo, [message]) @@ -1763,23 +1847,23 @@ def lastsave(self: TTransaction) -> TTransaction: """ return self.append_command(RequestType.LastSave, []) - def type(self: TTransaction, key: str) -> TTransaction: + def type(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns the string representation of the type of the value stored at `key`. See https://redis.io/commands/type/ for more details. - Args: - key (str): The key to check its data type. + Args: + key (TEncodable): The key to check its data type. Commands response: - str: If the key exists, the type of the stored value is returned. + bytes: If the key exists, the type of the stored value is returned. Otherwise, a "none" string is returned. """ return self.append_command(RequestType.Type, [key]) def function_load( - self: TTransaction, library_code: str, replace: bool = False + self: TTransaction, library_code: TEncodable, replace: bool = False ) -> TTransaction: """ Loads a library to Redis. @@ -1787,12 +1871,12 @@ def function_load( See https://valkey.io/docs/latest/commands/function-load/ for more details. Args: - library_code (str): The source code that implements the library. + library_code (TEncodable): The source code that implements the library. replace (bool): Whether the given library should overwrite a library with the same name if it already exists. Commands response: - str: The library name that was loaded. + bytes: The library name that was loaded. Since: Redis 7.0.0. """ @@ -1822,14 +1906,14 @@ def function_flush( [mode.value] if mode else [], ) - def function_delete(self: TTransaction, library_name: str) -> TTransaction: + def function_delete(self: TTransaction, library_name: TEncodable) -> TTransaction: """ Deletes a library and all its functions. See https://valkey.io/docs/latest/commands/function-delete/ for more details. Args: - library_code (str): The libary name to delete + library_code (TEncodable): The library name to delete Commands response: TOK: A simple `OK`. @@ -1843,26 +1927,23 @@ def function_delete(self: TTransaction, library_name: str) -> TTransaction: def fcall( self: TTransaction, - function: str, - keys: Optional[List[str]] = None, - arguments: Optional[List[str]] = None, + function: TEncodable, + keys: Optional[List[TEncodable]] = None, + arguments: Optional[List[TEncodable]] = None, ) -> TTransaction: """ Invokes a previously loaded function. See https://redis.io/commands/fcall/ for more details. - Args: - function (str): The function name. - keys (Optional[List[str]]): A list of keys accessed by the function. To ensure the correct + function (TEncodable): The function name. + keys (Optional[List[TEncodable]]): A list of keys accessed by the function. To ensure the correct execution of functions, both in standalone and clustered deployments, all names of keys that a function accesses must be explicitly provided as `keys`. - arguments (Optional[List[str]]): A list of `function` arguments. `Arguments` + arguments (Optional[List[TEncodable]]): A list of `function` arguments. `Arguments` should not represent names of keys. - Command Response: TResult: The invoked function's return value. - Since: Redis version 7.0.0. """ args = [] @@ -1876,9 +1957,9 @@ def fcall( def fcall_ro( self: TTransaction, - function: str, - keys: Optional[List[str]] = None, - arguments: Optional[List[str]] = None, + function: TEncodable, + keys: Optional[List[TEncodable]] = None, + arguments: Optional[List[TEncodable]] = None, ) -> TTransaction: """ Invokes a previously loaded read-only function. @@ -1886,11 +1967,11 @@ def fcall_ro( See https://valkey.io/commands/fcall_ro for more details. Args: - function (str): The function name. - keys (List[str]): An `array` of keys accessed by the function. To ensure the correct + function (TEncodable): The function name. + keys (List[TEncodable]): An `array` of keys accessed by the function. To ensure the correct execution of functions, all names of keys that a function accesses must be explicitly provided as `keys`. - arguments (List[str]): An `array` of `function` arguments. `arguments` should not + arguments (List[TEncodable]): An `array` of `function` arguments. `arguments` should not represent names of keys. Command Response: @@ -1909,8 +1990,8 @@ def fcall_ro( def xadd( self: TTransaction, - key: str, - values: List[Tuple[str, str]], + key: TEncodable, + values: List[Tuple[TEncodable, TEncodable]], options: StreamAddOptions = StreamAddOptions(), ) -> TTransaction: """ @@ -1919,12 +2000,12 @@ def xadd( See https://valkey.io/commands/xadd for more details. Args: - key (str): The key of the stream. - values (List[Tuple[str, str]]): Field-value pairs to be added to the entry. - options (Optional[StreamAddOptions]): Additional options for adding entries to the stream. Default to None. sSee `StreamAddOptions`. + key (TEncodable): The key of the stream. + values: List[Tuple[TEncodable, TEncodable]]: Field-value pairs to be added to the entry. + options (Optional[StreamAddOptions]): Additional options for adding entries to the stream. Default to None. See `StreamAddOptions`. Commands response: - str: The id of the added entry, or None if `options.make_stream` is set to False and no stream with the matching `key` exists. + bytes: The id of the added entry, or None if `options.make_stream` is set to False and no stream with the matching `key` exists. """ args = [key] if options: @@ -1933,15 +2014,17 @@ def xadd( return self.append_command(RequestType.XAdd, args) - def xdel(self: TTransaction, key: str, ids: List[str]) -> TTransaction: + def xdel( + self: TTransaction, key: TEncodable, ids: List[TEncodable] + ) -> TTransaction: """ Removes the specified entries by id from a stream, and returns the number of entries deleted. See https://valkey.io/commands/xdel for more details. Args: - key (str): The key of the stream. - ids (List[str]): An array of entry ids. + key (TEncodable): The key of the stream. + ids (List[TEncodable]): An array of entry ids. Command response: int: The number of entries removed from the stream. This number may be less than the number of entries in @@ -1951,7 +2034,7 @@ def xdel(self: TTransaction, key: str, ids: List[str]) -> TTransaction: def xtrim( self: TTransaction, - key: str, + key: TEncodable, options: StreamTrimOptions, ) -> TTransaction: """ @@ -1960,7 +2043,7 @@ def xtrim( See https://valkey.io/commands/xtrim for more details. Args: - key (str): The key of the stream. + key (TEncodable): The key of the stream. options (StreamTrimOptions): Options detailing how to trim the stream. See `StreamTrimOptions`. Commands response: @@ -1972,14 +2055,14 @@ def xtrim( return self.append_command(RequestType.XTrim, args) - def xlen(self: TTransaction, key: str) -> TTransaction: + def xlen(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns the number of entries in the stream stored at `key`. See https://valkey.io/commands/xlen for more details. Args: - key (str): The key of the stream. + key (TEncodable): The key of the stream. Command response: int: The number of entries in the stream. If `key` does not exist, returns 0. @@ -1988,7 +2071,7 @@ def xlen(self: TTransaction, key: str) -> TTransaction: def xrange( self: TTransaction, - key: str, + key: TEncodable, start: StreamRangeBound, end: StreamRangeBound, count: Optional[int] = None, @@ -1999,7 +2082,7 @@ def xrange( See https://valkey.io/commands/xrange for more details. Args: - key (str): The key of the stream. + key (TEncodable): The key of the stream. start (StreamRangeBound): The starting stream ID bound for the range. - Use `IdBound` to specify a stream ID. - Use `ExclusiveIdBound` to specify an exclusive bounded stream ID. @@ -2012,7 +2095,7 @@ def xrange( If `count` is not provided, all stream entries in the range will be returned. Command response: - Optional[Mapping[str, List[List[str]]]]: A mapping of stream IDs to stream entry data, where entry data is a + Optional[Mapping[bytes, List[List[bytes]]]]: A mapping of stream IDs to stream entry data, where entry data is a list of pairings with format `[[field, entry], [field, entry], ...]`. Returns None if the range arguments are not applicable. """ @@ -2024,7 +2107,7 @@ def xrange( def xrevrange( self: TTransaction, - key: str, + key: TEncodable, end: StreamRangeBound, start: StreamRangeBound, count: Optional[int] = None, @@ -2036,7 +2119,7 @@ def xrevrange( See https://valkey.io/commands/xrevrange for more details. Args: - key (str): The key of the stream. + key (TEncodable): The key of the stream. end (StreamRangeBound): The ending stream ID bound for the range. - Use `IdBound` to specify a stream ID. - Use `ExclusiveIdBound` to specify an exclusive bounded stream ID. @@ -2049,7 +2132,7 @@ def xrevrange( If `count` is not provided, all stream entries in the range will be returned. Command response: - Optional[Mapping[str, List[List[str]]]]: A mapping of stream IDs to stream entry data, where entry data is a + Optional[Mapping[bytes, List[List[bytes]]]]: A mapping of stream IDs to stream entry data, where entry data is a list of pairings with format `[[field, entry], [field, entry], ...]`. Returns None if the range arguments are not applicable. """ @@ -2061,7 +2144,7 @@ def xrevrange( def xread( self: TTransaction, - keys_and_ids: Mapping[str, str], + keys_and_ids: Mapping[TEncodable, TEncodable], options: Optional[StreamReadOptions] = None, ) -> TTransaction: """ @@ -2070,18 +2153,18 @@ def xread( See https://valkey.io/commands/xread for more details. Args: - keys_and_ids (Mapping[str, str]): A mapping of keys and entry IDs to read from. The mapping is composed of a + keys_and_ids (Mapping[TEncodable, TEncodable]): A mapping of keys and entry IDs to read from. The mapping is composed of a stream's key and the ID of the entry after which the stream will be read. options (Optional[StreamReadOptions]): Options detailing how to read the stream. Command response: - Optional[Mapping[str, Mapping[str, List[List[str]]]]]: A mapping of stream keys, to a mapping of stream IDs, + Optional[Mapping[bytes, Mapping[bytes, List[List[bytes]]]]]: A mapping of stream keys, to a mapping of stream IDs, to a list of pairings with format `[[field, entry], [field, entry], ...]`. None will be returned under the following conditions: - All key-ID pairs in `keys_and_ids` have either a non-existing key or a non-existing ID, or there are no entries after the given ID. - The `BLOCK` option is specified and the timeout is hit. """ - args = [] if options is None else options.to_args() + args: List[TEncodable] = [] if options is None else options.to_args() args.append("STREAMS") args.extend([key for key in keys_and_ids.keys()]) args.extend([value for value in keys_and_ids.values()]) @@ -2090,9 +2173,9 @@ def xread( def xgroup_create( self: TTransaction, - key: str, - group_name: str, - group_id: str, + key: TEncodable, + group_name: TEncodable, + group_id: TEncodable, options: Optional[StreamGroupOptions] = None, ) -> TTransaction: """ @@ -2101,9 +2184,9 @@ def xgroup_create( See https://valkey.io/commands/xgroup-create for more details. Args: - key (str): The key of the stream. - group_name (str): The newly created consumer group name. - group_id (str): The stream entry ID that specifies the last delivered entry in the stream from the new + key (TEncodable): The key of the stream. + group_name (TEncodable): The newly created consumer group name. + group_id (TEncodable): The stream entry ID that specifies the last delivered entry in the stream from the new group’s perspective. The special ID "$" can be used to specify the last entry in the stream. options (Optional[StreamGroupOptions]): Options for creating the stream group. @@ -2116,15 +2199,17 @@ def xgroup_create( return self.append_command(RequestType.XGroupCreate, args) - def xgroup_destroy(self: TTransaction, key: str, group_name: str) -> TTransaction: + def xgroup_destroy( + self: TTransaction, key: TEncodable, group_name: TEncodable + ) -> TTransaction: """ Destroys the consumer group `group_name` for the stream stored at `key`. See https://valkey.io/commands/xgroup-destroy for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name to delete. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name to delete. Command response: bool: True if the consumer group was destroyed. Otherwise, returns False. @@ -2132,7 +2217,10 @@ def xgroup_destroy(self: TTransaction, key: str, group_name: str) -> TTransactio return self.append_command(RequestType.XGroupDestroy, [key, group_name]) def xgroup_create_consumer( - self: TTransaction, key: str, group_name: str, consumer_name: str + self: TTransaction, + key: TEncodable, + group_name: TEncodable, + consumer_name: TEncodable, ) -> TTransaction: """ Creates a consumer named `consumer_name` in the consumer group `group_name` for the stream stored at `key`. @@ -2140,9 +2228,9 @@ def xgroup_create_consumer( See https://valkey.io/commands/xgroup-createconsumer for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. - consumer_name (str): The newly created consumer. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. + consumer_name (TEncodable): The newly created consumer. Command response: bool: True if the consumer is created. Otherwise, returns False. @@ -2152,7 +2240,10 @@ def xgroup_create_consumer( ) def xgroup_del_consumer( - self: TTransaction, key: str, group_name: str, consumer_name: str + self: TTransaction, + key: TEncodable, + group_name: TEncodable, + consumer_name: TEncodable, ) -> TTransaction: """ Deletes a consumer named `consumer_name` in the consumer group `group_name` for the stream stored at `key`. @@ -2160,9 +2251,9 @@ def xgroup_del_consumer( See https://valkey.io/commands/xgroup-delconsumer for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. - consumer_name (str): The consumer to delete. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. + consumer_name (TEncodable): The consumer to delete. Command response: int: The number of pending messages the `consumer` had before it was deleted. @@ -2173,9 +2264,9 @@ def xgroup_del_consumer( def xgroup_set_id( self: TTransaction, - key: str, - group_name: str, - stream_id: str, + key: TEncodable, + group_name: TEncodable, + stream_id: TEncodable, entries_read_id: Optional[str] = None, ) -> TTransaction: """ @@ -2184,9 +2275,9 @@ def xgroup_set_id( See https://valkey.io/commands/xgroup-setid for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. - stream_id (str): The stream entry ID that should be set as the last delivered ID for the consumer group. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. + stream_id (TEncodable): The stream entry ID that should be set as the last delivered ID for the consumer group. entries_read_id (Optional[str]): An arbitrary ID (that isn't the first ID, last ID, or the zero ID ("0-0")) used to find out how many entries are between the arbitrary ID (excluding it) and the stream's last entry. This argument can only be specified if you are using Redis version 7.0.0 or above. @@ -2202,9 +2293,9 @@ def xgroup_set_id( def xreadgroup( self: TTransaction, - keys_and_ids: Mapping[str, str], - group_name: str, - consumer_name: str, + keys_and_ids: Mapping[TEncodable, TEncodable], + group_name: TEncodable, + consumer_name: TEncodable, options: Optional[StreamReadGroupOptions] = None, ) -> TTransaction: """ @@ -2213,15 +2304,15 @@ def xreadgroup( See https://valkey.io/commands/xreadgroup for more details. Args: - keys_and_ids (Mapping[str, str]): A mapping of stream keys to stream entry IDs to read from. The special ">" + keys_and_ids (Mapping[TEncodable, TEncodable]): A mapping of stream keys to stream entry IDs to read from. The special ">" ID returns messages that were never delivered to any other consumer. Any other valid ID will return entries pending for the consumer with IDs greater than the one provided. - group_name (str): The consumer group name. - consumer_name (str): The consumer name. The consumer will be auto-created if it does not already exist. + group_name (TEncodable): The consumer group name. + consumer_name (TEncodable): The consumer name. The consumer will be auto-created if it does not already exist. options (Optional[StreamReadGroupOptions]): Options detailing how to read the stream. Command response: - Optional[Mapping[str, Mapping[str, Optional[List[List[str]]]]]]: A mapping of stream keys, to a mapping of + Optional[Mapping[bytes, Mapping[bytes, Optional[List[List[bytes]]]]]]: A mapping of stream keys, to a mapping of stream IDs, to a list of pairings with format `[[field, entry], [field, entry], ...]`. Returns None if the BLOCK option is given and a timeout occurs, or if there is no stream that can be served. """ @@ -2237,9 +2328,9 @@ def xreadgroup( def xack( self: TTransaction, - key: str, - group_name: str, - ids: List[str], + key: TEncodable, + group_name: TEncodable, + ids: List[TEncodable], ) -> TTransaction: """ Removes one or multiple messages from the Pending Entries List (PEL) of a stream consumer group. @@ -2249,9 +2340,9 @@ def xack( See https://valkey.io/commands/xack for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. - ids (List[str]): The stream entry IDs to acknowledge and consume for the given consumer group. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. + ids (List[TEncodable]): The stream entry IDs to acknowledge and consume for the given consumer group. Command response: int: The number of messages that were successfully acknowledged. @@ -2260,8 +2351,8 @@ def xack( def xpending( self: TTransaction, - key: str, - group_name: str, + key: TEncodable, + group_name: TEncodable, ) -> TTransaction: """ Returns stream message summary information for pending messages for the given consumer group. @@ -2269,11 +2360,11 @@ def xpending( See https://valkey.io/commands/xpending for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. Command response: - List[Union[int, str, List[List[str]], None]]: A list that includes the summary of pending messages, with the + List[Union[int, bytes, List[List[bytes]], None]]: A list that includes the summary of pending messages, with the format `[num_group_messages, start_id, end_id, [[consumer_name, num_consumer_messages]]]`, where: - `num_group_messages`: The total number of pending messages for this consumer group. - `start_id`: The smallest ID among the pending messages. @@ -2287,8 +2378,8 @@ def xpending( def xpending_range( self: TTransaction, - key: str, - group_name: str, + key: TEncodable, + group_name: TEncodable, start: StreamRangeBound, end: StreamRangeBound, count: int, @@ -2300,8 +2391,8 @@ def xpending_range( See https://valkey.io/commands/xpending for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. start (StreamRangeBound): The starting stream ID bound for the range. - Use `IdBound` to specify a stream ID. - Use `ExclusiveIdBound` to specify an exclusive bounded stream ID. @@ -2314,7 +2405,7 @@ def xpending_range( options (Optional[StreamPendingOptions]): The stream pending options. Command response: - List[List[Union[str, int]]]: A list of lists, where each inner list is a length 4 list containing extended + List[List[Union[bytes, int]]]: A list of lists, where each inner list is a length 4 list containing extended message information with the format `[[id, consumer_name, time_elapsed, num_delivered]]`, where: - `id`: The ID of the message. - `consumer_name`: The name of the consumer that fetched the message and has still to acknowledge it. We @@ -2328,11 +2419,11 @@ def xpending_range( def xautoclaim( self: TTransaction, - key: str, - group_name: str, - consumer_name: str, + key: TEncodable, + group_name: TEncodable, + consumer_name: TEncodable, min_idle_time_ms: int, - start: str, + start: TEncodable, count: Optional[int] = None, ) -> TTransaction: """ @@ -2341,16 +2432,16 @@ def xautoclaim( See https://valkey.io/commands/xautoclaim for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. - consumer_name (str): The consumer name. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. + consumer_name (TEncodable): The consumer name. min_idle_time_ms (int): Filters the claimed entries to those that have been idle for more than the specified value. - start (str): Filters the claimed entries to those that have an ID equal or greater than the specified value. + start (TEncodable): Filters the claimed entries to those that have an ID equal or greater than the specified value. count (Optional[int]): Limits the number of claimed entries to the specified value. Command response: - List[Union[str, Mapping[str, List[List[str]]], List[str]]]: A list containing the following elements: + List[Union[str, Mapping[bytes, List[List[bytes]]], List[bytes]]]: A list containing the following elements: - A stream ID to be used as the start argument for the next call to `XAUTOCLAIM`. This ID is equivalent to the next ID in the stream after the entries that were scanned, or "0-0" if the entire stream was scanned. @@ -2370,11 +2461,11 @@ def xautoclaim( def xautoclaim_just_id( self: TTransaction, - key: str, - group_name: str, - consumer_name: str, + key: TEncodable, + group_name: TEncodable, + consumer_name: TEncodable, min_idle_time_ms: int, - start: str, + start: TEncodable, count: Optional[int] = None, ) -> TTransaction: """ @@ -2385,16 +2476,16 @@ def xautoclaim_just_id( See https://valkey.io/commands/xautoclaim for more details. Args: - key (str): The key of the stream. - group_name (str): The consumer group name. - consumer_name (str): The consumer name. + key (TEncodable): The key of the stream. + group_name (TEncodable): The consumer group name. + consumer_name (TEncodable): The consumer name. min_idle_time_ms (int): Filters the claimed entries to those that have been idle for more than the specified value. - start (str): Filters the claimed entries to those that have an ID equal or greater than the specified value. + start (TEncodable): Filters the claimed entries to those that have an ID equal or greater than the specified value. count (Optional[int]): Limits the number of claimed entries to the specified value. Command response: - List[Union[str, List[str]]]: A list containing the following elements: + List[Union[bytes, List[bytes]]]: A list containing the following elements: - A stream ID to be used as the start argument for the next call to `XAUTOCLAIM`. This ID is equivalent to the next ID in the stream after the entries that were scanned, or "0-0" if the entire stream was scanned. @@ -2415,8 +2506,8 @@ def xautoclaim_just_id( def geoadd( self: TTransaction, - key: str, - members_geospatialdata: Mapping[str, GeospatialData], + key: TEncodable, + members_geospatialdata: Mapping[TEncodable, GeospatialData], existing_options: Optional[ConditionalChange] = None, changed: bool = False, ) -> TTransaction: @@ -2427,8 +2518,8 @@ def geoadd( See https://valkey.io/commands/geoadd for more details. Args: - key (str): The key of the sorted set. - members_geospatialdata (Mapping[str, GeospatialData]): A mapping of member names to their corresponding positions. See `GeospatialData`. + key (TEncodable): The key of the sorted set. + members_geospatialdata (Mapping[TEncodable, GeospatialData]): A mapping of member names to their corresponding positions. See `GeospatialData`. The command will report an error when the user attempts to index coordinates outside the specified ranges. existing_options (Optional[ConditionalChange]): Options for handling existing members. - NX: Only add new elements. @@ -2457,9 +2548,9 @@ def geoadd( def geodist( self: TTransaction, - key: str, - member1: str, - member2: str, + key: TEncodable, + member1: TEncodable, + member2: TEncodable, unit: Optional[GeoUnit] = None, ) -> TTransaction: """ @@ -2468,9 +2559,9 @@ def geodist( See https://valkey.io/commands/geodist for more details. Args: - key (str): The key of the sorted set. - member1 (str): The name of the first member. - member2 (str): The name of the second member. + key (TEncodable): The key of the sorted set. + member1 (TEncodable): The name of the first member. + member2 (TEncodable): The name of the second member. unit (Optional[GeoUnit]): The unit of distance measurement. See `GeoUnit`. If not specified, the default unit is meters. @@ -2484,27 +2575,29 @@ def geodist( return self.append_command(RequestType.GeoDist, args) - def geohash(self: TTransaction, key: str, members: List[str]) -> TTransaction: + def geohash( + self: TTransaction, key: TEncodable, members: List[TEncodable] + ) -> TTransaction: """ - Returns the GeoHash strings representing the positions of all the specified members in the sorted set stored at + Returns the GeoHash bytes strings representing the positions of all the specified members in the sorted set stored at `key`. See https://valkey.io/commands/geohash for more details. Args: - key (str): The key of the sorted set. - members (List[str]): The list of members whose GeoHash strings are to be retrieved. + key (TEncodable): The key of the sorted set. + members (List[TEncodable]): The list of members whose GeoHash bytes strings are to be retrieved. Commands response: - List[Optional[str]]: A list of GeoHash strings representing the positions of the specified members stored at `key`. + List[Optional[bytes]]: A list of GeoHash bytes strings representing the positions of the specified members stored at `key`. If a member does not exist in the sorted set, a None value is returned for that member. """ return self.append_command(RequestType.GeoHash, [key] + members) def geopos( self: TTransaction, - key: str, - members: List[str], + key: TEncodable, + members: List[TEncodable], ) -> TTransaction: """ Returns the positions (longitude and latitude) of all the given members of a geospatial index in the sorted set stored at @@ -2513,8 +2606,8 @@ def geopos( See https://valkey.io/commands/geopos for more details. Args: - key (str): The key of the sorted set. - members (List[str]): The members for which to get the positions. + key (TEncodable): The key of the sorted set. + members (List[TEncodable]): The members for which to get the positions. Commands response: List[Optional[List[float]]]: A list of positions (longitude and latitude) corresponding to the given members. @@ -2524,9 +2617,9 @@ def geopos( def geosearch( self: TTransaction, - key: str, - search_from: Union[str, GeospatialData], - seach_by: Union[GeoSearchByRadius, GeoSearchByBox], + key: TEncodable, + search_from: Union[TEncodable, GeospatialData], + search_by: Union[GeoSearchByRadius, GeoSearchByBox], order_by: Optional[OrderBy] = None, count: Optional[GeoSearchCount] = None, with_coord: bool = False, @@ -2539,8 +2632,8 @@ def geosearch( See https://valkey.io/commands/geosearch/ for more details. Args: - key (str): The key of the sorted set representing geospatial data. - search_from (Union[str, GeospatialData]): The location to search from. Can be specified either as a member + key (TEncodable): The key of the sorted set representing geospatial data. + search_from (Union[TEncodable, GeospatialData]): The location to search from. Can be specified either as a member from the sorted set or as a geospatial data (see `GeospatialData`). search_by (Union[GeoSearchByRadius, GeoSearchByBox]): The search criteria. For circular area search, see `GeoSearchByRadius`. @@ -2557,9 +2650,9 @@ def geosearch( with_hash (bool): Whether to include geohash of the returned items. Defaults to False. Command Response: - List[Union[str, List[Union[str, float, int, List[float]]]]]: By default, returns a list of members (locations) names. + List[Union[bytes, List[Union[bytes, float, int, List[float]]]]]: By default, returns a list of members (locations) names. If any of `with_coord`, `with_dist` or `with_hash` are True, returns an array of arrays, we're each sub array represents a single item in the following order: - (str): The member (location) name. + (bytes): The member (location) name. (float): The distance from the center as a floating point number, in the same unit specified in the radius, if `with_dist` is set to True. (int): The Geohash integer, if `with_hash` is set to True. List[float]: The coordinates as a two item [longitude,latitude] array, if `with_coord` is set to True. @@ -2569,7 +2662,7 @@ def geosearch( args = _create_geosearch_args( [key], search_from, - seach_by, + search_by, order_by, count, with_coord, @@ -2581,9 +2674,9 @@ def geosearch( def geosearchstore( self: TTransaction, - destination: str, - source: str, - search_from: Union[str, GeospatialData], + destination: TEncodable, + source: TEncodable, + search_from: Union[TEncodable, GeospatialData], search_by: Union[GeoSearchByRadius, GeoSearchByBox], count: Optional[GeoSearchCount] = None, store_dist: bool = False, @@ -2597,9 +2690,9 @@ def geosearchstore( See https://valkey.io/commands/geosearch/ for more details. Args: - destination (str): The key to store the search results. - source (str): The key of the sorted set representing geospatial data to search from. - search_from (Union[str, GeospatialData]): The location to search from. Can be specified either as a member + destination (TEncodable): The key to store the search results. + source (TEncodable): The key of the sorted set representing geospatial data to search from. + search_from (Union[TEncodable, GeospatialData]): The location to search from. Can be specified either as a member from the sorted set or as a geospatial data (see `GeospatialData`). search_by (Union[GeoSearchByRadius, GeoSearchByBox]): The search criteria. For circular area search, see `GeoSearchByRadius`. @@ -2632,8 +2725,8 @@ def geosearchstore( def zadd( self: TTransaction, - key: str, - members_scores: Mapping[str, float], + key: TEncodable, + members_scores: Mapping[TEncodable, float], existing_options: Optional[ConditionalChange] = None, update_condition: Optional[UpdateOptions] = None, changed: bool = False, @@ -2645,8 +2738,8 @@ def zadd( See https://redis.io/commands/zadd/ for more details. Args: - key (str): The key of the sorted set. - members_scores (Mapping[str, float]): A mapping of members to their corresponding scores. + key (TEncodable): The key of the sorted set. + members_scores (Mapping[TEncodable, float]): A mapping of members to their corresponding scores. existing_options (Optional[ConditionalChange]): Options for handling existing members. - NX: Only add new elements. - XX: Only update existing elements. @@ -2685,8 +2778,8 @@ def zadd( def zadd_incr( self: TTransaction, - key: str, - member: str, + key: TEncodable, + member: TEncodable, increment: float, existing_options: Optional[ConditionalChange] = None, update_condition: Optional[UpdateOptions] = None, @@ -2699,8 +2792,8 @@ def zadd_incr( See https://redis.io/commands/zadd/ for more details. Args: - key (str): The key of the sorted set. - member (str): A member in the sorted set to increment. + key (TEncodable): The key of the sorted set. + member (TEncodable): A member in the sorted set to increment. increment (float): The score to increment the member. existing_options (Optional[ConditionalChange]): Options for handling the member's existence. - NX: Only increment a member that doesn't exist. @@ -2732,14 +2825,14 @@ def zadd_incr( args += [str(increment), member] return self.append_command(RequestType.ZAdd, args) - def zcard(self: TTransaction, key: str) -> TTransaction: + def zcard(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns the cardinality (number of elements) of the sorted set stored at `key`. See https://redis.io/commands/zcard/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. Commands response: int: The number of elements in the sorted set. @@ -2749,7 +2842,7 @@ def zcard(self: TTransaction, key: str) -> TTransaction: def zcount( self: TTransaction, - key: str, + key: TEncodable, min_score: Union[InfBound, ScoreBoundary], max_score: Union[InfBound, ScoreBoundary], ) -> TTransaction: @@ -2759,7 +2852,7 @@ def zcount( See https://redis.io/commands/zcount/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. min_score (Union[InfBound, ScoreBoundary]): The minimum score to count from. Can be an instance of InfBound representing positive/negative infinity, or ScoreBoundary representing a specific score and inclusivity. @@ -2785,7 +2878,10 @@ def zcount( return self.append_command(RequestType.ZCount, [key, score_min, score_max]) def zincrby( - self: TTransaction, key: str, increment: float, member: str + self: TTransaction, + key: TEncodable, + increment: float, + member: TEncodable, ) -> TTransaction: """ Increments the score of `member` in the sorted set stored at `key` by `increment`. @@ -2795,9 +2891,9 @@ def zincrby( See https://valkey.io/commands/zincrby/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. increment (float): The score increment. - member (str): A member of the sorted set. + member (TEncodable): A member of the sorted set. Commands response: float: The new score of `member`. @@ -2805,7 +2901,7 @@ def zincrby( return self.append_command(RequestType.ZIncrBy, [key, str(increment), member]) def zpopmax( - self: TTransaction, key: str, count: Optional[int] = None + self: TTransaction, key: TEncodable, count: Optional[int] = None ) -> TTransaction: """ Removes and returns the members with the highest scores from the sorted set stored at `key`. @@ -2815,19 +2911,21 @@ def zpopmax( See https://redis.io/commands/zpopmax for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. count (Optional[int]): Specifies the quantity of members to pop. If not specified, pops one member. If `count` is higher than the sorted set's cardinality, returns all members and their scores, ordered from highest to lowest. Commands response: - Mapping[str, float]: A map of the removed members and their scores, ordered from the one with the highest score to the one with the lowest. + Mapping[bytes, float]: A map of the removed members and their scores, ordered from the one with the highest score to the one with the lowest. If `key` doesn't exist, it will be treated as an empy sorted set and the command returns an empty map. """ return self.append_command( RequestType.ZPopMax, [key, str(count)] if count else [key] ) - def bzpopmax(self: TTransaction, keys: List[str], timeout: float) -> TTransaction: + def bzpopmax( + self: TTransaction, keys: List[TEncodable], timeout: float + ) -> TTransaction: """ Pops the member with the highest score from the first non-empty sorted set, with the given keys being checked in the order that they are given. Blocks the connection when there are no members to remove from any of the given @@ -2840,18 +2938,18 @@ def bzpopmax(self: TTransaction, keys: List[str], timeout: float) -> TTransactio See https://valkey.io/commands/bzpopmax for more details. Args: - keys (List[str]): The keys of the sorted sets. + keys (List[TEncodable]): The keys of the sorted sets. timeout (float): The number of seconds to wait for a blocking operation to complete. A value of 0 will block indefinitely. Command response: - Optional[List[Union[str, float]]]: An array containing the key where the member was popped out, the member itself, + Optional[List[Union[bytes, float]]]: An array containing the key where the member was popped out, the member itself, and the member score. If no member could be popped and the `timeout` expired, returns None. """ return self.append_command(RequestType.BZPopMax, keys + [str(timeout)]) def zpopmin( - self: TTransaction, key: str, count: Optional[int] = None + self: TTransaction, key: TEncodable, count: Optional[int] = None ) -> TTransaction: """ Removes and returns the members with the lowest scores from the sorted set stored at `key`. @@ -2861,19 +2959,21 @@ def zpopmin( See https://redis.io/commands/zpopmin for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. count (Optional[int]): Specifies the quantity of members to pop. If not specified, pops one member. If `count` is higher than the sorted set's cardinality, returns all members and their scores. Commands response: - Mapping[str, float]: A map of the removed members and their scores, ordered from the one with the lowest score to the one with the highest. + Mapping[bytes, float]: A map of the removed members and their scores, ordered from the one with the lowest score to the one with the highest. If `key` doesn't exist, it will be treated as an empty sorted set and the command returns an empty map. """ return self.append_command( RequestType.ZPopMin, [key, str(count)] if count else [key] ) - def bzpopmin(self: TTransaction, keys: List[str], timeout: float) -> TTransaction: + def bzpopmin( + self: TTransaction, keys: List[TEncodable], timeout: float + ) -> TTransaction: """ Pops the member with the lowest score from the first non-empty sorted set, with the given keys being checked in the order that they are given. Blocks the connection when there are no members to remove from any of the given @@ -2886,19 +2986,19 @@ def bzpopmin(self: TTransaction, keys: List[str], timeout: float) -> TTransactio See https://valkey.io/commands/bzpopmin for more details. Args: - keys (List[str]): The keys of the sorted sets. + keys (List[TEncodable]): The keys of the sorted sets. timeout (float): The number of seconds to wait for a blocking operation to complete. A value of 0 will block indefinitely. Command response: - Optional[List[Union[str, float]]]: An array containing the key where the member was popped out, the member itself, + Optional[List[Union[bytes, float]]]: An array containing the key where the member was popped out, the member itself, and the member score. If no member could be popped and the `timeout` expired, returns None. """ return self.append_command(RequestType.BZPopMin, keys + [str(timeout)]) def zrange( self: TTransaction, - key: str, + key: TEncodable, range_query: Union[RangeByIndex, RangeByLex, RangeByScore], reverse: bool = False, ) -> TTransaction: @@ -2910,7 +3010,7 @@ def zrange( See https://redis.io/commands/zrange/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. range_query (Union[RangeByIndex, RangeByLex, RangeByScore]): The range query object representing the type of range query to perform. - For range queries by index (rank), use RangeByIndex. - For range queries by lexicographical order, use RangeByLex. @@ -2918,7 +3018,7 @@ def zrange( reverse (bool): If True, reverses the sorted set, with index 0 as the element with the highest score. Commands response: - List[str]: A list of elements within the specified range. + List[bytes]: A list of elements within the specified range. If `key` does not exist, it is treated as an empty sorted set, and the command returns an empty array. """ args = _create_zrange_args(key, range_query, reverse, with_scores=False) @@ -2927,7 +3027,7 @@ def zrange( def zrange_withscores( self: TTransaction, - key: str, + key: TEncodable, range_query: Union[RangeByIndex, RangeByScore], reverse: bool = False, ) -> TTransaction: @@ -2938,14 +3038,14 @@ def zrange_withscores( See https://redis.io/commands/zrange/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. range_query (Union[RangeByIndex, RangeByScore]): The range query object representing the type of range query to perform. - For range queries by index (rank), use RangeByIndex. - For range queries by score, use RangeByScore. reverse (bool): If True, reverses the sorted set, with index 0 as the element with the highest score. Commands response: - Mapping[str , float]: A map of elements and their scores within the specified range. + Mapping[bytes , float]: A map of elements and their scores within the specified range. If `key` does not exist, it is treated as an empty sorted set, and the command returns an empty map. """ args = _create_zrange_args(key, range_query, reverse, with_scores=True) @@ -2954,8 +3054,8 @@ def zrange_withscores( def zrangestore( self: TTransaction, - destination: str, - source: str, + destination: TEncodable, + source: TEncodable, range_query: Union[RangeByIndex, RangeByLex, RangeByScore], reverse: bool = False, ) -> TTransaction: @@ -2969,8 +3069,8 @@ def zrangestore( See https://valkey.io/commands/zrangestore for more details. Args: - destination (str): The key for the destination sorted set. - source (str): The key of the source sorted set. + destination (TEncodable): The key for the destination sorted set. + source (TEncodable): The key of the source sorted set. range_query (Union[RangeByIndex, RangeByLex, RangeByScore]): The range query object representing the type of range query to perform. - For range queries by index (rank), use RangeByIndex. - For range queries by lexicographical order, use RangeByLex. @@ -2986,8 +3086,8 @@ def zrangestore( def zrank( self: TTransaction, - key: str, - member: str, + key: TEncodable, + member: TEncodable, ) -> TTransaction: """ Returns the rank of `member` in the sorted set stored at `key`, with scores ordered from low to high. @@ -2997,8 +3097,8 @@ def zrank( To get the rank of `member` with its score, see `zrank_withscore`. Args: - key (str): The key of the sorted set. - member (str): The member whose rank is to be retrieved. + key (TEncodable): The key of the sorted set. + member (TEncodable): The member whose rank is to be retrieved. Commands response: Optional[int]: The rank of `member` in the sorted set. @@ -3008,8 +3108,8 @@ def zrank( def zrank_withscore( self: TTransaction, - key: str, - member: str, + key: TEncodable, + member: TEncodable, ) -> TTransaction: """ Returns the rank of `member` in the sorted set stored at `key` with its score, where scores are ordered from the lowest to highest. @@ -3017,8 +3117,8 @@ def zrank_withscore( See https://redis.io/commands/zrank for more details. Args: - key (str): The key of the sorted set. - member (str): The member whose rank is to be retrieved. + key (TEncodable): The key of the sorted set. + member (TEncodable): The member whose rank is to be retrieved. Commands response: Optional[List[Union[int, float]]]: A list containing the rank and score of `member` in the sorted set. @@ -3028,7 +3128,9 @@ def zrank_withscore( """ return self.append_command(RequestType.ZRank, [key, member, "WITHSCORE"]) - def zrevrank(self: TTransaction, key: str, member: str) -> TTransaction: + def zrevrank( + self: TTransaction, key: TEncodable, member: TEncodable + ) -> TTransaction: """ Returns the rank of `member` in the sorted set stored at `key`, where scores are ordered from the highest to lowest, starting from `0`. @@ -3038,8 +3140,8 @@ def zrevrank(self: TTransaction, key: str, member: str) -> TTransaction: See https://valkey.io/commands/zrevrank for more details. Args: - key (str): The key of the sorted set. - member (str): The member whose rank is to be retrieved. + key (TEncodable): The key of the sorted set. + member (TEncodable): The member whose rank is to be retrieved. Command response: Optional[int]: The rank of `member` in the sorted set, where ranks are ordered from high to low based on scores. @@ -3047,7 +3149,9 @@ def zrevrank(self: TTransaction, key: str, member: str) -> TTransaction: """ return self.append_command(RequestType.ZRevRank, [key, member]) - def zrevrank_withscore(self: TTransaction, key: str, member: str) -> TTransaction: + def zrevrank_withscore( + self: TTransaction, key: TEncodable, member: TEncodable + ) -> TTransaction: """ Returns the rank of `member` in the sorted set stored at `key` with its score, where scores are ordered from the highest to lowest, starting from `0`. @@ -3055,8 +3159,8 @@ def zrevrank_withscore(self: TTransaction, key: str, member: str) -> TTransactio See https://valkey.io/commands/zrevrank for more details. Args: - key (str): The key of the sorted set. - member (str): The member whose rank is to be retrieved. + key (TEncodable): The key of the sorted set. + member (TEncodable): The member whose rank is to be retrieved. Command response: Optional[List[Union[int, float]]]: A list containing the rank (as `int`) and score (as `float`) of `member` @@ -3069,8 +3173,8 @@ def zrevrank_withscore(self: TTransaction, key: str, member: str) -> TTransactio def zrem( self: TTransaction, - key: str, - members: List[str], + key: TEncodable, + members: List[TEncodable], ) -> TTransaction: """ Removes the specified members from the sorted set stored at `key`. @@ -3079,8 +3183,8 @@ def zrem( See https://redis.io/commands/zrem/ for more details. Args: - key (str): The key of the sorted set. - members (List[str]): A list of members to remove from the sorted set. + key (TEncodable): The key of the sorted set. + members (List[TEncodable]): A list of members to remove from the sorted set. Commands response: int: The number of members that were removed from the sorted set, not including non-existing members. @@ -3090,7 +3194,7 @@ def zrem( def zremrangebyscore( self: TTransaction, - key: str, + key: TEncodable, min_score: Union[InfBound, ScoreBoundary], max_score: Union[InfBound, ScoreBoundary], ) -> TTransaction: @@ -3100,7 +3204,7 @@ def zremrangebyscore( See https://redis.io/commands/zremrangebyscore/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. min_score (Union[InfBound, ScoreBoundary]): The minimum score to remove from. Can be an instance of InfBound representing positive/negative infinity, or ScoreBoundary representing a specific score and inclusivity. @@ -3129,7 +3233,7 @@ def zremrangebyscore( def zremrangebylex( self: TTransaction, - key: str, + key: TEncodable, min_lex: Union[InfBound, LexBoundary], max_lex: Union[InfBound, LexBoundary], ) -> TTransaction: @@ -3140,7 +3244,7 @@ def zremrangebylex( See https://redis.io/commands/zremrangebylex/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. min_lex (Union[InfBound, LexBoundary]): The minimum bound of the lexicographical range. Can be an instance of `InfBound` representing positive/negative infinity, or `LexBoundary` representing a specific lex and inclusivity. @@ -3166,7 +3270,7 @@ def zremrangebylex( def zremrangebyrank( self: TTransaction, - key: str, + key: TEncodable, start: int, end: int, ) -> TTransaction: @@ -3178,7 +3282,7 @@ def zremrangebyrank( See https://valkey.io/commands/zremrangebyrank/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. start (int): The starting point of the range. end (int): The end of the range. @@ -3194,7 +3298,7 @@ def zremrangebyrank( def zlexcount( self: TTransaction, - key: str, + key: TEncodable, min_lex: Union[InfBound, LexBoundary], max_lex: Union[InfBound, LexBoundary], ) -> TTransaction: @@ -3204,7 +3308,7 @@ def zlexcount( See https://redis.io/commands/zlexcount/ for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. min_lex (Union[InfBound, LexBoundary]): The minimum lexicographical value to count from. Can be an instance of InfBound representing positive/negative infinity, or LexBoundary representing a specific lexicographical value and inclusivity. @@ -3228,15 +3332,15 @@ def zlexcount( RequestType.ZLexCount, [key, min_lex_arg, max_lex_arg] ) - def zscore(self: TTransaction, key: str, member: str) -> TTransaction: + def zscore(self: TTransaction, key: TEncodable, member: TEncodable) -> TTransaction: """ Returns the score of `member` in the sorted set stored at `key`. See https://redis.io/commands/zscore/ for more details. Args: - key (str): The key of the sorted set. - member (str): The member whose score is to be retrieved. + key (TEncodable): The key of the sorted set. + member (TEncodable): The member whose score is to be retrieved. Commands response: Optional[float]: The score of the member. @@ -3245,15 +3349,17 @@ def zscore(self: TTransaction, key: str, member: str) -> TTransaction: """ return self.append_command(RequestType.ZScore, [key, member]) - def zmscore(self: TTransaction, key: str, members: List[str]) -> TTransaction: + def zmscore( + self: TTransaction, key: TEncodable, members: List[TEncodable] + ) -> TTransaction: """ Returns the scores associated with the specified `members` in the sorted set stored at `key`. See https://valkey.io/commands/zmscore for more details. Args: - key (str): The key of the sorted set. - members (List[str]): A list of members in the sorted set. + key (TEncodable): The key of the sorted set. + members (List[TEncodable]): A list of members in the sorted set. Command response: List[Optional[float]]: A list of scores corresponding to `members`. @@ -3261,7 +3367,7 @@ def zmscore(self: TTransaction, key: str, members: List[str]) -> TTransaction: """ return self.append_command(RequestType.ZMScore, [key] + members) - def zdiff(self: TTransaction, keys: List[str]) -> TTransaction: + def zdiff(self: TTransaction, keys: List[TEncodable]) -> TTransaction: """ Returns the difference between the first sorted set and all the successive sorted sets. To get the elements with their scores, see `zdiff_withscores`. @@ -3269,26 +3375,28 @@ def zdiff(self: TTransaction, keys: List[str]) -> TTransaction: See https://valkey.io/commands/zdiff for more details. Args: - keys (List[str]): The keys of the sorted sets. + keys (List[TEncodable]): The keys of the sorted sets. Command response: - List[str]: A list of elements representing the difference between the sorted sets. + List[bytes]: A list of elements representing the difference between the sorted sets. If the first key does not exist, it is treated as an empty sorted set, and the command returns an empty list. """ - return self.append_command(RequestType.ZDiff, [str(len(keys))] + keys) + args: List[TEncodable] = [str(len(keys))] + args.extend(keys) + return self.append_command(RequestType.ZDiff, args) - def zdiff_withscores(self: TTransaction, keys: List[str]) -> TTransaction: + def zdiff_withscores(self: TTransaction, keys: List[TEncodable]) -> TTransaction: """ Returns the difference between the first sorted set and all the successive sorted sets, with the associated scores. See https://valkey.io/commands/zdiff for more details. Args: - keys (List[str]): The keys of the sorted sets. + keys (List[TEncodable]): The keys of the sorted sets. Command response: - Mapping[str, float]: A mapping of elements and their scores representing the difference between the sorted sets. + Mapping[bytes, float]: A mapping of elements and their scores representing the difference between the sorted sets. If the first `key` does not exist, it is treated as an empty sorted set, and the command returns an empty list. """ @@ -3297,7 +3405,9 @@ def zdiff_withscores(self: TTransaction, keys: List[str]) -> TTransaction: ) def zdiffstore( - self: TTransaction, destination: str, keys: List[str] + self: TTransaction, + destination: TEncodable, + keys: List[TEncodable], ) -> TTransaction: """ Calculates the difference between the first sorted set and all the successive sorted sets at `keys` and stores @@ -3307,8 +3417,8 @@ def zdiffstore( See https://valkey.io/commands/zdiffstore for more details. Args: - destination (str): The key for the resulting sorted set. - keys (List[str]): The keys of the sorted sets to compare. + destination (TEncodable): The key for the resulting sorted set. + keys (List[TEncodable]): The keys of the sorted sets to compare. Command response: int: The number of members in the resulting sorted set stored at `destination`. @@ -3319,7 +3429,7 @@ def zdiffstore( def zinter( self: TTransaction, - keys: List[str], + keys: List[TEncodable], ) -> TTransaction: """ Computes the intersection of sorted sets given by the specified `keys` and returns a list of intersecting elements. @@ -3327,16 +3437,18 @@ def zinter( See https://valkey.io/commands/zinter/ for more details. Args: - keys (List[str]): The keys of the sorted sets. + keys (List[TEncodable]): The keys of the sorted sets. Command response: - List[str]: The resulting array of intersecting elements. + List[bytes]: The resulting array of intersecting elements. """ - return self.append_command(RequestType.ZInter, [str(len(keys))] + keys) + args: List[TEncodable] = [str(len(keys))] + args.extend(keys) + return self.append_command(RequestType.ZInter, args) def zinter_withscores( self: TTransaction, - keys: Union[List[str], List[Tuple[str, float]]], + keys: Union[List[TEncodable], List[Tuple[TEncodable, float]]], aggregation_type: Optional[AggregationType] = None, ) -> TTransaction: """ @@ -3345,14 +3457,14 @@ def zinter_withscores( See https://valkey.io/commands/zinter/ for more details. Args: - keys (Union[List[str], List[Tuple[str, float]]]): The keys of the sorted sets with possible formats: - List[str] - for keys only. - List[Tuple[str, float]] - for weighted keys with score multipliers. + keys (Union[List[TEncodable], List[Tuple[TEncodable, float]]]): The keys of the sorted sets with possible formats: + List[TEncodable] - for keys only. + List[Tuple[TEncodable, float]] - for weighted keys with score multipliers. aggregation_type (Optional[AggregationType]): Specifies the aggregation strategy to apply when combining the scores of elements. See `AggregationType`. Command response: - Mapping[str, float]: The resulting sorted set with scores. + Mapping[bytes, float]: The resulting sorted set with scores. """ args = _create_zinter_zunion_cmd_args(keys, aggregation_type) args.append("WITHSCORES") @@ -3360,8 +3472,8 @@ def zinter_withscores( def zinterstore( self: TTransaction, - destination: str, - keys: Union[List[str], List[Tuple[str, float]]], + destination: TEncodable, + keys: Union[List[TEncodable], List[Tuple[TEncodable, float]]], aggregation_type: Optional[AggregationType] = None, ) -> TTransaction: """ @@ -3373,10 +3485,10 @@ def zinterstore( See https://valkey.io/commands/zinterstore/ for more details. Args: - destination (str): The key of the destination sorted set. - keys (Union[List[str], List[Tuple[str, float]]]): The keys of the sorted sets with possible formats: - List[str] - for keys only. - List[Tuple[str, float]]] - for weighted keys with score multipliers. + destination (TEncodable): The key of the destination sorted set. + keys (Union[List[TEncodable], Tuple[TEncodable, float]]]): The keys of the sorted sets with possible formats: + List[TEncodable] - for keys only. + List[Tuple[TEncodable, float]]] - for weighted keys with score multipliers. aggregation_type (Optional[AggregationType]): Specifies the aggregation strategy to apply when combining the scores of elements. See `AggregationType`. @@ -3388,7 +3500,7 @@ def zinterstore( def zunion( self: TTransaction, - keys: List[str], + keys: List[TEncodable], ) -> TTransaction: """ Computes the union of sorted sets given by the specified `keys` and returns a list of union elements. @@ -3396,16 +3508,18 @@ def zunion( See https://valkey.io/commands/zunion/ for more details. Args: - keys (List[str]): The keys of the sorted sets. + keys (List[TEncodable]): The keys of the sorted sets. Command response: - List[str]: The resulting array of union elements. + List[bytes]: The resulting array of union elements. """ - return self.append_command(RequestType.ZUnion, [str(len(keys))] + keys) + args: List[TEncodable] = [str(len(keys))] + args.extend(keys) + return self.append_command(RequestType.ZUnion, args) def zunion_withscores( self: TTransaction, - keys: Union[List[str], List[Tuple[str, float]]], + keys: Union[List[TEncodable], List[Tuple[TEncodable, float]]], aggregation_type: Optional[AggregationType] = None, ) -> TTransaction: """ @@ -3414,14 +3528,14 @@ def zunion_withscores( See https://valkey.io/commands/zunion/ for more details. Args: - keys (Union[List[str], List[Tuple[str, float]]]): The keys of the sorted sets with possible formats: - List[str] - for keys only. - List[Tuple[str, float]] - for weighted keys with score multipliers. + keys (Union[List[TEncodable], List[Tuple[TEncodable, float]]]): The keys of the sorted sets with possible formats: + List[TEncodable] - for keys only. + List[Tuple[TEncodable, float]] - for weighted keys with score multipliers. aggregation_type (Optional[AggregationType]): Specifies the aggregation strategy to apply when combining the scores of elements. See `AggregationType`. Command response: - Mapping[str, float]: The resulting sorted set with scores. + Mapping[bytes, float]: The resulting sorted set with scores. """ args = _create_zinter_zunion_cmd_args(keys, aggregation_type) args.append("WITHSCORES") @@ -3429,9 +3543,9 @@ def zunion_withscores( def zunionstore( self: TTransaction, - destination: str, - keys: Union[List[str], List[Tuple[str, float]]], - aggregation_type: Optional[AggregationType] = None, + destination: TEncodable, + keys: Union[List[TEncodable], List[Tuple[TEncodable, float]]], + aggregation_type: Optional[Optional[AggregationType]] = None, ) -> TTransaction: """ Computes the union of sorted sets given by the specified `keys` and stores the result in `destination`. @@ -3442,10 +3556,10 @@ def zunionstore( see https://valkey.io/commands/zunionstore/ for more details. Args: - destination (str): The key of the destination sorted set. - keys (Union[List[str], List[Tuple[str, float]]]): The keys of the sorted sets with possible formats: - List[str] - for keys only. - List[Tuple[str, float]]] - for weighted keys with score multipliers. + destination (TEncodable): The key of the destination sorted set. + keys (Union[List[TEncodable], List[Tuple[TEncodable, float]]]): The keys of the sorted sets with possible formats: + List[TEncodable] - for keys only. + List[Tuple[TEncodable, float]] - for weighted keys with score multipliers. aggregation_type (Optional[AggregationType]): Specifies the aggregation strategy to apply when combining the scores of elements. See `AggregationType`. @@ -3455,41 +3569,43 @@ def zunionstore( args = _create_zinter_zunion_cmd_args(keys, aggregation_type, destination) return self.append_command(RequestType.ZUnionStore, args) - def zrandmember(self: TTransaction, key: str) -> TTransaction: + def zrandmember(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns a random member from the sorted set stored at 'key'. See https://valkey.io/commands/zrandmember for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. Command response: - Optional[str]: A random member from the sorted set. + Optional[bytes]: A random member from the sorted set. If the sorted set does not exist or is empty, the response will be None. """ return self.append_command(RequestType.ZRandMember, [key]) - def zrandmember_count(self: TTransaction, key: str, count: int) -> TTransaction: + def zrandmember_count( + self: TTransaction, key: TEncodable, count: int + ) -> TTransaction: """ Retrieves up to the absolute value of `count` random members from the sorted set stored at 'key'. See https://valkey.io/commands/zrandmember for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. count (int): The number of members to return. If `count` is positive, returns unique members. If `count` is negative, allows for duplicates members. Command response: - List[str]: A list of members from the sorted set. + List[bytes]: A list of members from the sorted set. If the sorted set does not exist or is empty, the response will be an empty list. """ return self.append_command(RequestType.ZRandMember, [key, str(count)]) def zrandmember_withscores( - self: TTransaction, key: str, count: int + self: TTransaction, key: TEncodable, count: int ) -> TTransaction: """ Retrieves up to the absolute value of `count` random members along with their scores from the sorted set @@ -3498,13 +3614,13 @@ def zrandmember_withscores( See https://valkey.io/commands/zrandmember for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. count (int): The number of members to return. If `count` is positive, returns unique members. If `count` is negative, allows for duplicates members. Command response: - List[List[Union[str, float]]]: A list of `[member, score]` lists, where `member` is a random member from + List[List[Union[bytes, float]]]: A list of `[member, score]` lists, where `member` is a random member from the sorted set and `score` is the associated score. If the sorted set does not exist or is empty, the response will be an empty list. """ @@ -3514,7 +3630,7 @@ def zrandmember_withscores( def zmpop( self: TTransaction, - keys: List[str], + keys: List[TEncodable], filter: ScoreFilter, count: Optional[int] = None, ) -> TTransaction: @@ -3526,13 +3642,13 @@ def zmpop( See https://valkey.io/commands/zmpop for more details. Args: - keys (List[str]): The keys of the sorted sets. + keys (List[TEncodable]): The keys of the sorted sets. modifier (ScoreFilter): The element pop criteria - either ScoreFilter.MIN or ScoreFilter.MAX to pop members with the lowest/highest scores accordingly. count (Optional[int]): The number of elements to pop. Command response: - Optional[List[Union[str, Mapping[str, float]]]]: A two-element list containing the key name of the set from + Optional[List[Union[bytes, Mapping[bytes, float]]]]: A two-element list containing the key name of the set from which elements were popped, and a member-score mapping of the popped elements. If no members could be popped, returns None. @@ -3546,7 +3662,7 @@ def zmpop( def bzmpop( self: TTransaction, - keys: List[str], + keys: List[TEncodable], modifier: ScoreFilter, timeout: float, count: Optional[int] = None, @@ -3567,7 +3683,7 @@ def bzmpop( `BZMPOP` is a client blocking command, see https://github.com/aws/glide-for-redis/wiki/General-Concepts#blocking-commands for more details and best practices. Args: - keys (List[str]): The keys of the sorted sets. + keys (List[TEncodable]): The keys of the sorted sets. modifier (ScoreFilter): The element pop criteria - either ScoreFilter.MIN or ScoreFilter.MAX to pop members with the lowest/highest scores accordingly. timeout (float): The number of seconds to wait for a blocking operation to complete. A value of 0 will @@ -3575,7 +3691,7 @@ def bzmpop( count (Optional[int]): The number of elements to pop. Command response: - Optional[List[Union[str, Mapping[str, float]]]]: A two-element list containing the key name of the set from + Optional[List[Union[bytes, Mapping[bytes, float]]]]: A two-element list containing the key name of the set from which elements were popped, and a member-score mapping. If no members could be popped and the timeout expired, returns None. @@ -3588,7 +3704,7 @@ def bzmpop( return self.append_command(RequestType.BZMPop, args) def zintercard( - self: TTransaction, keys: List[str], limit: Optional[int] = None + self: TTransaction, keys: List[TEncodable], limit: Optional[int] = None ) -> TTransaction: """ Returns the cardinality of the intersection of the sorted sets specified by `keys`. When provided with the @@ -3598,7 +3714,7 @@ def zintercard( See https://valkey.io/commands/zintercard for more details. Args: - keys (List[str]): The keys of the sorted sets to intersect. + keys (List[TEncodable]): The keys of the sorted sets to intersect. limit (Optional[int]): An optional argument that can be used to specify a maximum number for the intersection cardinality. If limit is not supplied, or if it is set to 0, there will be no limit. @@ -3623,7 +3739,9 @@ def dbsize(self: TTransaction) -> TTransaction: """ return self.append_command(RequestType.DBSize, []) - def pfadd(self: TTransaction, key: str, elements: List[str]) -> TTransaction: + def pfadd( + self: TTransaction, key: TEncodable, elements: List[TEncodable] + ) -> TTransaction: """ Adds all elements to the HyperLogLog data structure stored at the specified `key`. Creates a new structure if the `key` does not exist. @@ -3632,8 +3750,8 @@ def pfadd(self: TTransaction, key: str, elements: List[str]) -> TTransaction: See https://redis.io/commands/pfadd/ for more details. Args: - key (str): The key of the HyperLogLog data structure to add elements into. - elements (List[str]): A list of members to add to the HyperLogLog stored at `key`. + key (TEncodable): The key of the HyperLogLog data structure to add elements into. + elements (List[TEncodable]): A list of members to add to the HyperLogLog stored at `key`. Commands response: int: If the HyperLogLog is newly created, or if the HyperLogLog approximated cardinality is @@ -3641,7 +3759,7 @@ def pfadd(self: TTransaction, key: str, elements: List[str]) -> TTransaction: """ return self.append_command(RequestType.PfAdd, [key] + elements) - def pfcount(self: TTransaction, keys: List[str]) -> TTransaction: + def pfcount(self: TTransaction, keys: List[TEncodable]) -> TTransaction: """ Estimates the cardinality of the data stored in a HyperLogLog structure for a single key or calculates the combined cardinality of multiple keys by merging their HyperLogLogs temporarily. @@ -3649,7 +3767,7 @@ def pfcount(self: TTransaction, keys: List[str]) -> TTransaction: See https://valkey.io/commands/pfcount for more details. Args: - keys (List[str]): The keys of the HyperLogLog data structures to be analyzed. + keys (List[TEncodable]): The keys of the HyperLogLog data structures to be analyzed. Command response: int: The approximated cardinality of given HyperLogLog data structures. @@ -3658,7 +3776,9 @@ def pfcount(self: TTransaction, keys: List[str]) -> TTransaction: return self.append_command(RequestType.PfCount, keys) def pfmerge( - self: TTransaction, destination: str, source_keys: List[str] + self: TTransaction, + destination: TEncodable, + source_keys: List[TEncodable], ) -> TTransaction: """ Merges multiple HyperLogLog values into a unique value. If the destination variable exists, it is treated as one @@ -3667,8 +3787,8 @@ def pfmerge( See https://valkey.io/commands/pfmerge for more details. Args: - destination (str): The key of the destination HyperLogLog where the merged data sets will be stored. - source_keys (List[str]): The keys of the HyperLogLog structures to be merged. + destination (TEncodable): The key of the destination HyperLogLog where the merged data sets will be stored. + source_keys (List[TEncodable]): The keys of the HyperLogLog structures to be merged. Command response: OK: A simple OK response. @@ -3676,7 +3796,9 @@ def pfmerge( return self.append_command(RequestType.PfMerge, [destination] + source_keys) def bitcount( - self: TTransaction, key: str, options: Optional[OffsetOptions] = None + self: TTransaction, + key: TEncodable, + options: Optional[OffsetOptions] = None, ) -> TTransaction: """ Counts the number of set bits (population counting) in a string stored at `key`. The `options` argument can @@ -3685,7 +3807,7 @@ def bitcount( See https://valkey.io/commands/bitcount for more details. Args: - key (str): The key for the string to count the set bits of. + key (TEncodable): The key for the string to count the set bits of. options (Optional[OffsetOptions]): The offset options. Command response: @@ -3693,13 +3815,15 @@ def bitcount( If `options` is not provided, returns the number of set bits in the string stored at `key`. Otherwise, if `key` is missing, returns `0` as it is treated as an empty string. """ - args = [key] + args: List[TEncodable] = [key] if options is not None: - args = args + options.to_args() + args.extend(options.to_args()) return self.append_command(RequestType.BitCount, args) - def setbit(self: TTransaction, key: str, offset: int, value: int) -> TTransaction: + def setbit( + self: TTransaction, key: TEncodable, offset: int, value: int + ) -> TTransaction: """ Sets or clears the bit at `offset` in the string value stored at `key`. The `offset` is a zero-based index, with `0` being the first element of the list, `1` being the next element, and so on. The `offset` must be less @@ -3709,7 +3833,7 @@ def setbit(self: TTransaction, key: str, offset: int, value: int) -> TTransactio See https://valkey.io/commands/setbit for more details. Args: - key (str): The key of the string. + key (TEncodable): The key of the string. offset (int): The index of the bit to be set. value (int): The bit value to set at `offset`. The value must be `0` or `1`. @@ -3718,7 +3842,7 @@ def setbit(self: TTransaction, key: str, offset: int, value: int) -> TTransactio """ return self.append_command(RequestType.SetBit, [key, str(offset), str(value)]) - def getbit(self: TTransaction, key: str, offset: int) -> TTransaction: + def getbit(self: TTransaction, key: TEncodable, offset: int) -> TTransaction: """ Returns the bit value at `offset` in the string value stored at `key`. `offset` should be greater than or equal to zero. @@ -3726,7 +3850,7 @@ def getbit(self: TTransaction, key: str, offset: int) -> TTransaction: See https://valkey.io/commands/getbit for more details. Args: - key (str): The key of the string. + key (TEncodable): The key of the string. offset (int): The index of the bit to return. Command response: @@ -3736,7 +3860,10 @@ def getbit(self: TTransaction, key: str, offset: int) -> TTransaction: return self.append_command(RequestType.GetBit, [key, str(offset)]) def bitpos( - self: TTransaction, key: str, bit: int, start: Optional[int] = None + self: TTransaction, + key: TEncodable, + bit: int, + start: Optional[int] = None, ) -> TTransaction: """ Returns the position of the first bit matching the given `bit` value. The optional starting offset @@ -3747,7 +3874,7 @@ def bitpos( See https://valkey.io/commands/bitpos for more details. Args: - key (str): The key of the string. + key (TEncodable): The key of the string. bit (int): The bit value to match. Must be `0` or `1`. start (Optional[int]): The starting offset. @@ -3760,7 +3887,7 @@ def bitpos( def bitpos_interval( self: TTransaction, - key: str, + key: TEncodable, bit: int, start: int, end: int, @@ -3780,7 +3907,7 @@ def bitpos_interval( See https://valkey.io/commands/bitpos for more details. Args: - key (str): The key of the string. + key (TEncodable): The key of the string. bit (int): The bit value to match. Must be `0` or `1`. start (int): The starting offset. end (int): The ending offset. @@ -3802,8 +3929,8 @@ def bitpos_interval( def bitop( self: TTransaction, operation: BitwiseOperation, - destination: str, - keys: List[str], + destination: TEncodable, + keys: List[TEncodable], ) -> TTransaction: """ Perform a bitwise operation between multiple keys (containing string values) and store the result in the @@ -3813,8 +3940,8 @@ def bitop( Args: operation (BitwiseOperation): The bitwise operation to perform. - destination (str): The key that will store the resulting string. - keys (List[str]): The list of keys to perform the bitwise operation on. + destination (TEncodable): The key that will store the resulting string. + keys (List[TEncodable]): The list of keys to perform the bitwise operation on. Command response: int: The size of the string stored in `destination`. @@ -3824,7 +3951,9 @@ def bitop( ) def bitfield( - self: TTransaction, key: str, subcommands: List[BitFieldSubCommands] + self: TTransaction, + key: TEncodable, + subcommands: List[BitFieldSubCommands], ) -> TTransaction: """ Reads or modifies the array of bits representing the string that is held at `key` based on the specified @@ -3833,7 +3962,7 @@ def bitfield( See https://valkey.io/commands/bitfield for more details. Args: - key (str): The key of the string. + key (TEncodable): The key of the string. subcommands (List[BitFieldSubCommands]): The subcommands to be performed on the binary value of the string at `key`, which could be any of the following: - `BitFieldGet` @@ -3854,7 +3983,7 @@ def bitfield( return self.append_command(RequestType.BitField, args) def bitfield_read_only( - self: TTransaction, key: str, subcommands: List[BitFieldGet] + self: TTransaction, key: TEncodable, subcommands: List[BitFieldGet] ) -> TTransaction: """ Reads the array of bits representing the string that is held at `key` based on the specified `subcommands`. @@ -3862,7 +3991,7 @@ def bitfield_read_only( See https://valkey.io/commands/bitfield_ro for more details. Args: - key (str): The key of the string. + key (TEncodable): The key of the string. subcommands (List[BitFieldGet]): The "GET" subcommands to be performed. Command response: @@ -3873,29 +4002,29 @@ def bitfield_read_only( args = [key] + _create_bitfield_read_only_args(subcommands) return self.append_command(RequestType.BitFieldReadOnly, args) - def object_encoding(self: TTransaction, key: str) -> TTransaction: + def object_encoding(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns the internal encoding for the Redis object stored at `key`. See https://valkey.io/commands/object-encoding for more details. Args: - key (str): The `key` of the object to get the internal encoding of. + key (TEncodable): The `key` of the object to get the internal encoding of. Command response: - Optional[str]: If `key` exists, returns the internal encoding of the object stored at - `key` as a string. Otherwise, returns None. + Optional[bytes]: If `key` exists, returns the internal encoding of the object stored at + `key` as a bytes string. Otherwise, returns None. """ return self.append_command(RequestType.ObjectEncoding, [key]) - def object_freq(self: TTransaction, key: str) -> TTransaction: + def object_freq(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns the logarithmic access frequency counter of a Redis object stored at `key`. See https://valkey.io/commands/object-freq for more details. Args: - key (str): The key of the object to get the logarithmic access frequency counter of. + key (TEncodable): The key of the object to get the logarithmic access frequency counter of. Command response: Optional[int]: If `key` exists, returns the logarithmic access frequency counter of the object stored at `key` as an @@ -3903,28 +4032,28 @@ def object_freq(self: TTransaction, key: str) -> TTransaction: """ return self.append_command(RequestType.ObjectFreq, [key]) - def object_idletime(self: TTransaction, key: str) -> TTransaction: + def object_idletime(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns the time in seconds since the last access to the value stored at `key`. See https://valkey.io/commands/object-idletime for more details. Args: - key (str): The key of the object to get the idle time of. + key (TEncodable): The key of the object to get the idle time of. Command response: Optional[int]: If `key` exists, returns the idle time in seconds. Otherwise, returns None. """ return self.append_command(RequestType.ObjectIdleTime, [key]) - def object_refcount(self: TTransaction, key: str) -> TTransaction: + def object_refcount(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns the reference count of the object stored at `key`. See https://valkey.io/commands/object-refcount for more details. Args: - key (str): The key of the object to get the reference count of. + key (TEncodable): The key of the object to get the reference count of. Command response: Optional[int]: If `key` exists, returns the reference count of the object stored at `key` as an integer. @@ -3932,34 +4061,36 @@ def object_refcount(self: TTransaction, key: str) -> TTransaction: """ return self.append_command(RequestType.ObjectRefCount, [key]) - def srandmember(self: TTransaction, key: str) -> TTransaction: + def srandmember(self: TTransaction, key: TEncodable) -> TTransaction: """ Returns a random element from the set value stored at 'key'. See https://valkey.io/commands/srandmember for more details. Args: - key (str): The key from which to retrieve the set member. + key (TEncodable): The key from which to retrieve the set member. Command Response: - str: A random element from the set, or None if 'key' does not exist. + bytes: A random element from the set, or None if 'key' does not exist. """ return self.append_command(RequestType.SRandMember, [key]) - def srandmember_count(self: TTransaction, key: str, count: int) -> TTransaction: + def srandmember_count( + self: TTransaction, key: TEncodable, count: int + ) -> TTransaction: """ Returns one or more random elements from the set value stored at 'key'. See https://valkey.io/commands/srandmember for more details. Args: - key (str): The key of the sorted set. + key (TEncodable): The key of the sorted set. count (int): The number of members to return. If `count` is positive, returns unique members. If `count` is negative, allows for duplicates members. Command Response: - List[str]: A list of members from the set. + List[TEncodable]: A list of members from the set. If the set does not exist or is empty, the response will be an empty list. """ return self.append_command(RequestType.SRandMember, [key, str(count)]) @@ -3977,7 +4108,7 @@ def flushall( Command Response: TOK: OK. """ - args = [] + args: List[TEncodable] = [] if flush_mode is not None: args.append(flush_mode.value) return self.append_command(RequestType.FlushAll, args) @@ -3996,31 +4127,31 @@ def flushdb( Command Response: TOK: OK. """ - args = [] + args: List[TEncodable] = [] if flush_mode is not None: args.append(flush_mode.value) return self.append_command(RequestType.FlushDB, args) def getex( - self: TTransaction, key: str, expiry: Optional[ExpiryGetEx] = None + self: TTransaction, key: TEncodable, expiry: Optional[ExpiryGetEx] = None ) -> TTransaction: """ Get the value of `key` and optionally set its expiration. GETEX is similar to GET. See https://valkey.io/commands/getex for more details. Args: - key (str): The key to get. + key (TEncodable): The key to get. expiry (Optional[ExpirySet], optional): set expiriation to the given key. Equivalent to [`EX` | `PX` | `EXAT` | `PXAT` | `PERSIST`] in the Redis API. Command Response: - Optional[str]: + Optional[bytes]: If `key` exists, return the value stored at `key` If 'key` does not exist, return 'None' Since: Redis version 6.2.0. """ - args = [key] + args: List[TEncodable] = [key] if expiry is not None: args.extend(expiry.get_cmd_args()) return self.append_command(RequestType.GetEx, args) @@ -4042,9 +4173,9 @@ def lolwut( For version `6`, those are number of columns and number of lines. Command Response: - str: A piece of generative computer art along with the current Redis version. + bytes: A piece of generative computer art along with the current Redis version. """ - args = [] + args: List[TEncodable] = [] if version is not None: args.extend(["VERSION", str(version)]) if parameters: @@ -4059,15 +4190,15 @@ def random_key(self: TTransaction) -> TTransaction: See https://valkey.io/commands/randomkey for more details. Command response: - Optional[str]: A random existing key name. + Optional[bytes]: A random existing key name. """ return self.append_command(RequestType.RandomKey, []) def sscan( self: TTransaction, - key: str, - cursor: str, - match: Optional[str] = None, + key: TEncodable, + cursor: TEncodable, + match: Optional[TEncodable] = None, count: Optional[int] = None, ) -> TTransaction: """ @@ -4076,11 +4207,11 @@ def sscan( See https://valkey.io/commands/sscan for more details. Args: - key (str): The key of the set. - cursor (str): The cursor that points to the next iteration of results. A value of "0" indicates the start of + key (TEncodable): The key of the set. + cursor (TEncodable): The cursor that points to the next iteration of results. A value of "0" indicates the start of the search. - match (Optional[str]): The match filter is applied to the result of the command and will only include - strings that match the pattern specified. If the set is large enough for scan commands to return only a + match (Optional[TEncodable]): The match filter is applied to the result of the command and will only include + strings or bytes strings that match the pattern specified. If the set is large enough for scan commands to return only a subset of the set then there could be a case where the result is empty although there are items that match the pattern specified. This is due to the default `COUNT` being `10` which indicates that it will only fetch and match `10` items from the list. @@ -4089,7 +4220,7 @@ def sscan( as compact single-allocation packed encoding. Command Response: - List[Union[str, List[str]]]: An `Array` of the `cursor` and the subset of the set held by `key`. + List[Union[bytes, List[bytes]]]: An `Array` of the `cursor` and the subset of the set held by `key`. The first element is always the `cursor` for the next iteration of results. `0` will be the `cursor` returned on the last iteration of the set. The second element is always an `Array` of the subset of the set held in `key`. @@ -4104,9 +4235,9 @@ def sscan( def zscan( self: TTransaction, - key: str, - cursor: str, - match: Optional[str] = None, + key: TEncodable, + cursor: TEncodable, + match: Optional[TEncodable] = None, count: Optional[int] = None, ) -> TTransaction: """ @@ -4115,11 +4246,11 @@ def zscan( See https://valkey.io/commands/zscan for more details. Args: - key (str): The key of the sorted set. - cursor (str): The cursor that points to the next iteration of results. A value of "0" indicates the start of + key (TEncodable): The key of the sorted set. + cursor (TEncodable): The cursor that points to the next iteration of results. A value of "0" indicates the start of the search. - match (Optional[str]): The match filter is applied to the result of the command and will only include - strings that match the pattern specified. If the sorted set is large enough for scan commands to return + match (Optional[TEncodable]): The match filter is applied to the result of the command and will only include + strings or byte string that match the pattern specified. If the sorted set is large enough for scan commands to return only a subset of the sorted set then there could be a case where the result is empty although there are items that match the pattern specified. This is due to the default `COUNT` being `10` which indicates that it will only fetch and match `10` items from the list. @@ -4128,7 +4259,7 @@ def zscan( represent the results as compact single-allocation packed encoding. Returns: - List[Union[str, List[str]]]: An `Array` of the `cursor` and the subset of the sorted set held by `key`. + List[Union[bytes, List[bytes]]]: An `Array` of the `cursor` and the subset of the sorted set held by `key`. The first element is always the `cursor` for the next iteration of results. `0` will be the `cursor` returned on the last iteration of the sorted set. The second element is always an `Array` of the subset of the sorted set held in `key`. The `Array` in the second element is always a flattened series of @@ -4144,9 +4275,9 @@ def zscan( def hscan( self: TTransaction, - key: str, - cursor: str, - match: Optional[str] = None, + key: TEncodable, + cursor: TEncodable, + match: Optional[TEncodable] = None, count: Optional[int] = None, ) -> TTransaction: """ @@ -4155,11 +4286,11 @@ def hscan( See https://valkey.io/commands/hscan for more details. Args: - key (str): The key of the set. - cursor (str): The cursor that points to the next iteration of results. A value of "0" indicates the start of + key (TEncodable): The key of the set. + cursor (TEncodable): The cursor that points to the next iteration of results. A value of "0" indicates the start of the search. - match (Optional[str]): The match filter is applied to the result of the command and will only include - strings that match the pattern specified. If the hash is large enough for scan commands to return only a + match (Optional[TEncodable]): The match filter is applied to the result of the command and will only include + strings or bytes strings that match the pattern specified. If the hash is large enough for scan commands to return only a subset of the hash then there could be a case where the result is empty although there are items that match the pattern specified. This is due to the default `COUNT` being `10` which indicates that it will only fetch and match `10` items from the list. @@ -4168,7 +4299,7 @@ def hscan( as compact single-allocation packed encoding. Returns: - List[Union[str, List[str]]]: An `Array` of the `cursor` and the subset of the hash held by `key`. + List[Union[bytes, List[bytes]]]: An `Array` of the `cursor` and the subset of the hash held by `key`. The first element is always the `cursor` for the next iteration of results. `0` will be the `cursor` returned on the last iteration of the hash. The second element is always an `Array` of the subset of the hash held in `key`. The `Array` in the second element is always a flattened series of `String` pairs, @@ -4184,8 +4315,8 @@ def hscan( def lcs( self: TTransaction, - key1: str, - key2: str, + key1: TEncodable, + key2: TEncodable, ) -> TTransaction: """ Returns the longest common subsequence between strings stored at key1 and key2. @@ -4199,12 +4330,12 @@ def lcs( See https://valkey.io/commands/lcs for more details. Args: - key1 (str): The key that stores the first string. - key2 (str): The key that stores the second string. + key1 (TEncodable): The key that stores the first value. + key2 (TEncodable): The key that stores the second value. Command Response: - A String containing the longest common subsequence between the 2 strings. - An empty String is returned if the keys do not exist or have no common subsequences. + A Bytes String containing the longest common subsequence between the 2 strings. + An empty Bytes String is returned if the keys do not exist or have no common subsequences. Since: Redis version 7.0.0. """ @@ -4214,8 +4345,8 @@ def lcs( def lcs_len( self: TTransaction, - key1: str, - key2: str, + key1: TEncodable, + key2: TEncodable, ) -> TTransaction: """ Returns the length of the longest common subsequence between strings stored at key1 and key2. @@ -4229,8 +4360,8 @@ def lcs_len( See https://valkey.io/commands/lcs for more details. Args: - key1 (str): The key that stores the first string. - key2 (str): The key that stores the second string. + key1 (TEncodable): The key that stores the first value. + key2 (TEncodable): The key that stores the second value. Command Response: The length of the longest common subsequence between the 2 strings. @@ -4243,8 +4374,8 @@ def lcs_len( def lcs_idx( self: TTransaction, - key1: str, - key2: str, + key1: TEncodable, + key2: TEncodable, min_match_len: Optional[int] = None, with_match_len: Optional[bool] = False, ) -> TTransaction: @@ -4260,8 +4391,8 @@ def lcs_idx( See https://valkey.io/commands/lcs for more details. Args: - key1 (str): The key that stores the first string. - key2 (str): The key that stores the second string. + key1 (TEncodable): The key that stores the first value. + key2 (TEncodable): The key that stores the second value. min_match_len (Optional[int]): The minimum length of matches to include in the result. with_match_len (Optional[bool]): If True, include the length of the substring matched for each substring. @@ -4303,15 +4434,15 @@ def wait( timeout (int): The timeout value specified in milliseconds. Command Response: - str: The number of replicas reached by all the writes performed in the context of the current connection. + bytes: The number of replicas reached by all the writes performed in the context of the current connection. """ - args = [str(numreplicas), str(timeout)] + args: List[TEncodable] = [str(numreplicas), str(timeout)] return self.append_command(RequestType.Wait, args) def lpos( self: TTransaction, - key: str, - element: str, + key: TEncodable, + element: TEncodable, rank: Optional[int] = None, count: Optional[int] = None, max_len: Optional[int] = None, @@ -4323,8 +4454,8 @@ def lpos( See https://valkey.io/commands/lpos for more details. Args: - key (str): The name of the list. - element (str): The value to search for within the list. + key (TEncodable): The name of the list. + element (TEncodable): The value to search for within the list. rank (Optional[int]): The rank of the match to return. count (Optional[int]): The number of matches wanted. A `count` of 0 returns all the matches. max_len (Optional[int]): The maximum number of comparisons to make between the element and the items @@ -4370,14 +4501,14 @@ class Transaction(BaseTransaction): """ # TODO: add SLAVEOF and all SENTINEL commands - def move(self, key: str, db_index: int) -> "Transaction": + def move(self, key: TEncodable, db_index: int) -> "Transaction": """ Move `key` from the currently selected database to the database specified by `db_index`. See https://valkey.io/commands/move/ for more details. Args: - key (str): The key to move. + key (TEncodable): The key to move. db_index (int): The index of the database to move `key` to. Commands response: @@ -4401,10 +4532,10 @@ def select(self, index: int) -> "Transaction": def sort( self: TTransaction, - key: str, - by_pattern: Optional[str] = None, + key: TEncodable, + by_pattern: Optional[TEncodable] = None, limit: Optional[Limit] = None, - get_patterns: Optional[List[str]] = None, + get_patterns: Optional[List[TEncodable]] = None, order: Optional[OrderBy] = None, alpha: Optional[bool] = None, ) -> TTransaction: @@ -4416,8 +4547,8 @@ def sort( See https://valkey.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 external keys instead of by the elements stored at the key themselves. + key (TEncodable): The key of the list, set, or sorted set to be sorted. + by_pattern (Optional[TEncodable]): 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 @@ -4426,7 +4557,7 @@ def sort( 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_pattern (Optional[str]): A pattern used to retrieve external keys' values, instead of the elements at `key`. + get_pattern (Optional[TEncodable]): 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` @@ -4441,18 +4572,18 @@ 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]]: Returns a list of sorted elements. + List[Optional[bytes]]: 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, - destination: str, - by_pattern: Optional[str] = None, + key: TEncodable, + destination: TEncodable, + by_pattern: Optional[TEncodable] = None, limit: Optional[Limit] = None, - get_patterns: Optional[List[str]] = None, + get_patterns: Optional[List[TEncodable]] = None, order: Optional[OrderBy] = None, alpha: Optional[bool] = None, ) -> TTransaction: @@ -4464,9 +4595,9 @@ def sort_store( See https://valkey.io/commands/sort for more details. 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. + key (TEncodable): The key of the list, set, or sorted set to be sorted. + destination (TEncodable): The key where the sorted result will be stored. + by_pattern (Optional[TEncodable]): 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 @@ -4475,7 +4606,7 @@ def sort_store( 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_pattern (Optional[str]): A pattern used to retrieve external keys' values, instead of the elements at `key`. + get_pattern (Optional[TEncodable]): 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` @@ -4499,8 +4630,8 @@ def sort_store( def copy( self: TTransaction, - source: str, - destination: str, + source: TEncodable, + destination: TEncodable, destinationDB: Optional[int] = None, replace: Optional[bool] = None, ) -> TTransaction: @@ -4513,8 +4644,8 @@ def copy( See https://valkey.io/commands/copy for more details. Args: - source (str): The key to the source value. - destination (str): The key where the value should be copied to. + source (TEncodable): The key to the source value. + destination (TEncodable): The key where the value should be copied to. destinationDB (Optional[int]): The alternative logical database index for the destination key. replace (Optional[bool]): If the destination key should be removed before copying the value to it. @@ -4531,14 +4662,16 @@ def copy( return self.append_command(RequestType.Copy, args) - def publish(self: TTransaction, message: str, channel: str) -> TTransaction: + def publish( + self: TTransaction, message: TEncodable, channel: TEncodable + ) -> TTransaction: """ Publish a message on pubsub channel. See https://valkey.io/commands/publish for more details. Args: - message (str): Message to publish - channel (str): Channel to publish the message on. + message (TEncodable): Message to publish + channel (TEncodable): Channel to publish the message on. Returns: TOK: a simple `OK` response. @@ -4558,7 +4691,7 @@ class ClusterTransaction(BaseTransaction): def sort( self: TTransaction, - key: str, + key: TEncodable, limit: Optional[Limit] = None, order: Optional[OrderBy] = None, alpha: Optional[bool] = None, @@ -4570,7 +4703,7 @@ def sort( See https://valkey.io/commands/sort for more details. Args: - key (str): The key of the list, set, or sorted set to be sorted. + key (TEncodable): 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). @@ -4578,15 +4711,15 @@ 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[str]: A list of sorted elements. + List[bytes]: 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: TTransaction, - key: str, - destination: str, + key: TEncodable, + destination: TEncodable, limit: Optional[Limit] = None, order: Optional[OrderBy] = None, alpha: Optional[bool] = None, @@ -4599,8 +4732,8 @@ def sort_store( See https://valkey.io/commands/sort for more details. 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. + key (TEncodable): The key of the list, set, or sorted set to be sorted. + destination (TEncodable): 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). @@ -4615,8 +4748,8 @@ def sort_store( def copy( self: TTransaction, - source: str, - destination: str, + source: TEncodable, + destination: TEncodable, replace: Optional[bool] = None, ) -> TTransaction: """ @@ -4626,8 +4759,8 @@ def copy( See https://valkey.io/commands/copy for more details. Args: - source (str): The key to the source value. - destination (str): The key where the value should be copied to. + source (TEncodable): The key to the source value. + destination (TEncodable): The key where the value should be copied to. replace (Optional[bool]): If the destination key should be removed before copying the value to it. Command response: diff --git a/python/python/glide/constants.py b/python/python/glide/constants.py index 0eacccb040..c86756d5d6 100644 --- a/python/python/glide/constants.py +++ b/python/python/glide/constants.py @@ -35,3 +35,4 @@ # Otherwise, (when specifying JSONPath), response will be List[Optional[T]]. # For more information, see: https://redis.io/docs/data-types/json/path/ . TJsonResponse = Union[T, List[Optional[T]]] +TEncodable = Union[str, bytes] diff --git a/python/python/glide/glide_client.py b/python/python/glide/glide_client.py index f49efa3118..57b36f4455 100644 --- a/python/python/glide/glide_client.py +++ b/python/python/glide/glide_client.py @@ -10,7 +10,7 @@ from glide.async_commands.core import CoreCommands from glide.async_commands.standalone_commands import StandaloneCommands from glide.config import BaseClientConfiguration -from glide.constants import DEFAULT_READ_BYTES_SIZE, OK, TRequest, TResult +from glide.constants import DEFAULT_READ_BYTES_SIZE, OK, TEncodable, TRequest, TResult from glide.exceptions import ( ClosingError, ConfigurationError, @@ -197,7 +197,7 @@ async def _write_buffered_requests_to_socket(self) -> None: self._writer.write(b_arr) await self._writer.drain() - def _encode_arg(self, arg: Union[str, bytes]) -> bytes: + def _encode_arg(self, arg: TEncodable) -> bytes: """ Converts a string argument to bytes. @@ -212,17 +212,16 @@ def _encode_arg(self, arg: Union[str, bytes]) -> bytes: return bytes(arg, encoding="utf8") return arg - # TODO: change `List[str]` to `List[TEncodable]` where `TEncodable = Union[str, bytes]` def _encode_and_sum_size( self, - args_list: Optional[List[str]], + args_list: Optional[List[TEncodable]], ) -> Tuple[List[bytes], int]: """ Encodes the list and calculates the total memory size. Args: - args_list (Optional[List[str]]): A list of strings to be converted to bytes. - If None or empty, returns ([], 0). + args_list (Optional[List[TEncodable]]): A list of strings to be converted to bytes. + If None or empty, returns ([], 0). Returns: int: The total memory size of the encoded arguments in bytes. @@ -232,7 +231,7 @@ def _encode_and_sum_size( if not args_list: return (encoded_args_list, args_size) for arg in args_list: - encoded_arg = self._encode_arg(arg) + encoded_arg = self._encode_arg(arg) if isinstance(arg, str) else arg encoded_args_list.append(encoded_arg) args_size += sys.getsizeof(encoded_arg) return (encoded_args_list, args_size) @@ -240,7 +239,7 @@ def _encode_and_sum_size( async def _execute_command( self, request_type: RequestType.ValueType, - args: List[str], + args: List[TEncodable], route: Optional[Route] = None, ) -> TResult: if self._is_closed: @@ -266,7 +265,7 @@ async def _execute_command( async def _execute_transaction( self, - commands: List[Tuple[RequestType.ValueType, List[str]]], + commands: List[Tuple[RequestType.ValueType, List[TEncodable]]], route: Optional[Route] = None, ) -> List[TResult]: if self._is_closed: diff --git a/python/python/tests/test_async_client.py b/python/python/tests/test_async_client.py index cc5bbc99c5..7c9632ed93 100644 --- a/python/python/tests/test_async_client.py +++ b/python/python/tests/test_async_client.py @@ -8,7 +8,7 @@ import time from collections.abc import Mapping from datetime import date, datetime, timedelta, timezone -from typing import Any, Dict, List, Union, cast +from typing import Any, Dict, List, Tuple, Union, cast import pytest from glide import ClosingError, RequestError, Script @@ -75,7 +75,7 @@ ProtocolVersion, RedisCredentials, ) -from glide.constants import OK, TResult +from glide.constants import OK, TEncodable, TResult from glide.glide_client import GlideClient, GlideClusterClient, TGlideClient from glide.routes import ( AllNodes, @@ -647,8 +647,11 @@ async def test_msetnx(self, redis_client: TGlideClient): non_existing = get_random_string(5) value = get_random_string(5) value_encoded = value.encode() - key_value_map1 = {key1: value, key2: value} - key_value_map2 = {key2: get_random_string(5), key3: value} + key_value_map1: Mapping[TEncodable, TEncodable] = {key1: value, key2: value} + key_value_map2: Mapping[TEncodable, TEncodable] = { + key2: get_random_string(5), + key3: value, + } assert await redis_client.msetnx(key_value_map1) is True mget_res = await redis_client.mget([key1, key2, non_existing]) @@ -1036,10 +1039,10 @@ async def test_hstrlen(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_lpush_lpop_lrange(self, redis_client: TGlideClient): key = get_random_string(10) - value_list = ["value4", "value3", "value2", "value1"] + value_list: List[TEncodable] = ["value4", "value3", "value2", "value1"] assert await redis_client.lpush(key, value_list) == 4 - assert await redis_client.lpop(key) == value_list[-1].encode() + assert await redis_client.lpop(key) == cast(str, value_list[-1]).encode() assert await redis_client.lrange(key, 0, -1) == convert_string_to_bytes_object( value_list[-2::-1] ) @@ -1099,7 +1102,7 @@ async def test_blpop(self, redis_client: TGlideClient): key2 = f"{{test}}-2-f{get_random_string(10)}" value1 = "value1" value2 = "value2" - value_list = [value1, value2] + value_list: List[TEncodable] = [value1, value2] assert await redis_client.lpush(key1, value_list) == 2 assert await redis_client.blpop( @@ -1223,10 +1226,10 @@ async def test_lindex(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_rpush_rpop(self, redis_client: TGlideClient): key = get_random_string(10) - value_list = ["value4", "value3", "value2", "value1"] + value_list: List[TEncodable] = ["value4", "value3", "value2", "value1"] assert await redis_client.rpush(key, value_list) == 4 - assert await redis_client.rpop(key) == value_list[-1].encode() + assert await redis_client.rpop(key) == cast(str, value_list[-1]).encode() assert await redis_client.rpop_count(key, 2) == convert_string_to_bytes_object( value_list[-2:0:-1] @@ -1277,7 +1280,7 @@ async def test_brpop(self, redis_client: TGlideClient): key2 = f"{{test}}-2-f{get_random_string(10)}" value1 = "value1" value2 = "value2" - value_list = [value1, value2] + value_list: List[TEncodable] = [value1, value2] assert await redis_client.lpush(key1, value_list) == 2 # ensure that command doesn't time out even if timeout > request timeout (250ms by default) @@ -1558,7 +1561,7 @@ async def test_lset(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_sadd_srem_smembers_scard(self, redis_client: TGlideClient): key = get_random_string(10) - value_list = ["member1", "member2", "member3", "member4"] + value_list: List[TEncodable] = ["member1", "member2", "member3", "member4"] assert await redis_client.sadd(key, value_list) == 4 assert await redis_client.srem(key, ["member4", "nonExistingMember"]) == 1 @@ -1696,8 +1699,8 @@ async def test_sunion(self, redis_client: TGlideClient): key1 = f"{{testKey}}:{get_random_string(10)}" key2 = f"{{testKey}}:{get_random_string(10)}" non_existing_key = f"{{testKey}}:non_existing_key" - member1_list = ["a", "b", "c"] - member2_list = ["b", "c", "d", "e"] + member1_list: List[TEncodable] = ["a", "b", "c"] + member2_list: List[TEncodable] = ["b", "c", "d", "e"] assert await redis_client.sadd(key1, member1_list) == 3 assert await redis_client.sadd(key2, member2_list) == 4 @@ -1710,7 +1713,7 @@ async def test_sunion(self, redis_client: TGlideClient): # non-existing key returns the set of existing keys assert await redis_client.sunion( [key1, non_existing_key] - ) == convert_string_to_bytes_object(set(member1_list)) + ) == convert_string_to_bytes_object(set(cast(List[str], member1_list))) # non-set key assert await redis_client.set(key2, "value") == OK @@ -1780,8 +1783,8 @@ async def test_sinter(self, redis_client: TGlideClient): key1 = f"{{testKey}}:{get_random_string(10)}" key2 = f"{{testKey}}:{get_random_string(10)}" non_existing_key = f"{{testKey}}:non_existing_key" - member1_list = ["a", "b", "c"] - member2_list = ["c", "d", "e"] + member1_list: List[TEncodable] = ["a", "b", "c"] + member2_list: List[TEncodable] = ["c", "d", "e"] # positive test case assert await redis_client.sadd(key1, member1_list) == 3 @@ -1809,8 +1812,8 @@ async def test_sinterstore(self, redis_client: TGlideClient): key3 = f"{{testKey}}:{get_random_string(10)}" string_key = f"{{testKey}}:{get_random_string(10)}" non_existing_key = f"{{testKey}}:non_existing_key" - member1_list = ["a", "b", "c"] - member2_list = ["c", "d", "e"] + member1_list: List[TEncodable] = ["a", "b", "c"] + member2_list: List[TEncodable] = ["c", "d", "e"] assert await redis_client.sadd(key1, member1_list) == 3 assert await redis_client.sadd(key2, member2_list) == 3 @@ -1856,9 +1859,9 @@ async def test_sintercard(self, redis_client: TGlideClient): key3 = f"{{testKey}}:{get_random_string(10)}" string_key = f"{{testKey}}:{get_random_string(10)}" non_existing_key = f"{{testKey}}:non_existing_key" - member1_list = ["a", "b", "c"] - member2_list = ["b", "c", "d", "e"] - member3_list = ["b", "c", "f", "g"] + member1_list: List[TEncodable] = ["a", "b", "c"] + member2_list: List[TEncodable] = ["b", "c", "d", "e"] + member3_list: List[TEncodable] = ["b", "c", "f", "g"] assert await redis_client.sadd(key1, member1_list) == 3 assert await redis_client.sadd(key2, member2_list) == 4 @@ -2001,7 +2004,7 @@ async def test_smismember(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_ltrim(self, redis_client: TGlideClient): key = get_random_string(10) - value_list = ["value4", "value3", "value2", "value1"] + value_list: List[TEncodable] = ["value4", "value3", "value2", "value1"] assert await redis_client.lpush(key, value_list) == 4 assert await redis_client.ltrim(key, 0, 1) == OK @@ -2023,7 +2026,13 @@ async def test_ltrim(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_lrem(self, redis_client: TGlideClient): key = get_random_string(10) - value_list = ["value1", "value2", "value1", "value1", "value2"] + value_list: List[TEncodable] = [ + "value1", + "value2", + "value1", + "value1", + "value2", + ] assert await redis_client.lpush(key, value_list) == 5 @@ -2047,7 +2056,7 @@ async def test_lrem(self, redis_client: TGlideClient): async def test_llen(self, redis_client: TGlideClient): key1 = get_random_string(10) key2 = get_random_string(10) - value_list = ["value4", "value3", "value2", "value1"] + value_list: List[TEncodable] = ["value4", "value3", "value2", "value1"] assert await redis_client.lpush(key1, value_list) == 4 assert await redis_client.llen(key1) == 4 @@ -2064,7 +2073,7 @@ async def test_llen(self, redis_client: TGlideClient): async def test_strlen(self, redis_client: TGlideClient): key1 = get_random_string(10) key2 = get_random_string(10) - value_list = ["value4", "value3", "value2", "value1"] + value_list: List[TEncodable] = ["value4", "value3", "value2", "value1"] assert await redis_client.set(key1, "foo") == OK assert await redis_client.strlen(key1) == 3 @@ -2287,7 +2296,7 @@ async def test_persist(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_geoadd(self, redis_client: TGlideClient): key, key2 = get_random_string(10), get_random_string(10) - members_coordinates = { + members_coordinates: Dict[str | bytes, GeospatialData] = { "Palermo": GeospatialData(13.361389, 38.115556), "Catania": GeospatialData(15.087269, 37.502669), } @@ -2349,7 +2358,7 @@ async def test_geoadd_invalid_args(self, redis_client: TGlideClient): async def test_geosearch_by_box(self, redis_client: TGlideClient): key = get_random_string(10) members = ["Catania", "Palermo", "edge2", "edge1"] - members_coordinates = { + members_coordinates: Mapping[TEncodable, GeospatialData] = { "Palermo": GeospatialData(13.361389, 38.115556), "Catania": GeospatialData(15.087269, 37.502669), "edge1": GeospatialData(12.758489, 38.788135), @@ -2441,7 +2450,7 @@ async def test_geosearch_by_box(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_geosearch_by_radius(self, redis_client: TGlideClient): key = get_random_string(10) - members_coordinates = { + members_coordinates: Mapping[TEncodable, GeospatialData] = { "Palermo": GeospatialData(13.361389, 38.115556), "Catania": GeospatialData(15.087269, 37.502669), "edge1": GeospatialData(12.758489, 38.788135), @@ -2516,7 +2525,7 @@ async def test_geosearch_by_radius(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_geosearch_no_result(self, redis_client: TGlideClient): key = get_random_string(10) - members_coordinates = { + members_coordinates: Mapping[TEncodable, GeospatialData] = { "Palermo": GeospatialData(13.361389, 38.115556), "Catania": GeospatialData(15.087269, 37.502669), "edge1": GeospatialData(12.758489, 38.788135), @@ -2579,7 +2588,7 @@ async def test_geosearch_no_result(self, redis_client: TGlideClient): async def test_geosearchstore_by_box(self, redis_client: TGlideClient): key = f"{{testKey}}:{get_random_string(10)}" destination_key = f"{{testKey}}:{get_random_string(8)}" - members_coordinates = { + members_coordinates: Mapping[TEncodable, GeospatialData] = { "Palermo": GeospatialData(13.361389, 38.115556), "Catania": GeospatialData(15.087269, 37.502669), "edge1": GeospatialData(12.758489, 38.788135), @@ -2695,7 +2704,7 @@ async def test_geosearchstore_by_box(self, redis_client: TGlideClient): async def test_geosearchstore_by_radius(self, redis_client: TGlideClient): key = f"{{testKey}}:{get_random_string(10)}" destination_key = f"{{testKey}}:{get_random_string(8)}" - members_coordinates = { + members_coordinates: Mapping[TEncodable, GeospatialData] = { "Palermo": GeospatialData(13.361389, 38.115556), "Catania": GeospatialData(15.087269, 37.502669), "edge1": GeospatialData(12.758489, 38.788135), @@ -2808,7 +2817,7 @@ async def test_geosearchstore_by_radius(self, redis_client: TGlideClient): async def test_geosearchstore_no_result(self, redis_client: TGlideClient): key = f"{{testKey}}:{get_random_string(10)}" destination_key = f"{{testKey}}:{get_random_string(8)}" - members_coordinates = { + members_coordinates: Mapping[TEncodable, GeospatialData] = { "Palermo": GeospatialData(13.361389, 38.115556), "Catania": GeospatialData(15.087269, 37.502669), "edge1": GeospatialData(12.758489, 38.788135), @@ -2880,7 +2889,7 @@ async def test_geosearchstore_no_result(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_geohash(self, redis_client: TGlideClient): key = get_random_string(10) - members_coordinates = { + members_coordinates: Mapping[TEncodable, GeospatialData] = { "Palermo": GeospatialData(13.361389, 38.115556), "Catania": GeospatialData(15.087269, 37.502669), } @@ -2915,7 +2924,7 @@ async def test_geohash(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_geodist(self, redis_client: TGlideClient): key, key2 = get_random_string(10), get_random_string(10) - members_coordinates = { + members_coordinates: Mapping[TEncodable, GeospatialData] = { "Palermo": GeospatialData(13.361389, 38.115556), "Catania": GeospatialData(15.087269, 37.502669), } @@ -2942,7 +2951,7 @@ async def test_geodist(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_geopos(self, redis_client: TGlideClient): key = get_random_string(10) - members_coordinates = { + members_coordinates: Mapping[TEncodable, GeospatialData] = { "Palermo": GeospatialData(13.361389, 38.115556), "Catania": GeospatialData(15.087269, 37.502669), } @@ -2986,7 +2995,7 @@ async def test_geopos(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_zadd_zaddincr(self, redis_client: TGlideClient): key = get_random_string(10) - members_scores = {"one": 1, "two": 2, "three": 3} + members_scores: Mapping[TEncodable, float] = {"one": 1, "two": 2, "three": 3} assert await redis_client.zadd(key, members_scores=members_scores) == 3 assert await redis_client.zadd_incr(key, member="one", increment=2) == 3.0 @@ -2994,7 +3003,7 @@ async def test_zadd_zaddincr(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_zadd_nx_xx(self, redis_client: TGlideClient): key = get_random_string(10) - members_scores = {"one": 1, "two": 2, "three": 3} + members_scores: Mapping[TEncodable, float] = {"one": 1, "two": 2, "three": 3} assert ( await redis_client.zadd( key, @@ -3036,7 +3045,7 @@ async def test_zadd_nx_xx(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_zadd_gt_lt(self, redis_client: TGlideClient): key = get_random_string(10) - members_scores = {"one": -3, "two": 2, "three": 3} + members_scores: Dict[TEncodable, float] = {"one": -3, "two": 2, "three": 3} assert await redis_client.zadd(key, members_scores=members_scores) == 3 members_scores["one"] = 10 assert ( @@ -3109,7 +3118,7 @@ async def test_zincrby(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_zrem(self, redis_client: TGlideClient): key = get_random_string(10) - members_scores = {"one": 1, "two": 2, "three": 3} + members_scores: Mapping[TEncodable, float] = {"one": 1, "two": 2, "three": 3} assert await redis_client.zadd(key, members_scores=members_scores) == 3 assert await redis_client.zrem(key, ["one"]) == 1 @@ -3121,7 +3130,7 @@ async def test_zrem(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_zremrangebyscore(self, redis_client: TGlideClient): key = get_random_string(10) - members_scores = {"one": 1, "two": 2, "three": 3} + members_scores: Mapping[TEncodable, float] = {"one": 1, "two": 2, "three": 3} assert await redis_client.zadd(key, members_scores) == 3 assert ( @@ -3151,7 +3160,7 @@ async def test_zremrangebylex(self, redis_client: TGlideClient): key1 = get_random_string(10) key2 = get_random_string(10) range = RangeByIndex(0, -1) - members_scores = {"a": 1, "b": 2, "c": 3, "d": 4} + members_scores: Mapping[TEncodable, float] = {"a": 1, "b": 2, "c": 3, "d": 4} assert await redis_client.zadd(key1, members_scores) == 4 assert ( @@ -3196,7 +3205,13 @@ async def test_zremrangebyrank(self, redis_client: TGlideClient): key1 = get_random_string(10) key2 = get_random_string(10) range = RangeByIndex(0, -1) - members_scores = {"a": 1, "b": 2, "c": 3, "d": 4, "e": 5} + members_scores: Mapping[TEncodable, float] = { + "a": 1, + "b": 2, + "c": 3, + "d": 4, + "e": 5, + } assert await redis_client.zadd(key1, members_scores) == 5 # Test start exceeding end @@ -3224,7 +3239,7 @@ async def test_zremrangebyrank(self, redis_client: TGlideClient): async def test_zlexcount(self, redis_client: TGlideClient): key1 = get_random_string(10) key2 = get_random_string(10) - members_scores = {"a": 1.0, "b": 2.0, "c": 3.0} + members_scores: Mapping[TEncodable, float] = {"a": 1.0, "b": 2.0, "c": 3.0} assert await redis_client.zadd(key1, members_scores) == 3 assert ( @@ -3267,7 +3282,7 @@ async def test_zlexcount(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_zcard(self, redis_client: TGlideClient): key = get_random_string(10) - members_scores = {"one": 1, "two": 2, "three": 3} + members_scores: Mapping[TEncodable, float] = {"one": 1, "two": 2, "three": 3} assert await redis_client.zadd(key, members_scores=members_scores) == 3 assert await redis_client.zcard(key) == 3 @@ -3279,7 +3294,7 @@ async def test_zcard(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_zcount(self, redis_client: TGlideClient): key = get_random_string(10) - members_scores = {"one": 1, "two": 2, "three": 3} + members_scores: Mapping[TEncodable, float] = {"one": 1, "two": 2, "three": 3} assert await redis_client.zadd(key, members_scores=members_scores) == 3 assert await redis_client.zcount(key, InfBound.NEG_INF, InfBound.POS_INF) == 3 @@ -3322,7 +3337,7 @@ async def test_zcount(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_zscore(self, redis_client: TGlideClient): key = get_random_string(10) - members_scores = {"one": 1, "two": 2, "three": 3} + members_scores: Mapping[TEncodable, float] = {"one": 1, "two": 2, "three": 3} assert await redis_client.zadd(key, members_scores=members_scores) == 3 assert await redis_client.zscore(key, "one") == 1.0 @@ -3336,7 +3351,7 @@ async def test_zscore(self, redis_client: TGlideClient): async def test_zmscore(self, redis_client: TGlideClient): key1 = get_random_string(10) key2 = get_random_string(10) - members_scores = {"one": 1, "two": 2, "three": 3} + members_scores: Mapping[TEncodable, float] = {"one": 1, "two": 2, "three": 3} assert await redis_client.zadd(key1, members_scores=members_scores) == 3 assert await redis_client.zmscore(key1, ["one", "two", "three"]) == [ @@ -3360,8 +3375,12 @@ async def test_zinter_commands(self, redis_client: TGlideClient): key2 = "{testKey}:2-" + get_random_string(10) key3 = "{testKey}:3-" + get_random_string(10) range = RangeByIndex(0, -1) - members_scores1 = {"one": 1.0, "two": 2.0} - members_scores2 = {"one": 1.5, "two": 2.5, "three": 3.5} + members_scores1: Mapping[TEncodable, float] = {"one": 1.0, "two": 2.0} + members_scores2: Mapping[TEncodable, float] = { + "one": 1.5, + "two": 2.5, + "three": 3.5, + } assert await redis_client.zadd(key1, members_scores1) == 2 assert await redis_client.zadd(key2, members_scores2) == 3 @@ -3472,7 +3491,9 @@ async def test_zinter_commands(self, redis_client: TGlideClient): # Empty list check with pytest.raises(RequestError) as e: - await redis_client.zinterstore("{xyz}", []) + await redis_client.zinterstore( + "{xyz}", cast(List[TEncodable], cast(List[TEncodable], [])) + ) assert "wrong number of arguments" in str(e) with pytest.raises(RequestError) as e: @@ -3480,7 +3501,7 @@ async def test_zinter_commands(self, redis_client: TGlideClient): assert "wrong number of arguments" in str(e) with pytest.raises(RequestError) as e: - await redis_client.zinter_withscores([]) + await redis_client.zinter_withscores(cast(List[TEncodable], [])) assert "at least 1 input key is needed" in str(e) @pytest.mark.parametrize("cluster_mode", [True, False]) @@ -3490,8 +3511,12 @@ async def test_zunion_commands(self, redis_client: TGlideClient): key2 = "{testKey}:2-" + get_random_string(10) key3 = "{testKey}:3-" + get_random_string(10) range = RangeByIndex(0, -1) - members_scores1 = {"one": 1.0, "two": 2.0} - members_scores2 = {"one": 1.5, "two": 2.5, "three": 3.5} + members_scores1: Mapping[TEncodable, float] = {"one": 1.0, "two": 2.0} + members_scores2: Mapping[TEncodable, float] = { + "one": 1.5, + "two": 2.5, + "three": 3.5, + } assert await redis_client.zadd(key1, members_scores1) == 2 assert await redis_client.zadd(key2, members_scores2) == 3 @@ -3625,7 +3650,7 @@ async def test_zunion_commands(self, redis_client: TGlideClient): # Empty list check with pytest.raises(RequestError) as e: - await redis_client.zunionstore("{xyz}", []) + await redis_client.zunionstore("{xyz}", cast(List[TEncodable], [])) assert "wrong number of arguments" in str(e) with pytest.raises(RequestError) as e: @@ -3633,14 +3658,14 @@ async def test_zunion_commands(self, redis_client: TGlideClient): assert "wrong number of arguments" in str(e) with pytest.raises(RequestError) as e: - await redis_client.zunion_withscores([]) + await redis_client.zunion_withscores(cast(List[TEncodable], [])) assert "at least 1 input key is needed" in str(e) @pytest.mark.parametrize("cluster_mode", [True, False]) @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_zpopmin(self, redis_client: TGlideClient): key = get_random_string(10) - members_scores = {"a": 1.0, "b": 2.0, "c": 3.0} + members_scores: Mapping[TEncodable, float] = {"a": 1.0, "b": 2.0, "c": 3.0} assert await redis_client.zadd(key, members_scores=members_scores) == 3 assert await redis_client.zpopmin(key) == {b"a": 1.0} @@ -3699,7 +3724,7 @@ async def endless_bzpopmin_call(): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_zpopmax(self, redis_client: TGlideClient): key = get_random_string(10) - members_scores = {"a": 1.0, "b": 2.0, "c": 3.0} + members_scores: Mapping[TEncodable, float] = {"a": 1.0, "b": 2.0, "c": 3.0} assert await redis_client.zadd(key, members_scores) == 3 assert await redis_client.zpopmax(key) == {b"c": 3.0} @@ -3758,7 +3783,7 @@ async def endless_bzpopmax_call(): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_zrange_by_index(self, redis_client: TGlideClient): key = get_random_string(10) - members_scores = {"one": 1, "two": 2, "three": 3} + members_scores: Mapping[TEncodable, float] = {"one": 1, "two": 2, "three": 3} assert await redis_client.zadd(key, members_scores=members_scores) == 3 assert await redis_client.zrange(key, RangeByIndex(start=0, stop=1)) == [ @@ -3789,7 +3814,7 @@ async def test_zrange_by_index(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_zrange_byscore(self, redis_client: TGlideClient): key = get_random_string(10) - members_scores = {"one": 1, "two": 2, "three": 3} + members_scores: Mapping[TEncodable, float] = {"one": 1, "two": 2, "three": 3} assert await redis_client.zadd(key, members_scores=members_scores) == 3 assert await redis_client.zrange( @@ -3871,7 +3896,7 @@ async def test_zrange_byscore(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_zrange_bylex(self, redis_client: TGlideClient): key = get_random_string(10) - members_scores = {"a": 1, "b": 2, "c": 3} + members_scores: Mapping[TEncodable, float] = {"a": 1, "b": 2, "c": 3} assert await redis_client.zadd(key, members_scores=members_scores) == 3 assert await redis_client.zrange( @@ -3952,7 +3977,11 @@ async def test_zrangestore_by_index(self, redis_client: TGlideClient): string_key = f"{{testKey}}:{get_random_string(10)}" non_existing_key = f"{{testKey}}:{get_random_string(10)}" - member_scores = {"one": 1.0, "two": 2.0, "three": 3.0} + member_scores: Mapping[TEncodable, float] = { + "one": 1.0, + "two": 2.0, + "three": 3.0, + } assert await redis_client.zadd(source, member_scores) == 3 # full range @@ -4010,7 +4039,11 @@ async def test_zrangestore_by_score(self, redis_client: TGlideClient): string_key = f"{{testKey}}:{get_random_string(10)}" non_existing_key = f"{{testKey}}:{get_random_string(10)}" - member_scores = {"one": 1.0, "two": 2.0, "three": 3.0} + member_scores: Mapping[TEncodable, float] = { + "one": 1.0, + "two": 2.0, + "three": 3.0, + } assert await redis_client.zadd(source, member_scores) == 3 # range from negative infinity to 3 (exclusive) @@ -4113,7 +4146,7 @@ async def test_zrangestore_by_lex(self, redis_client: TGlideClient): string_key = f"{{testKey}}:4-{get_random_string(10)}" non_existing_key = f"{{testKey}}:5-{get_random_string(10)}" - member_scores = {"a": 1.0, "b": 2.0, "c": 3.0} + member_scores: Mapping[TEncodable, float] = {"a": 1.0, "b": 2.0, "c": 3.0} assert await redis_client.zadd(source, member_scores) == 3 # range from negative infinity to "c" (exclusive) @@ -4212,7 +4245,7 @@ async def test_zrangestore_by_lex(self, redis_client: TGlideClient): @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_zrank(self, redis_client: TGlideClient): key = get_random_string(10) - members_scores = {"one": 1.5, "two": 2, "three": 3} + members_scores: Mapping[TEncodable, float] = {"one": 1.5, "two": 2, "three": 3} assert await redis_client.zadd(key, members_scores) == 3 assert await redis_client.zrank(key, "one") == 0 if not await check_if_server_version_lt(redis_client, "7.2.0"): @@ -4235,7 +4268,11 @@ async def test_zrevrank(self, redis_client: TGlideClient): key = get_random_string(10) non_existing_key = get_random_string(10) string_key = get_random_string(10) - member_scores = {"one": 1.0, "two": 2.0, "three": 3.0} + member_scores: Mapping[TEncodable, float] = { + "one": 1.0, + "two": 2.0, + "three": 3.0, + } assert await redis_client.zadd(key, member_scores) == 3 assert await redis_client.zrevrank(key, "three") == 0 @@ -4244,7 +4281,7 @@ async def test_zrevrank(self, redis_client: TGlideClient): await redis_client.zrevrank(non_existing_key, "non_existing_member") is None ) - if not check_if_server_version_lt(redis_client, "7.2.0"): + if not await check_if_server_version_lt(redis_client, "7.2.0"): assert await redis_client.zrevrank_withscore(key, "one") == [2, 1.0] assert ( await redis_client.zrevrank_withscore(key, "non_existing_member") @@ -4273,9 +4310,18 @@ async def test_zdiff(self, redis_client: TGlideClient): string_key = f"{{testKey}}:4-{get_random_string(10)}" non_existing_key = f"{{testKey}}:5-{get_random_string(10)}" - member_scores1 = {"one": 1.0, "two": 2.0, "three": 3.0} - member_scores2 = {"two": 2.0} - member_scores3 = {"one": 1.0, "two": 2.0, "three": 3.0, "four": 4.0} + member_scores1: Mapping[TEncodable, float] = { + "one": 1.0, + "two": 2.0, + "three": 3.0, + } + member_scores2: Mapping[TEncodable, float] = {"two": 2.0} + member_scores3: Mapping[TEncodable, float] = { + "one": 1.0, + "two": 2.0, + "three": 3.0, + "four": 4.0, + } assert await redis_client.zadd(key1, member_scores1) == 3 assert await redis_client.zadd(key2, member_scores2) == 1 @@ -4292,7 +4338,7 @@ async def test_zdiff(self, redis_client: TGlideClient): } assert compare_maps(zdiff_map, expected_map) is True assert ( - compare_maps(await redis_client.zdiff_withscores([key1, key3]), {}) is True + compare_maps(await redis_client.zdiff_withscores([key1, key3]), {}) is True # type: ignore ) non_exist_res = await redis_client.zdiff_withscores([non_existing_key, key3]) assert non_exist_res == {} @@ -4324,9 +4370,18 @@ async def test_zdiffstore(self, redis_client: TGlideClient): string_key = f"{{testKey}}:4-{get_random_string(10)}" non_existing_key = f"{{testKey}}:5-{get_random_string(10)}" - member_scores1 = {"one": 1.0, "two": 2.0, "three": 3.0} - member_scores2 = {"two": 2.0} - member_scores3 = {"one": 1.0, "two": 2.0, "three": 3.0, "four": 4.0} + member_scores1: Mapping[TEncodable, float] = { + "one": 1.0, + "two": 2.0, + "three": 3.0, + } + member_scores2: Mapping[TEncodable, float] = {"two": 2.0} + member_scores3: Mapping[TEncodable, float] = { + "one": 1.0, + "two": 2.0, + "three": 3.0, + "four": 4.0, + } assert await redis_client.zadd(key1, member_scores1) == 3 assert await redis_client.zadd(key2, member_scores2) == 1 @@ -4365,8 +4420,18 @@ async def test_bzmpop(self, redis_client: TGlideClient): non_existing_key = f"{{test}}-non_existing_key" string_key = f"{{test}}-3-f{get_random_string(10)}" - assert await redis_client.zadd(key1, {"a1": 1, "b1": 2}) == 2 - assert await redis_client.zadd(key2, {"a2": 0.1, "b2": 0.2}) == 2 + assert ( + await redis_client.zadd( + key1, cast(Mapping[TEncodable, float], {"a1": 1, "b1": 2}) + ) + == 2 + ) + assert ( + await redis_client.zadd( + key2, cast(Mapping[TEncodable, float], {"a2": 0.1, "b2": 0.2}) + ) + == 2 + ) assert await redis_client.bzmpop([key1, key2], ScoreFilter.MAX, 0.1) == [ key1.encode(), @@ -4402,7 +4467,7 @@ async def test_bzmpop(self, redis_client: TGlideClient): assert await redis_client.bzmpop([key1], ScoreFilter.MAX, 0.1, 0) # check that order of entries in the response is preserved - entries = {} + entries: Dict[TEncodable, float] = {} for i in range(0, 10): entries.update({f"a{i}": float(i)}) @@ -4410,7 +4475,7 @@ async def test_bzmpop(self, redis_client: TGlideClient): result = await redis_client.bzmpop([key2], ScoreFilter.MIN, 0.1, 10) assert result is not None result_map = cast(Mapping[bytes, float], result[1]) - assert compare_maps(entries, result_map) is True + assert compare_maps(entries, result_map) is True # type: ignore async def endless_bzmpop_call(): await redis_client.bzmpop(["non_existent_key"], ScoreFilter.MAX, 0) @@ -4425,7 +4490,7 @@ async def endless_bzmpop_call(): async def test_zrandmember(self, redis_client: TGlideClient): key = get_random_string(10) string_key = get_random_string(10) - scores = {"one": 1, "two": 2} + scores: Mapping[TEncodable, float] = {"one": 1, "two": 2} assert await redis_client.zadd(key, scores) == 2 member = await redis_client.zrandmember(key) @@ -4444,7 +4509,7 @@ async def test_zrandmember(self, redis_client: TGlideClient): async def test_zrandmember_count(self, redis_client: TGlideClient): key = get_random_string(10) string_key = get_random_string(10) - scores = {"one": 1, "two": 2} + scores: Mapping[TEncodable, float] = {"one": 1, "two": 2} assert await redis_client.zadd(key, scores) == 2 # unique values are expected as count is positive @@ -4473,7 +4538,7 @@ async def test_zrandmember_count(self, redis_client: TGlideClient): async def test_zrandmember_withscores(self, redis_client: TGlideClient): key = get_random_string(10) string_key = get_random_string(10) - scores = {"one": 1, "two": 2} + scores: Mapping[TEncodable, float] = {"one": 1, "two": 2} assert await redis_client.zadd(key, scores) == 2 # unique values are expected as count is positive @@ -4513,8 +4578,16 @@ async def test_zintercard(self, redis_client: TGlideClient): string_key = f"{{testKey}}:4-{get_random_string(10)}" non_existing_key = f"{{testKey}}:5-{get_random_string(10)}" - member_scores1 = {"one": 1.0, "two": 2.0, "three": 3.0} - member_scores2 = {"two": 2.0, "three": 3.0, "four": 4.0} + member_scores1: Mapping[TEncodable, float] = { + "one": 1.0, + "two": 2.0, + "three": 3.0, + } + member_scores2: Mapping[TEncodable, float] = { + "two": 2.0, + "three": 3.0, + "four": 4.0, + } assert await redis_client.zadd(key1, member_scores1) == 3 assert await redis_client.zadd(key2, member_scores2) == 3 @@ -4578,15 +4651,15 @@ async def test_zmpop(self, redis_client: TGlideClient): assert await redis_client.zmpop([key1], ScoreFilter.MAX, 0) # check that order of entries in the response is preserved - entries = {} + entries: Dict[TEncodable, float] = {} for i in range(0, 10): - entries.update({f"a{i}": float(i)}) + entries[f"a{i}"] = float(i) assert await redis_client.zadd(key2, entries) == 10 result = await redis_client.zmpop([key2], ScoreFilter.MIN, 10) assert result is not None result_map = cast(Mapping[bytes, float], result[1]) - assert compare_maps(entries, result_map) is True + assert compare_maps(entries, result_map) is True # type: ignore @pytest.mark.parametrize("cluster_mode", [True, False]) @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) @@ -6619,11 +6692,11 @@ async def test_bitpos_and_bitpos_interval(self, redis_client: TGlideClient): async def test_bitop(self, redis_client: TGlideClient): key1 = f"{{testKey}}:1-{get_random_string(10)}" key2 = f"{{testKey}}:2-{get_random_string(10)}" - keys = [key1, key2] - destination = f"{{testKey}}:3-{get_random_string(10)}" + keys: List[TEncodable] = [key1, key2] + destination: TEncodable = f"{{testKey}}:3-{get_random_string(10)}" non_existing_key1 = f"{{testKey}}:4-{get_random_string(10)}" non_existing_key2 = f"{{testKey}}:5-{get_random_string(10)}" - non_existing_keys = [non_existing_key1, non_existing_key2] + non_existing_keys: List[TEncodable] = [non_existing_key1, non_existing_key2] set_key = f"{{testKey}}:6-{get_random_string(10)}" value1 = "foobar" value2 = "abcdef" @@ -7289,7 +7362,7 @@ async def test_fcall_with_key(self, redis_client: GlideClusterClient): key1 = f"{{testKey}}:1-{get_random_string(10)}" key2 = f"{{testKey}}:2-{get_random_string(10)}" - keys = [key1, key2] + keys: List[TEncodable] = [key1, key2] route = SlotKeyRoute(SlotType.PRIMARY, key1) lib_name = f"mylib1C{get_random_string(5)}" func_name = f"myfunc1c{get_random_string(5)}" @@ -7382,7 +7455,7 @@ async def test_fcall_readonly_function(self, redis_client: GlideClusterClient): async def test_srandmember(self, redis_client: TGlideClient): key = get_random_string(10) string_key = get_random_string(10) - elements = ["one", "two"] + elements: List[TEncodable] = ["one", "two"] assert await redis_client.sadd(key, elements) == 2 member = await redis_client.srandmember(key) @@ -7401,7 +7474,7 @@ async def test_srandmember(self, redis_client: TGlideClient): async def test_srandmember_count(self, redis_client: TGlideClient): key = get_random_string(10) string_key = get_random_string(10) - elements = ["one", "two"] + elements: List[TEncodable] = ["one", "two"] assert await redis_client.sadd(key, elements) == 2 # unique values are expected as count is positive @@ -7678,13 +7751,11 @@ async def test_lolwut(self, redis_client: TGlideClient): # test with single-node route result = await redis_client.lolwut(2, route=RandomNode()) assert isinstance(result, bytes) - result_decoded = convert_bytes_to_string_object(result) - assert "Redis ver. " in node_result + assert b"Redis ver. " in result result = await redis_client.lolwut(2, [10, 20], RandomNode()) assert isinstance(result, bytes) - result_decoded = convert_bytes_to_string_object(result) - assert "Redis ver. " in node_result + assert b"Redis ver. " in result @pytest.mark.parametrize("cluster_mode", [True]) @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) @@ -7927,7 +7998,7 @@ async def test_lpos(self, redis_client: TGlideClient): return pytest.mark.skip(reason=f"Redis version required >= {min_version}") key = f"{{key}}-1{get_random_string(5)}" non_list_key = f"{{key}}-2{get_random_string(5)}" - mylist = ["a", "a", "b", "c", "a", "b"] + mylist: List[TEncodable] = ["a", "a", "b", "c", "a", "b"] # basic case await redis_client.rpush(key, mylist) @@ -7986,8 +8057,12 @@ async def test_multi_key_command_returns_cross_slot_error( redis_client.zdiff(["abc", "zxy", "lkn"]), redis_client.zdiff_withscores(["abc", "zxy", "lkn"]), redis_client.zrangestore("abc", "zxy", RangeByIndex(0, -1)), - redis_client.zinterstore("{xyz}", ["{abc}", "{def}"]), - redis_client.zunionstore("{xyz}", ["{abc}", "{def}"]), + redis_client.zinterstore( + "{xyz}", cast(Union[List[Union[TEncodable]]], ["{abc}", "{def}"]) + ), + redis_client.zunionstore( + "{xyz}", cast(Union[List[Union[TEncodable]]], ["{abc}", "{def}"]) + ), redis_client.bzpopmin(["abc", "zxy", "lkn"], 0.5), redis_client.bzpopmax(["abc", "zxy", "lkn"], 0.5), redis_client.smove("abc", "def", "_"), @@ -8000,9 +8075,11 @@ async def test_multi_key_command_returns_cross_slot_error( redis_client.pfcount(["def", "ghi"]), redis_client.pfmerge("abc", ["def", "ghi"]), redis_client.zinter(["def", "ghi"]), - redis_client.zinter_withscores(["def", "ghi"]), + redis_client.zinter_withscores( + cast(Union[List[TEncodable]], ["def", "ghi"]) + ), redis_client.zunion(["def", "ghi"]), - redis_client.zunion_withscores(["def", "ghi"]), + redis_client.zunion_withscores(cast(List[TEncodable], ["def", "ghi"])), redis_client.sort_store("abc", "zxy"), redis_client.lmove("abc", "zxy", ListDirection.LEFT, ListDirection.LEFT), redis_client.blmove( @@ -8361,10 +8438,10 @@ async def test_sscan(self, redis_client: GlideClusterClient): result_cursor_index = 0 result_collection_index = 1 default_count = 10 - num_members = list( + num_members: List[TEncodable] = list( map(str, range(50000)) ) # Use large dataset to force an iterative cursor. - char_members = ["a", "b", "c", "d", "e"] + char_members: List[TEncodable] = ["a", "b", "c", "d", "e"] # Empty set result = await redis_client.sscan(key1, initial_cursor) @@ -8392,7 +8469,7 @@ async def test_sscan(self, redis_client: GlideClusterClient): # Result contains a subset of the key assert await redis_client.sadd(key1, num_members) == len(num_members) result_cursor = "0" - result_values = set() # type: set[str] + result_values = set() # type: set[bytes] result = cast( list, convert_bytes_to_string_object( @@ -8400,7 +8477,7 @@ async def test_sscan(self, redis_client: GlideClusterClient): ), ) result_cursor = str(result[result_cursor_index]) - result_values.update(result[result_collection_index]) + result_values.update(result[result_collection_index]) # type: ignore # 0 is returned for the cursor of the last iteration. while result_cursor != "0": @@ -8458,12 +8535,12 @@ async def test_zscan(self, redis_client: GlideClusterClient): result_cursor_index = 0 result_collection_index = 1 default_count = 20 - num_map = {} + num_map: Dict[TEncodable, float] = {} num_map_with_str_scores = {} for i in range(50000): # Use large dataset to force an iterative cursor. num_map.update({"value " + str(i): i}) num_map_with_str_scores.update({"value " + str(i): str(i)}) - char_map = {"a": 0, "b": 1, "c": 2, "d": 3, "e": 4} + char_map: Mapping[TEncodable, float] = {"a": 0, "b": 1, "c": 2, "d": 3, "e": 4} char_map_with_str_scores = { "a": "0", "b": "1", @@ -8573,10 +8650,10 @@ async def test_hscan(self, redis_client: GlideClusterClient): result_cursor_index = 0 result_collection_index = 1 default_count = 20 - num_map = {} + num_map: dict[TEncodable, TEncodable] = {} for i in range(50000): # Use large dataset to force an iterative cursor. num_map.update({"field " + str(i): "value " + str(i)}) - char_map = { + char_map: Dict[TEncodable, TEncodable] = { "field a": "value a", "field b": "value b", "field c": "value c", @@ -8605,7 +8682,7 @@ async def test_hscan(self, redis_client: GlideClusterClient): assert result[result_cursor_index] == initial_cursor.encode() assert len(result_collection) == len(char_map) * 2 assert convert_list_to_dict(result_collection) == cast( - dict, convert_string_to_bytes_object(char_map) + dict, convert_string_to_bytes_object(char_map) # type: ignore ) result = await redis_client.hscan(key1, initial_cursor, match="field a") diff --git a/python/python/tests/test_transaction.py b/python/python/tests/test_transaction.py index be29dae28e..a557dd1788 100644 --- a/python/python/tests/test_transaction.py +++ b/python/python/tests/test_transaction.py @@ -405,7 +405,7 @@ async def transaction_test( transaction.zpopmax(key8) args.append({b"three": 3.0}) transaction.zpopmin(key8) - args.append({}) + args.append({}) # type: ignore transaction.zremrangebyscore(key8, InfBound.NEG_INF, InfBound.POS_INF) args.append(0) transaction.zremrangebylex(key8, InfBound.NEG_INF, InfBound.POS_INF) @@ -438,15 +438,17 @@ async def transaction_test( args.append(3) transaction.zinter([key14, key15]) args.append([b"one", b"two"]) - transaction.zinter_withscores([key14, key15]) + transaction.zinter_withscores(cast(list[str | bytes], [key14, key15])) args.append({b"one": 2.0, b"two": 4.0}) - transaction.zinterstore(key8, [key14, key15]) + transaction.zinterstore(key8, cast(list[str | bytes], [key14, key15])) args.append(2) transaction.zunion([key14, key15]) args.append([b"one", b"three", b"two"]) - transaction.zunion_withscores([key14, key15]) + transaction.zunion_withscores(cast(list[str | bytes], [key14, key15])) args.append({b"one": 2.0, b"two": 4.0, b"three": 3.5}) - transaction.zunionstore(key8, [key14, key15], AggregationType.MAX) + transaction.zunionstore( + key8, cast(list[str | bytes], [key14, key15]), AggregationType.MAX + ) args.append(3) transaction.pfadd(key10, ["a", "b", "c"]) diff --git a/python/python/tests/utils/utils.py b/python/python/tests/utils/utils.py index 959191ec15..9a684a09e3 100644 --- a/python/python/tests/utils/utils.py +++ b/python/python/tests/utils/utils.py @@ -100,8 +100,8 @@ def compare_maps( Compare two maps by converting them to JSON strings and checking for equality, including property order. Args: - map1 (Optional[Union[Mapping[Union[str, bytes], TResult], Dict[Union[str, bytes], TResult]]]): The first map to compare. - map2 (Optional[Union[Mapping[Union[str, bytes], TResult], Dict[Union[str, bytes], TResult]]]): The second map to compare. + map1 (Optional[Union[Mapping[str, TResult], Dict[str, TResult], Mapping[bytes, TResult], Dict[bytes, TResult]]]): The first map to compare. + map2 (Optional[Union[Mapping[str, TResult], Dict[str, TResult], Mapping[bytes, TResult], Dict[bytes, TResult]]]): The second map to compare. Returns: bool: True if the maps are equal, False otherwise. @@ -174,7 +174,6 @@ def convert(item: Any) -> Any: def convert_string_to_bytes_object( - # TODO: remove the bytes options string_structure: Optional[ Union[ List[Any],