Skip to content

Commit

Permalink
Delete the first-defined (and thus "duplicate") Script class (#3333)
Browse files Browse the repository at this point in the history
The second definition was copied over the first definition,
with the following changes:

* The type annotations were copied to the second definition
* The mutable default arguments to the `keys` and `args` parameters
  were replaced with `None`, as is best-practice.

Closes #3332

Co-authored-by: Vladyslav Vildanov <[email protected]>
  • Loading branch information
kurtmckee and vladvildanov authored Sep 2, 2024
1 parent c6faa65 commit 93b9d85
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 61 deletions.
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
* Prevent async ClusterPipeline instances from becoming "false-y" in case of empty command stack (#3061)
* Close Unix sockets if the connection attempt fails. This prevents `ResourceWarning`s. (#3314)
* Close SSL sockets if the connection attempt fails, or if validations fail. (#3317)
* Eliminate mutable default arguments in the `redis.commands.core.Script` class. (#3332)

* 4.1.3 (Feb 8, 2022)
* Fix flushdb and flushall (#1926)
Expand Down
80 changes: 19 additions & 61 deletions redis/commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -5475,11 +5475,7 @@ def __init__(self, registered_client: "redis.client.Redis", script: ScriptTextT)
if isinstance(script, str):
# We need the encoding from the client in order to generate an
# accurate byte representation of the script
try:
encoder = registered_client.connection_pool.get_encoder()
except AttributeError:
# Cluster
encoder = registered_client.get_encoder()
encoder = self.get_encoder()
script = encoder.encode(script)
self.sha = hashlib.sha1(script).hexdigest()

Expand Down Expand Up @@ -5510,6 +5506,24 @@ def __call__(
self.sha = client.script_load(self.script)
return client.evalsha(self.sha, len(keys), *args)

def get_encoder(self):
"""Get the encoder to encode string scripts into bytes."""
try:
return self.registered_client.get_encoder()
except AttributeError:
# DEPRECATED
# In version <=4.1.2, this was the code we used to get the encoder.
# However, after 4.1.2 we added support for scripting in clustered
# redis. ClusteredRedis doesn't have a `.connection_pool` attribute
# so we changed the Script class to use
# `self.registered_client.get_encoder` (see above).
# However, that is technically a breaking change, as consumers who
# use Scripts directly might inject a `registered_client` that
# doesn't have a `.get_encoder` field. This try/except prevents us
# from breaking backward-compatibility. Ideally, it would be
# removed in the next major release.
return self.registered_client.connection_pool.get_encoder()


class AsyncScript:
"""
Expand Down Expand Up @@ -6293,62 +6307,6 @@ def command(self) -> ResponseT:
return self.execute_command("COMMAND")


class Script:
"""
An executable Lua script object returned by ``register_script``
"""

def __init__(self, registered_client, script):
self.registered_client = registered_client
self.script = script
# Precalculate and store the SHA1 hex digest of the script.

if isinstance(script, str):
# We need the encoding from the client in order to generate an
# accurate byte representation of the script
encoder = self.get_encoder()
script = encoder.encode(script)
self.sha = hashlib.sha1(script).hexdigest()

def __call__(self, keys=[], args=[], client=None):
"Execute the script, passing any required ``args``"
if client is None:
client = self.registered_client
args = tuple(keys) + tuple(args)
# make sure the Redis server knows about the script
from redis.client import Pipeline

if isinstance(client, Pipeline):
# Make sure the pipeline can register the script before executing.
client.scripts.add(self)
try:
return client.evalsha(self.sha, len(keys), *args)
except NoScriptError:
# Maybe the client is pointed to a different server than the client
# that created this instance?
# Overwrite the sha just in case there was a discrepancy.
self.sha = client.script_load(self.script)
return client.evalsha(self.sha, len(keys), *args)

def get_encoder(self):
"""Get the encoder to encode string scripts into bytes."""
try:
return self.registered_client.get_encoder()
except AttributeError:
# DEPRECATED
# In version <=4.1.2, this was the code we used to get the encoder.
# However, after 4.1.2 we added support for scripting in clustered
# redis. ClusteredRedis doesn't have a `.connection_pool` attribute
# so we changed the Script class to use
# `self.registered_client.get_encoder` (see above).
# However, that is technically a breaking change, as consumers who
# use Scripts directly might inject a `registered_client` that
# doesn't have a `.get_encoder` field. This try/except prevents us
# from breaking backward-compatibility. Ideally, it would be
# removed in the next major release.
return self.registered_client.connection_pool.get_encoder()


class AsyncModuleCommands(ModuleCommands):
async def command_info(self) -> None:
return super().command_info()
Expand Down

0 comments on commit 93b9d85

Please sign in to comment.