summaryrefslogtreecommitdiff
path: root/redis
diff options
context:
space:
mode:
authordvora-h <67596500+dvora-h@users.noreply.github.com>2022-02-22 13:11:55 +0200
committerGitHub <noreply@github.com>2022-02-22 13:11:55 +0200
commitfa76ac49a9ea02c204bd4f1644f39d90140cf356 (patch)
tree0578d5e4748c64824a1f72ed3b64f23c8f57368b /redis
parentf2e34739fccab28a28a066a3ece955eb455b32f9 (diff)
downloadredis-py-fa76ac49a9ea02c204bd4f1644f39d90140cf356.tar.gz
Add support for Redis 7 functions (#1998)
* add function support * linters * test fcall * decode reponses for unstable_r * linters * fix evalsho_ro test * fix eval_ro test * add response callbaks * linters
Diffstat (limited to 'redis')
-rwxr-xr-xredis/client.py4
-rw-r--r--redis/commands/core.py126
-rwxr-xr-xredis/connection.py11
3 files changed, 139 insertions, 2 deletions
diff --git a/redis/client.py b/redis/client.py
index 22c5dc1..0eade79 100755
--- a/redis/client.py
+++ b/redis/client.py
@@ -733,6 +733,10 @@ class AbstractRedis:
"CONFIG RESETSTAT": bool_ok,
"CONFIG SET": bool_ok,
"DEBUG OBJECT": parse_debug_object,
+ "FUNCTION DELETE": bool_ok,
+ "FUNCTION FLUSH": bool_ok,
+ "FUNCTION LOAD": bool_ok,
+ "FUNCTION RESTORE": bool_ok,
"GEOHASH": lambda r: list(map(str_if_bytes, r)),
"GEOPOS": lambda r: list(
map(lambda ll: (float(ll[0]), float(ll[1])) if ll is not None else None, r)
diff --git a/redis/commands/core.py b/redis/commands/core.py
index 80bc55f..e74550f 100644
--- a/redis/commands/core.py
+++ b/redis/commands/core.py
@@ -5429,6 +5429,131 @@ class ClusterCommands(CommandsProtocol):
return self.execute_command("READONLY", **kwargs)
+class FunctionCommands:
+ """
+ Redis Function commands
+ """
+
+ def function_load(
+ self,
+ engine: str,
+ library: str,
+ code: str,
+ replace: Optional[bool] = False,
+ description: Optional[str] = None,
+ ) -> str:
+ """
+ Load a library to Redis.
+ :param engine: the name of the execution engine for the library
+ :param library: the unique name of the library
+ :param code: the source code
+ :param replace: changes the behavior to replace the library if a library called
+ ``library`` already exists
+ :param description: description to the library
+
+ For more information check https://redis.io/commands/function-load
+ """
+ pieces = [engine, library]
+ if replace:
+ pieces.append("REPLACE")
+ if description is not None:
+ pieces.append(description)
+ pieces.append(code)
+ return self.execute_command("FUNCTION LOAD", *pieces)
+
+ def function_delete(self, library: str) -> str:
+ """
+ Delete the library called ``library`` and all its functions.
+
+ For more information check https://redis.io/commands/function-delete
+ """
+ return self.execute_command("FUNCTION DELETE", library)
+
+ def function_flush(self, mode: str = "SYNC") -> str:
+ """
+ Deletes all the libraries.
+
+ For more information check https://redis.io/commands/function-flush
+ """
+ return self.execute_command("FUNCTION FLUSH", mode)
+
+ def function_list(
+ self, library: Optional[str] = "*", withcode: Optional[bool] = False
+ ) -> List:
+ """
+ Return information about the functions and libraries.
+ :param library: pecify a pattern for matching library names
+ :param withcode: cause the server to include the libraries source
+ implementation in the reply
+ """
+ args = ["LIBRARYNAME", library]
+ if withcode:
+ args.append("WITHCODE")
+ return self.execute_command("FUNCTION LIST", *args)
+
+ def _fcall(
+ self, command: str, function, numkeys: int, *keys_and_args: Optional[List]
+ ) -> str:
+ return self.execute_command(command, function, numkeys, *keys_and_args)
+
+ def fcall(self, function, numkeys: int, *keys_and_args: Optional[List]) -> str:
+ """
+ Invoke a function.
+
+ For more information check https://redis.io/commands/fcall
+ """
+ return self._fcall("FCALL", function, numkeys, *keys_and_args)
+
+ def fcall_ro(self, function, numkeys: int, *keys_and_args: Optional[List]) -> str:
+ """
+ This is a read-only variant of the FCALL command that cannot
+ execute commands that modify data.
+
+ For more information check https://redis.io/commands/fcal_ro
+ """
+ return self._fcall("FCALL_RO", function, numkeys, *keys_and_args)
+
+ def function_dump(self) -> str:
+ """
+ Return the serialized payload of loaded libraries.
+
+ For more information check https://redis.io/commands/function-dump
+ """
+ from redis.client import NEVER_DECODE
+
+ options = {}
+ options[NEVER_DECODE] = []
+
+ return self.execute_command("FUNCTION DUMP", **options)
+
+ def function_restore(self, payload: str, policy: Optional[str] = "APPEND") -> str:
+ """
+ Restore libraries from the serialized ``payload``.
+ You can use the optional policy argument to provide a policy
+ for handling existing libraries.
+
+ For more information check https://redis.io/commands/function-restore
+ """
+ return self.execute_command("FUNCTION RESTORE", payload, policy)
+
+ def function_kill(self) -> str:
+ """
+ Kill a function that is currently executing.
+
+ For more information check https://redis.io/commands/function-kill
+ """
+ return self.execute_command("FUNCTION KILL")
+
+ def function_stats(self) -> list:
+ """
+ Return information about the function that's currently running
+ and information about the available execution engines.
+
+ For more information check https://redis.io/commands/function-stats
+ """
+ return self.execute_command("FUNCTION STATS")
+
+
AsyncClusterCommands = ClusterCommands
@@ -5474,6 +5599,7 @@ class CoreCommands(
ModuleCommands,
PubSubCommands,
ScriptCommands,
+ FunctionCommands,
):
"""
A class containing all of the implemented redis commands. This class is
diff --git a/redis/connection.py b/redis/connection.py
index 891695d..189cecb 100755
--- a/redis/connection.py
+++ b/redis/connection.py
@@ -463,10 +463,17 @@ class HiredisParser(BaseParser):
self._next_response = False
return response
- response = self._reader.gets()
+ if disable_decoding:
+ response = self._reader.gets(False)
+ else:
+ response = self._reader.gets()
+
while response is False:
self.read_from_socket()
- response = self._reader.gets()
+ if disable_decoding:
+ response = self._reader.gets(False)
+ else:
+ response = self._reader.gets()
# if an older version of hiredis is installed, we need to attempt
# to convert ResponseErrors to their appropriate types.
if not HIREDIS_SUPPORTS_CALLABLE_ERRORS: