Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert #2104, provide way to disable disconnects in read_response() #2506

Conversation

kristjanvalur
Copy link
Contributor

@kristjanvalur kristjanvalur commented Dec 12, 2022

Pull Request check-list

Please make sure to review and check all of these items:

  • Does $ tox pass with this change (including linting)?
  • Do the CI tests pass with this change (enable it first in your forked repo and wait for the github action build to finish)?
  • Is the new or changed code fully tested?
  • Is a documentation update included (if this change modifies existing APIs, or introduces new ones)?
  • Is there an example added to the examples folder (if applicable)?
  • Was the change added to CHANGES file?

NOTE: these things are not required to open a PR and can be done
afterwards / while the PR is open.

Description of change

PR #2104, a fix to #2103 caused a regression for issue #1128. This has been dicussed in issue #2499.

This PR provides

A lot of code uses the Command/Response pattern and if an exception occurs during that, the conneciton is in an
indeterminate state:

  • Connection.send_command() has no way to continue sending a command if there is a benign interrupt, e.g. a Timeout. Ensuring that the connection is closed in this case is prudent, because some code does capture BaseExceptions, e.g. gevent style code.
  • Code often pairs send_command() and read_response() and even if the error happens in read_response() (which is in principle resumable), application code has no way of knowing and so closing the connection is necessary.

To support PubSub, and other cases where an application may want to properly handle Timeouts and other errors while reading reponses, a new argument is added to read_response(), which disables the automatic disconnect() of the connection when an exception is occurred. It is then the responsibility of the caller to take appropriate action.

@codecov-commenter
Copy link

codecov-commenter commented Dec 12, 2022

Codecov Report

Patch coverage: 30.76% and project coverage change: -31.81 ⚠️

Comparison is base (e1017fd) 92.29% compared to head (e34f456) 60.49%.

📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more

Additional details and impacted files
@@             Coverage Diff             @@
##           master    #2506       +/-   ##
===========================================
- Coverage   92.29%   60.49%   -31.81%     
===========================================
  Files         116      116               
  Lines       29890    29935       +45     
===========================================
- Hits        27588    18110     -9478     
- Misses       2302    11825     +9523     
Impacted Files Coverage Δ
redis/asyncio/client.py 27.08% <0.00%> (-65.54%) ⬇️
tests/test_asyncio/test_connection.py 39.35% <0.00%> (-58.71%) ⬇️
tests/test_connection.py 68.59% <0.00%> (-29.76%) ⬇️
tests/test_commands.py 70.49% <26.31%> (-19.52%) ⬇️
tests/test_asyncio/test_commands.py 73.64% <33.33%> (-24.72%) ⬇️
redis/asyncio/connection.py 82.54% <37.50%> (-5.08%) ⬇️
redis/connection.py 84.14% <44.44%> (-2.04%) ⬇️
redis/client.py 70.37% <100.00%> (-19.15%) ⬇️

... and 73 files with indirect coverage changes

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

Comment on lines 3027 to 3028
try:
async with async_timeout.timeout(0.1):
assert await task == "done"
except asyncio.TimeoutError:
task.cancel()
await task
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a 2nd phase of the same test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure exactly what you're referring to. The 'helper´ gets interrupted, then does another request. The main function then sets out to wait for the 'helper' to finish. The timeout is there to ensure that we finish, even if the helper task hangs.

print("start")

def helper():
try:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit - even though it's not the test itself, can replace with

Suggested change
try:
with pytest.raises(CancelledError):

print("canc")
pass # we got some BaseException.
# if all is well, we can continue.
r.set("status", "down") # should not hang
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this also exercise the "command expects int but got back str" scenario?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. It excercises the originally reported scenario: A blocking wait is initiated, and even though a new command is sent on the channel, the server is still in blocking wait mode.
It is harder to interrupt a half-read response, although not impossible by using mocking. I can look into that.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That scenario doesn't require half-read. It's an interrupt between send_command and parse_response:

send_command("EXISTS foo")
<interrupt>
send_command("GET foo")
parse_response() --> expected str, got int (from previous command)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add a half-read test case.

tests/test_commands.py Outdated Show resolved Hide resolved
"""
print("start")

def helper():
Copy link

@ikonst ikonst Dec 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def helper():
def helper() -> None:

IIUC there's no way to get a retval from a thread, though you can pass a mutable object and use that to communicate.

In particular it might be that we need to marshal errors to avoid them being silently ignored? e.g. https://github.com/bjoluc/pytest-reraise

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test is relying on the thread actually finishing. There is no way to interrupt a hanging thread in python. If these tests fail, the test suite hangs. I'm open to suggestions on how to avoid that. I suppose that an old-school timeout can be added.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, there is no type hinting in redis-py, not going to start adding that to unit tests :)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I mostly just meant for you to remove the retval. No need to type-annotate, though I do notice that some stuff is type-annotated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, there is the odd type hinting, but It is not consistently applied. I guess people add it to help their dev tools with code completion.

@Chronial
Copy link
Contributor

Note that this is not enough to fix everything broken by #2104. At least the other callsites of send_command and read_response are also affected.

@ikonst
Copy link

ikonst commented Dec 13, 2022

I saw the other send_commands too, but wasn't sure whether to nitpick since they seem to be in distinct flows:

  • self.send_command("PING") in SentinelManagedConnection
  • connection.send_command("READONLY") in RedisCluster

but overall I'd think those would also do well to be consolidated under a single pattern

@ikonst
Copy link

ikonst commented Dec 13, 2022

Also, might be good to remove the except Exception: unless there's a specific reason for it.

@kristjanvalur
Copy link
Contributor Author

Also, might be good to remove the except Exception: unless there's a specific reason for it.

Which one is that?

@ikonst
Copy link

ikonst commented Dec 13, 2022

Also, might be good to remove the except Exception: unless there's a specific reason for it.

Which one is that?

except Exception:
self.disconnect()
raise

except Exception:
self.disconnect()
raise

# blocking pop
with patch.object(
socket.socket, "recv_into", side_effect=CancelledError
) as mock_recv:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
) as mock_recv:
):

unless you use mock_recv later

def helper():
try:
with pytest.raises(BaseException):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that unless you propagate exceptions from the thread to the test, we'd be unaware of this pytest.raises assertion failing.

@Chronial
Copy link
Contributor

Chronial commented Dec 14, 2022

Since you seem really determined to go down this route:

You now disconnect on the outside for any exception. Are you sure this is correct? This will at least disconnect twice sometimes. And are there really no exceptions that should go through without disconnect?

Since you are against rolling back #2104, you should denote the API change in the functions affected, because they now have a rather surprising API. send_command needs a comment explaining that if it raises, the connection is now in an undefined state and the caller needs to disconnect it. Same for read_response and parse_response.

If you succeed with #2510, that comment could change on the async response functions to explaining that if the Exception was a CancellationException, the connection is not undefined, but still holds the previous response. If it is another Exception like KeyboardInterrupt, the connection will still be broken.

@ikonst
Copy link

ikonst commented Dec 14, 2022

Do we agree that under all scenarios, interrupted send_command:

  • leaves the socket in a defined state?
  • leaves the redis.Connection in an undefined state (per RESP protocol)?

So expecting socket to handle this (e.g. by disconnecting) would be wrong, since socket will be making assumptions about a higher-level protocol. However, should the responsibility fall unto redis.Connection or unto all its callers?

Arguments in favor of making redis.Connection.send_command responsible:

  • Less code repetition
  • Lower chance of forgetting to do it at a call site
  • Scope: redis.Connection has knowledge of RESP, and is expected to make decisions based on that knowledge

If it is another Exception like KeyboardInterrupt, the connection will still be broken.

Maybe a side-note, but when interruption can happen at any point, as it is with KeyboardInterrupt, I think no approach could protect against an undefined state, so maybe there's no use thinking about it.

@tobymao
Copy link

tobymao commented Dec 14, 2022

Would it be easier to just roll back #2104?

@ikonst
Copy link

ikonst commented Dec 14, 2022

@tobymao no, because it was done for a reason

Comment on lines +3018 to +3019
# if all is well, we can continue. The following should not hang.
await r.set("status", "down")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still tbd to validate that not only you don't "hang", but also that the next read response matches the command.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, a separate test which continues an interrupted read seems proper.

@Chronial
Copy link
Contributor

Chronial commented Dec 14, 2022

Maybe a side-note, but when interruption can happen at any point, as it is with KeyboardInterrupt, I think no approach could protect against an undefined state, so maybe there's no use thinking about it.

Before #2104 this seemed to work quite well.

@ikonst
Copy link

ikonst commented Dec 14, 2022

Before #2104 this seemed to work quite well.

You can't guarantee that KeyboardInterrupt doesn't happen twice, once when you recv and another time before you run disconnect(). If something happened, it's by chance, because most of the time you had to Ctrl-C was during lengthy I/O calls.

@Chronial
Copy link
Contributor

In production, where this matters nobody is pressing Ctrl-C. And if they are, they should know not to press it twice if they want sensible shutdown. In the important scenario, like the one you explained before, the exception is raised by a framework. Obviously it should only raise a single one.

@kristjanvalur
Copy link
Contributor Author

Also, might be good to remove the except Exception: unless there's a specific reason for it.

Right, this needs to be BaseException (naked except clauses are deprectated).

Ok, let's give this PR another whirl.

@kristjanvalur
Copy link
Contributor Author

kristjanvalur commented Dec 15, 2022

You now disconnect on the outside for any exception. Are you sure this is correct? This will at least disconnect twice sometimes. And are there really no exceptions that should go through without disconnect?
Disconnecting twice is safe.
I think we have established that there should be no exceptions going through without a disconnect. That was previously the case with all exceptions while reading a response. Now BaseExceptions don't disconnect, in the Connection but they do cause a disconnect in the scope of a command/response pair.

Since you are against rolling back #2104, you should denote the API change in the functions affected, because they now have a rather surprising API. send_command needs a comment explaining that if it raises, the connection is now in an undefined state and the caller needs to disconnect it. Same for read_response and parse_response.

This is incorrect. It it is only in the case of BaseExceptions that it is kept open, exceptions that are not handled or caught anywhere and typically result in an exit. (In async code, the TimeoutError does result in a disconnect().
However, since there is no way to restart a partially completed send (the API doesn't support it, even if we would keep track of the sent data), I see no harm in closing it. Particularly since it may help the code jive with gevent. I'll make a PR to fix the send_command.

(We could, if we wanted, create a different api which could be restarted when a Timeout has previously occurred.)

If you succeed with #2510, that comment could change on the async response functions to explaining that if the Exception was a CancellationException, the connection is not undefined, but still holds the previous response. If it is another Exception like KeyboardInterrupt, the connection will still be broken.

Fair point. Yes, a timeout on read_response really should mean that the application can retry, and that should be documented, I guess, if the opposite is already undocumented. Otherwise, in all APIs that I am familiar with, a timeout on an operation which provides a "timeout" parameter, means that the operation can be retried.

@Chronial
Copy link
Contributor

You now disconnect on the outside for any exception. Are you sure this is correct? This will at least disconnect twice sometimes. And are there really no exceptions that should go through without disconnect?
Disconnecting twice is safe.

I think we have established that there should be no exceptions going through without a disconnect. That was previously the case with all exceptions while reading a response. Now BaseExceptions don't disconnect, in the Connection but they do cause a
disconnect in the scope of a command/response pair.

Yes: "That was previously the case with all exceptions while reading a response". You extended the scope of the try-catch. Now, for example, any exception raised by a response callback will also disconnect the connection. That was not previously the case.

@kristjanvalur
Copy link
Contributor Author

Yes: "That was previously the case with all exceptions while reading a response". You extended the scope of the try-catch. Now, for example, any exception raised by a response callback will also disconnect the connection. That was not previously the case.

Okay, I think it is simplest that I restore the original behaviour of connection.parse_response(), since there simply seem to be too many cases that rely on it. Even though none of them was caught by the test suite. I'll modify this PR so that the BaseException behaviour becomes optional.

@kristjanvalur kristjanvalur force-pushed the kristjan/interrupted-send-receive branch from 7dccb43 to 1985884 Compare December 15, 2022 15:03
@kristjanvalur kristjanvalur changed the title Connections interrupted during Command/Response transaction must be disconnected. Revert #2104, provide way to disable disconnects in read_response() Dec 15, 2022
Comment on lines 767 to 768
# The send_packed_command api does not support re-trying a partially
# sent message, so there is no point in keeping the connection open.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider: The lack of support is really RESP's (the wire protocol).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually no. You can keep the buffer of data (the message) around in a send buffer. the actual socket.send() message lets you know how much of this has been successfully delivered to underlying layers. So a re-triable API could, for example, accept a None as the data, and then continue sending from where it left off, if it has a buffer in place. Consider this api:

def send_packed_command(message: Optional[str]):
   """ Send the packed command, or, if None, a previous call must not have completed and the function will
        will resume sending that data over the wire.
  """
  ...

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, on the Python side (e.g. in Connection) we could choose to implement a write buffer and "continue where we left off". As I mentioned before, the problem with a write buffer would be the potential of flushing out a command that's stale from an app code's perspective.

What I'd rather see, is being able to, instead of flushing a command that can be stale, to send a short control sequence that would cancel a command that's half-written into the socket, turning it into a no-op. This is the feature that RESP protocol doesn't support.

So:

  1. Write buffer: Not an inherent limitation in Python, we simply don't want to do it because it's bad UX.
  2. Cancel a half-written command: Inherent limitation of RESP.

Hence the "problem" is RESP, not send_packed_command.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you are saying, but I'm not even thinking about the "cancel" of the command. That's something I've never seen and in my mind completely unnecessary. For that, you can simply disconnect. I'm primarily thinking about Timeouts, where the transmitting of the command over the wire times out, and you want to maybe do some housekeeping and then continue trying to send the rest of the command.

In the context of this PR, do you suggest that I change this comment somehow? Is it confusing? I always find that code comments help future contributors. A similar comment would have probably caused me to do my original PR differently :)

Copy link

@ikonst ikonst Dec 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'm discussing how we phrase the comment :) I think I understand now.

My perspective:
I called send and caught an exception. Next time I call send, it might be a different command, at a different time, on a different thread. I wouldn't want send_packed_command to flush my previous command at an arbitrary time in the future. I would settle for flushing a short "cancel sequence" instead, but RESP doesn't support that, so instead I'd like it to disconnect.

From that perspective, it's a RESP limitation.

Your perspective:
I called send and caught an exception. Now I want to retry immediately, but send_packed_command didn't tell me where it stopped nor allows me to resume half-way.

From that perspective, it's a send_packed_command limitation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I understand. Let me try to formulate the comment better.

except BaseException:
# The send_packed_command api does not support re-trying a partially
# sent message, so there is no point in keeping the connection open.
# An unknown number of bytes has been sent and the connection is therefore
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if you knew how many bytes were sent (I think you can know), the problem is you can't "take them back".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not about "taking them back", its about "trying again to send the rest". This could (theoretically) be done in case of a timeout, and is the way that many socket.sendall() implementations work. (the underlying socket.send() sends a potential subset of the data and needs to be retried.)

send_packed_api() could be architected in a similar way, but maintain an internal buffer of unsent data so that it can be re-tried.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But of course it's not reasonable to flush a command after an arbitrary delay (could be milliseconds, could be days). The "workaround" supported by RESP is not reasonable for what Redis is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand what you mean. All I'm saying is that sometimes your send() can time out, for various reasons, buffers, server responsiveness, or whatever. It's technically possible to engineer things such that you can at least be sure that you've delivered all of your payload down to the OS to deliver over the wire. What happens after that is anyone's guess. Typically, then, you'd listen for the response, and time out in the listening phase if nothing happens.

This is in no way dissimilar to http, and doesn't have anything to do with RESP as such.

Anyway, I thought I'd comment on that, a different API, allowing one to retry a partially completed send() operation, could mean that it would make sense to keep the connection open. But the current API has no semantics that woudl allow a "retry".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, see the above discussion :)

@chayim
Copy link
Contributor

chayim commented Feb 26, 2023

@kristjanvalur I see the green passes. Ready for a review?

@kristjanvalur
Copy link
Contributor Author

Yes, this has been ready for a long time. The non-green are the spurious failures that the test suite has.

@dvora-h
Copy link
Collaborator

dvora-h commented Mar 16, 2023

@chayim Can you review this?

@kristjanvalur
Copy link
Contributor Author

I'm investigating the test failure.

@kristjanvalur
Copy link
Contributor Author

This is new behaviour with the 3.11 timeout context manager. It doesn't work if there has been a previous cancel on the task.
python/cpython#102780

@kristjanvalur
Copy link
Contributor Author

Oh dear. Now it is hanging because it is no longer possible to cancel an operation, due to this code:

        return await asyncio.shield(
            self._try_send_command_parse_response(conn, *args, **options)
        )

in client.py.
The send command and parse is shielded, so cancelling the command won't cancel it. This leaves the __single_conn_lock held.
I wonder why this was added? It breaks things.

@kristjanvalur
Copy link
Contributor Author

This happened in pr #2666

@ikonst
Copy link

ikonst commented Apr 3, 2023

This issue is your white whale. I'm sorry :) but thanks for the efforts.

@kristjanvalur
Copy link
Contributor Author

Oh my. This here PR actually fixes all the other problems, including #2624 and is a much simpler and cleaner fix than the change from #2666 and related commits. I have started a new pr, #2695 , to move this forward and undo those other changes. It would have saved a lot of trouble if I had been pinged about those other issues, I could have pointed to this PR which has been lingering for months.

@kristjanvalur
Copy link
Contributor Author

Closed this now that #2695 has been merged (a re-creation of this PR)

@kristjanvalur kristjanvalur deleted the kristjan/interrupted-send-receive branch May 11, 2023 07:42
Petitoto pushed a commit to aeecleclair/Hyperion that referenced this pull request Aug 19, 2023
Bumps [redis](https://github.com/redis/redis-py) from 4.6.0 to 5.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/redis/redis-py/releases">redis's
releases</a>.</em></p>
<blockquote>
<h2>5.0.0</h2>
<h2>What's new?</h2>
<h3>Triggers and Functions support</h3>
<p>Triggers and Functions allow you to execute server-side functions
triggered when key values are modified or created in Redis, a stream
entry arrival, or explicitly calling them. Simply put, you can replace
Lua scripts with easy-to-develop JavaScript or TypeScript code. Move
your business logic closer to the data to ensure a lower latency, and
forget about updating dependent key values manually in your code.
<a
href="https://redis.io/docs/interact/programmability/triggers-and-functions/quick_start/">Try
it for yourself with Quick start</a></p>
<h3>Full Redis 7.2 and <a
href="https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md">RESP3
support</a></h3>
<h3>Python 3.7 End-of-Life</h3>
<p><a href="https://devguide.python.org/versions/">Python 3.7 has
reached its end-of-life (EOL) as of June 2023</a>. This means that
starting from this date, Python 3.7 will no longer receive any updates,
including security patches, bug fixes, or improvements. If you continue
to use Python 3.7 post-EOL, you may expose your projects and systems to
potential security vulnerabilities. We ended its support in this version
and strongly recommend migrating to Python 3.10.</p>
<h2>🐛 Bug Fixes</h2>
<ul>
<li>Fix timeout retrying on pipeline execution (<a
href="https://redirect.github.com/redis/redis-py/issues/2812">#2812</a>)</li>
<li>Fix socket garbage collection (<a
href="https://redirect.github.com/redis/redis-py/issues/2859">#2859</a>)</li>
</ul>
<h2>🧰 Maintenance</h2>
<ul>
<li>Updating client license to clear, MIT (<a
href="https://redirect.github.com/redis/redis-py/issues/2884">#2884</a>)</li>
<li>Add py.typed in accordance with PEP-561 (<a
href="https://redirect.github.com/redis/redis-py/issues/2738">#2738</a>)</li>
<li>Dependabot label change (<a
href="https://redirect.github.com/redis/redis-py/issues/2880">#2880</a>)</li>
<li>Fix type hints in SearchCommands (<a
href="https://redirect.github.com/redis/redis-py/issues/2817">#2817</a>)</li>
<li>Add sync modules (except search) tests to cluster CI (<a
href="https://redirect.github.com/redis/redis-py/issues/2850">#2850</a>)</li>
<li>Fix a duplicate word in <code>CONTRIBUTING.md</code> (<a
href="https://redirect.github.com/redis/redis-py/issues/2848">#2848</a>)</li>
<li>Fixing doc builds (<a
href="https://redirect.github.com/redis/redis-py/issues/2869">#2869</a>)</li>
<li>Change cluster docker to edge and enable debug command (<a
href="https://redirect.github.com/redis/redis-py/issues/2853">#2853</a>)</li>
</ul>
<h2>Contributors</h2>
<p>We'd like to thank all the contributors who worked on this
release!</p>
<p><a href="https://github.com/JoanFM"><code>@​JoanFM</code></a>, <a
href="https://github.com/Ovsyanka83"><code>@​Ovsyanka83</code></a>, <a
href="https://github.com/chayim"><code>@​chayim</code></a>, <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>, <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot],
<a href="https://github.com/dvora-h"><code>@​dvora-h</code></a>, <a
href="https://github.com/kristjanvalur"><code>@​kristjanvalur</code></a>,
<a href="https://github.com/kurtmckee"><code>@​kurtmckee</code></a>, <a
href="https://github.com/pall-j"><code>@​pall-j</code></a> and <a
href="https://github.com/shacharPash"><code>@​shacharPash</code></a></p>
<h2>5.0.0rc2</h2>
<h2>Changes</h2>
<h2>🧰 Maintenance</h2>
<ul>
<li>RESP3 response-callbacks cleanup (<a
href="https://redirect.github.com/redis/redis-py/issues/2841">#2841</a>)</li>
<li>Merge master to 5.0 (<a
href="https://redirect.github.com/redis/redis-py/issues/2827">#2827</a>)</li>
</ul>
<h2>5.0.0rc1</h2>
<h2>Changes</h2>
<h2>🔥 Breaking Changes</h2>
<ul>
<li>Change <code>SISMEMBER</code> return type to int by (<a
href="https://redirect.github.com/redis/redis-py/issues/2813">#2813</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/redis/redis-py/blob/master/CHANGES">redis's
changelog</a>.</em></p>
<blockquote>
<pre><code>* Fix [#2831](redis/redis-py#2831),
add auto_close_connection_pool=True arg to asyncio.Redis.from_url()
* Fix incorrect redis.asyncio.Cluster type hint for `retry_on_error`
* Fix dead weakref in sentinel connection causing ReferenceError
([#2767](redis/redis-py#2767))
* Fix [#2768](redis/redis-py#2768), Fix
KeyError: 'first-entry' in parse_xinfo_stream.
* Fix [#2749](redis/redis-py#2749), remove
unnecessary __del__ logic to close connections.
* Fix [#2754](redis/redis-py#2754), adding a
missing argument to SentinelManagedConnection
* Fix `xadd` command to accept non-negative `maxlen` including 0
* Revert [#2104](redis/redis-py#2104),
[#2673](redis/redis-py#2673), add
`disconnect_on_error` option to `read_response()` (issues
[#2506](redis/redis-py#2506),
[#2624](redis/redis-py#2624))
* Add `address_remap` parameter to `RedisCluster`
* Fix incorrect usage of once flag in async Sentinel
* asyncio: Fix memory leak caused by hiredis
([#2693](redis/redis-py#2693))
* Allow data to drain from async PythonParser when reading during a
disconnect()
* Use asyncio.timeout() instead of async_timeout.timeout() for python
&gt;= 3.11 ([#2602](redis/redis-py#2602))
* Add a Dependabot configuration to auto-update GitHub action versions.
* Add test and fix async HiredisParser when reading during a
disconnect() ([#2349](redis/redis-py#2349))
* Use hiredis-py pack_command if available.
* Support `.unlink()` in ClusterPipeline
* Simplify synchronous SocketBuffer state management
* Fix string cleanse in Redis Graph
* Make PythonParser resumable in case of error
([#2510](redis/redis-py#2510))
* Add `timeout=None` in `SentinelConnectionManager.read_response`
* Documentation fix: password protected socket connection
([#2374](redis/redis-py#2374))
* Allow `timeout=None` in `PubSub.get_message()` to wait forever
* add `nowait` flag to `asyncio.Connection.disconnect()`
* Update README.md links
* Fix timezone handling for datetime to unixtime conversions
* Fix start_id type for XAUTOCLAIM
* Remove verbose logging from cluster.py
* Add retry mechanism to async version of Connection
* Compare commands case-insensitively in the asyncio command parser
* Allow negative `retries` for `Retry` class to retry forever
* Add `items` parameter to `hset` signature
* Create codeql-analysis.yml
([#1988](redis/redis-py#1988)). Thanks @chayim
* Add limited support for Lua scripting with RedisCluster
* Implement `.lock()` method on RedisCluster
* Fix cursor returned by SCAN for RedisCluster &amp; change default
target to PRIMARIES
* Fix scan_iter for RedisCluster
* Remove verbose logging when initializing ClusterPubSub,
ClusterPipeline or RedisCluster
* Fix broken connection writer lock-up for asyncio
([#2065](redis/redis-py#2065))
* Fix auth bug when provided with no username
([#2086](redis/redis-py#2086))
* Fix missing ClusterPipeline._lock
([#2189](redis/redis-py#2189))
* Added dynaminc_startup_nodes configuration to RedisCluster
* Fix reusing the old nodes' connections when cluster topology refresh
is being done
* Fix RedisCluster to immediately raise AuthenticationError without a
retry
* ClusterPipeline Doesn't Handle ConnectionError for Dead Hosts
([#2225](redis/redis-py#2225))
* Remove compatibility code for old versions of Hiredis, drop Packaging
dependency
* The `deprecated` library is no longer a dependency
* Failover handling improvements for RedisCluster and Async RedisCluster
([#2377](redis/redis-py#2377))
* Fixed &quot;cannot pickle '_thread.lock' object&quot; bug
([#2354](redis/redis-py#2354),
[#2297](redis/redis-py#2297))
* Added CredentialsProvider class to support password rotation
</code></pre>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/redis/redis-py/commit/28cc65c18cc4fb37ef14497c963eb181dba8d25d"><code>28cc65c</code></a>
Updating all client licenses to clearly be MIT (<a
href="https://redirect.github.com/redis/redis-py/issues/2884">#2884</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/2f679261b7ef0e7372868cacd8ba8721406eb495"><code>2f67926</code></a>
Version 5.0.0 (<a
href="https://redirect.github.com/redis/redis-py/issues/2874">#2874</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/f121cf29e7d7fb5c85c5915ba5ce10a20826e8c0"><code>f121cf2</code></a>
Add support for <code>CLIENT SETINFO</code> (<a
href="https://redirect.github.com/redis/redis-py/issues/2857">#2857</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/d5c2d1d42ed9f653d450e6127cb6f673f43fb2d0"><code>d5c2d1d</code></a>
Adding support for triggered functions (TFUNCTION) (<a
href="https://redirect.github.com/redis/redis-py/issues/2861">#2861</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/b0abd555770bba42c57881b488b5fe5b188f088e"><code>b0abd55</code></a>
RESP 3 feature documentation (<a
href="https://redirect.github.com/redis/redis-py/issues/2872">#2872</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/a532f89adcd5b790e2811588a2d7c34a79b095d5"><code>a532f89</code></a>
Add py.typed in accordance with PEP-561 (<a
href="https://redirect.github.com/redis/redis-py/issues/2738">#2738</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/673617d2cbac265c6c8d43280d5e6898df4572b6"><code>673617d</code></a>
Bump actions/upload-artifact from 2 to 3 (<a
href="https://redirect.github.com/redis/redis-py/issues/2877">#2877</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/0ed807777cfab129904fd72fbada793f21ea0a9c"><code>0ed8077</code></a>
Bump pypa/gh-action-pip-audit from 1.0.0 to 1.0.8 (<a
href="https://redirect.github.com/redis/redis-py/issues/2879">#2879</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/38c7de617a482c9dd2d40699fbdd7ce44736cae9"><code>38c7de6</code></a>
Dependabot label change (<a
href="https://redirect.github.com/redis/redis-py/issues/2880">#2880</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/8370c4ac20835002fd1044e1742986072f19289c"><code>8370c4a</code></a>
Add a Dependabot config to auto-update GitHub action versions (<a
href="https://redirect.github.com/redis/redis-py/issues/2847">#2847</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/redis/redis-py/compare/v4.6.0...v5.0.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=redis&package-manager=pip&previous-version=4.6.0&new-version=5.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
oleobal pushed a commit to Substra/substra-backend that referenced this pull request Sep 11, 2023
Bumps [redis](https://github.com/redis/redis-py) from 4.5.4 to 5.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/redis/redis-py/releases">redis's
releases</a>.</em></p>
<blockquote>
<h2>5.0.0</h2>
<h2>What's new?</h2>
<h3>Triggers and Functions support</h3>
<p>Triggers and Functions allow you to execute server-side functions
triggered when key values are modified or created in Redis, a stream
entry arrival, or explicitly calling them. Simply put, you can replace
Lua scripts with easy-to-develop JavaScript or TypeScript code. Move
your business logic closer to the data to ensure a lower latency, and
forget about updating dependent key values manually in your code.
<a
href="https://redis.io/docs/interact/programmability/triggers-and-functions/quick_start/">Try
it for yourself with Quick start</a></p>
<h3>Full <a href="https://redis.com/blog/introducing-redis-7-2/">Redis
7.2</a> and <a
href="https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md">RESP3
support</a></h3>
<h3>Python 3.7 End-of-Life</h3>
<p><a href="https://devguide.python.org/versions/">Python 3.7 has
reached its end-of-life (EOL) as of June 2023</a>. This means that
starting from this date, Python 3.7 will no longer receive any updates,
including security patches, bug fixes, or improvements. If you continue
to use Python 3.7 post-EOL, you may expose your projects and systems to
potential security vulnerabilities. We ended its support in this version
and strongly recommend migrating to Python 3.10.</p>
<h2>🐛 Bug Fixes</h2>
<ul>
<li>Fix timeout retrying on pipeline execution (<a
href="https://redirect.github.com/redis/redis-py/issues/2812">#2812</a>)</li>
<li>Fix socket garbage collection (<a
href="https://redirect.github.com/redis/redis-py/issues/2859">#2859</a>)</li>
</ul>
<h2>🧰 Maintenance</h2>
<ul>
<li>Updating client license to clear, MIT (<a
href="https://redirect.github.com/redis/redis-py/issues/2884">#2884</a>)</li>
<li>Add py.typed in accordance with PEP-561 (<a
href="https://redirect.github.com/redis/redis-py/issues/2738">#2738</a>)</li>
<li>Dependabot label change (<a
href="https://redirect.github.com/redis/redis-py/issues/2880">#2880</a>)</li>
<li>Fix type hints in SearchCommands (<a
href="https://redirect.github.com/redis/redis-py/issues/2817">#2817</a>)</li>
<li>Add sync modules (except search) tests to cluster CI (<a
href="https://redirect.github.com/redis/redis-py/issues/2850">#2850</a>)</li>
<li>Fix a duplicate word in <code>CONTRIBUTING.md</code> (<a
href="https://redirect.github.com/redis/redis-py/issues/2848">#2848</a>)</li>
<li>Fixing doc builds (<a
href="https://redirect.github.com/redis/redis-py/issues/2869">#2869</a>)</li>
<li>Change cluster docker to edge and enable debug command (<a
href="https://redirect.github.com/redis/redis-py/issues/2853">#2853</a>)</li>
</ul>
<h2>Contributors</h2>
<p>We'd like to thank all the contributors who worked on this
release!</p>
<p><a href="https://github.com/JoanFM"><code>@​JoanFM</code></a>, <a
href="https://github.com/Ovsyanka83"><code>@​Ovsyanka83</code></a>, <a
href="https://github.com/chayim"><code>@​chayim</code></a>, <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>, <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot],
<a href="https://github.com/dvora-h"><code>@​dvora-h</code></a>, <a
href="https://github.com/kristjanvalur"><code>@​kristjanvalur</code></a>,
<a href="https://github.com/kurtmckee"><code>@​kurtmckee</code></a>, <a
href="https://github.com/pall-j"><code>@​pall-j</code></a> and <a
href="https://github.com/shacharPash"><code>@​shacharPash</code></a></p>
<h2>5.0.0rc2</h2>
<h2>Changes</h2>
<h2>🧰 Maintenance</h2>
<ul>
<li>RESP3 response-callbacks cleanup (<a
href="https://redirect.github.com/redis/redis-py/issues/2841">#2841</a>)</li>
<li>Merge master to 5.0 (<a
href="https://redirect.github.com/redis/redis-py/issues/2827">#2827</a>)</li>
</ul>
<h2>5.0.0rc1</h2>
<h2>Changes</h2>
<h2>🔥 Breaking Changes</h2>
<ul>
<li>Change <code>SISMEMBER</code> return type to int by (<a
href="https://redirect.github.com/redis/redis-py/issues/2813">#2813</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/redis/redis-py/blob/master/CHANGES">redis's
changelog</a>.</em></p>
<blockquote>
<pre><code>* Fix [#2831](redis/redis-py#2831),
add auto_close_connection_pool=True arg to asyncio.Redis.from_url()
* Fix incorrect redis.asyncio.Cluster type hint for `retry_on_error`
* Fix dead weakref in sentinel connection causing ReferenceError
([#2767](redis/redis-py#2767))
* Fix [#2768](redis/redis-py#2768), Fix
KeyError: 'first-entry' in parse_xinfo_stream.
* Fix [#2749](redis/redis-py#2749), remove
unnecessary __del__ logic to close connections.
* Fix [#2754](redis/redis-py#2754), adding a
missing argument to SentinelManagedConnection
* Fix `xadd` command to accept non-negative `maxlen` including 0
* Revert [#2104](redis/redis-py#2104),
[#2673](redis/redis-py#2673), add
`disconnect_on_error` option to `read_response()` (issues
[#2506](redis/redis-py#2506),
[#2624](redis/redis-py#2624))
* Add `address_remap` parameter to `RedisCluster`
* Fix incorrect usage of once flag in async Sentinel
* asyncio: Fix memory leak caused by hiredis
([#2693](redis/redis-py#2693))
* Allow data to drain from async PythonParser when reading during a
disconnect()
* Use asyncio.timeout() instead of async_timeout.timeout() for python
&gt;= 3.11 ([#2602](redis/redis-py#2602))
* Add a Dependabot configuration to auto-update GitHub action versions.
* Add test and fix async HiredisParser when reading during a
disconnect() ([#2349](redis/redis-py#2349))
* Use hiredis-py pack_command if available.
* Support `.unlink()` in ClusterPipeline
* Simplify synchronous SocketBuffer state management
* Fix string cleanse in Redis Graph
* Make PythonParser resumable in case of error
([#2510](redis/redis-py#2510))
* Add `timeout=None` in `SentinelConnectionManager.read_response`
* Documentation fix: password protected socket connection
([#2374](redis/redis-py#2374))
* Allow `timeout=None` in `PubSub.get_message()` to wait forever
* add `nowait` flag to `asyncio.Connection.disconnect()`
* Update README.md links
* Fix timezone handling for datetime to unixtime conversions
* Fix start_id type for XAUTOCLAIM
* Remove verbose logging from cluster.py
* Add retry mechanism to async version of Connection
* Compare commands case-insensitively in the asyncio command parser
* Allow negative `retries` for `Retry` class to retry forever
* Add `items` parameter to `hset` signature
* Create codeql-analysis.yml
([#1988](redis/redis-py#1988)). Thanks @chayim
* Add limited support for Lua scripting with RedisCluster
* Implement `.lock()` method on RedisCluster
* Fix cursor returned by SCAN for RedisCluster &amp; change default
target to PRIMARIES
* Fix scan_iter for RedisCluster
* Remove verbose logging when initializing ClusterPubSub,
ClusterPipeline or RedisCluster
* Fix broken connection writer lock-up for asyncio
([#2065](redis/redis-py#2065))
* Fix auth bug when provided with no username
([#2086](redis/redis-py#2086))
* Fix missing ClusterPipeline._lock
([#2189](redis/redis-py#2189))
* Added dynaminc_startup_nodes configuration to RedisCluster
* Fix reusing the old nodes' connections when cluster topology refresh
is being done
* Fix RedisCluster to immediately raise AuthenticationError without a
retry
* ClusterPipeline Doesn't Handle ConnectionError for Dead Hosts
([#2225](redis/redis-py#2225))
* Remove compatibility code for old versions of Hiredis, drop Packaging
dependency
* The `deprecated` library is no longer a dependency
* Failover handling improvements for RedisCluster and Async RedisCluster
([#2377](redis/redis-py#2377))
* Fixed &quot;cannot pickle '_thread.lock' object&quot; bug
([#2354](redis/redis-py#2354),
[#2297](redis/redis-py#2297))
* Added CredentialsProvider class to support password rotation
</code></pre>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/redis/redis-py/commit/28cc65c18cc4fb37ef14497c963eb181dba8d25d"><code>28cc65c</code></a>
Updating all client licenses to clearly be MIT (<a
href="https://redirect.github.com/redis/redis-py/issues/2884">#2884</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/2f679261b7ef0e7372868cacd8ba8721406eb495"><code>2f67926</code></a>
Version 5.0.0 (<a
href="https://redirect.github.com/redis/redis-py/issues/2874">#2874</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/f121cf29e7d7fb5c85c5915ba5ce10a20826e8c0"><code>f121cf2</code></a>
Add support for <code>CLIENT SETINFO</code> (<a
href="https://redirect.github.com/redis/redis-py/issues/2857">#2857</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/d5c2d1d42ed9f653d450e6127cb6f673f43fb2d0"><code>d5c2d1d</code></a>
Adding support for triggered functions (TFUNCTION) (<a
href="https://redirect.github.com/redis/redis-py/issues/2861">#2861</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/b0abd555770bba42c57881b488b5fe5b188f088e"><code>b0abd55</code></a>
RESP 3 feature documentation (<a
href="https://redirect.github.com/redis/redis-py/issues/2872">#2872</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/a532f89adcd5b790e2811588a2d7c34a79b095d5"><code>a532f89</code></a>
Add py.typed in accordance with PEP-561 (<a
href="https://redirect.github.com/redis/redis-py/issues/2738">#2738</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/673617d2cbac265c6c8d43280d5e6898df4572b6"><code>673617d</code></a>
Bump actions/upload-artifact from 2 to 3 (<a
href="https://redirect.github.com/redis/redis-py/issues/2877">#2877</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/0ed807777cfab129904fd72fbada793f21ea0a9c"><code>0ed8077</code></a>
Bump pypa/gh-action-pip-audit from 1.0.0 to 1.0.8 (<a
href="https://redirect.github.com/redis/redis-py/issues/2879">#2879</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/38c7de617a482c9dd2d40699fbdd7ce44736cae9"><code>38c7de6</code></a>
Dependabot label change (<a
href="https://redirect.github.com/redis/redis-py/issues/2880">#2880</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/8370c4ac20835002fd1044e1742986072f19289c"><code>8370c4a</code></a>
Add a Dependabot config to auto-update GitHub action versions (<a
href="https://redirect.github.com/redis/redis-py/issues/2847">#2847</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/redis/redis-py/compare/v4.5.4...v5.0.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=redis&package-manager=pip&previous-version=4.5.4&new-version=5.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
oleobal pushed a commit to Substra/substra-backend that referenced this pull request Sep 11, 2023
Bumps [redis](https://github.com/redis/redis-py) from 4.6.0 to 5.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/redis/redis-py/releases">redis's
releases</a>.</em></p>
<blockquote>
<h2>5.0.0</h2>
<h2>What's new?</h2>
<h3>Triggers and Functions support</h3>
<p>Triggers and Functions allow you to execute server-side functions
triggered when key values are modified or created in Redis, a stream
entry arrival, or explicitly calling them. Simply put, you can replace
Lua scripts with easy-to-develop JavaScript or TypeScript code. Move
your business logic closer to the data to ensure a lower latency, and
forget about updating dependent key values manually in your code.
<a
href="https://redis.io/docs/interact/programmability/triggers-and-functions/quick_start/">Try
it for yourself with Quick start</a></p>
<h3>Full <a href="https://redis.com/blog/introducing-redis-7-2/">Redis
7.2</a> and <a
href="https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md">RESP3
support</a></h3>
<h3>Python 3.7 End-of-Life</h3>
<p><a href="https://devguide.python.org/versions/">Python 3.7 has
reached its end-of-life (EOL) as of June 2023</a>. This means that
starting from this date, Python 3.7 will no longer receive any updates,
including security patches, bug fixes, or improvements. If you continue
to use Python 3.7 post-EOL, you may expose your projects and systems to
potential security vulnerabilities. We ended its support in this version
and strongly recommend migrating to Python 3.10.</p>
<h2>🐛 Bug Fixes</h2>
<ul>
<li>Fix timeout retrying on pipeline execution (<a
href="https://redirect.github.com/redis/redis-py/issues/2812">#2812</a>)</li>
<li>Fix socket garbage collection (<a
href="https://redirect.github.com/redis/redis-py/issues/2859">#2859</a>)</li>
</ul>
<h2>🧰 Maintenance</h2>
<ul>
<li>Updating client license to clear, MIT (<a
href="https://redirect.github.com/redis/redis-py/issues/2884">#2884</a>)</li>
<li>Add py.typed in accordance with PEP-561 (<a
href="https://redirect.github.com/redis/redis-py/issues/2738">#2738</a>)</li>
<li>Dependabot label change (<a
href="https://redirect.github.com/redis/redis-py/issues/2880">#2880</a>)</li>
<li>Fix type hints in SearchCommands (<a
href="https://redirect.github.com/redis/redis-py/issues/2817">#2817</a>)</li>
<li>Add sync modules (except search) tests to cluster CI (<a
href="https://redirect.github.com/redis/redis-py/issues/2850">#2850</a>)</li>
<li>Fix a duplicate word in <code>CONTRIBUTING.md</code> (<a
href="https://redirect.github.com/redis/redis-py/issues/2848">#2848</a>)</li>
<li>Fixing doc builds (<a
href="https://redirect.github.com/redis/redis-py/issues/2869">#2869</a>)</li>
<li>Change cluster docker to edge and enable debug command (<a
href="https://redirect.github.com/redis/redis-py/issues/2853">#2853</a>)</li>
</ul>
<h2>Contributors</h2>
<p>We'd like to thank all the contributors who worked on this
release!</p>
<p><a href="https://github.com/JoanFM"><code>@​JoanFM</code></a>, <a
href="https://github.com/Ovsyanka83"><code>@​Ovsyanka83</code></a>, <a
href="https://github.com/chayim"><code>@​chayim</code></a>, <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>, <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot],
<a href="https://github.com/dvora-h"><code>@​dvora-h</code></a>, <a
href="https://github.com/kristjanvalur"><code>@​kristjanvalur</code></a>,
<a href="https://github.com/kurtmckee"><code>@​kurtmckee</code></a>, <a
href="https://github.com/pall-j"><code>@​pall-j</code></a> and <a
href="https://github.com/shacharPash"><code>@​shacharPash</code></a></p>
<h2>5.0.0rc2</h2>
<h2>Changes</h2>
<h2>🧰 Maintenance</h2>
<ul>
<li>RESP3 response-callbacks cleanup (<a
href="https://redirect.github.com/redis/redis-py/issues/2841">#2841</a>)</li>
<li>Merge master to 5.0 (<a
href="https://redirect.github.com/redis/redis-py/issues/2827">#2827</a>)</li>
</ul>
<h2>5.0.0rc1</h2>
<h2>Changes</h2>
<h2>🔥 Breaking Changes</h2>
<ul>
<li>Change <code>SISMEMBER</code> return type to int by (<a
href="https://redirect.github.com/redis/redis-py/issues/2813">#2813</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/redis/redis-py/blob/master/CHANGES">redis's
changelog</a>.</em></p>
<blockquote>
<pre><code>* Fix [#2831](redis/redis-py#2831),
add auto_close_connection_pool=True arg to asyncio.Redis.from_url()
* Fix incorrect redis.asyncio.Cluster type hint for `retry_on_error`
* Fix dead weakref in sentinel connection causing ReferenceError
([#2767](redis/redis-py#2767))
* Fix [#2768](redis/redis-py#2768), Fix
KeyError: 'first-entry' in parse_xinfo_stream.
* Fix [#2749](redis/redis-py#2749), remove
unnecessary __del__ logic to close connections.
* Fix [#2754](redis/redis-py#2754), adding a
missing argument to SentinelManagedConnection
* Fix `xadd` command to accept non-negative `maxlen` including 0
* Revert [#2104](redis/redis-py#2104),
[#2673](redis/redis-py#2673), add
`disconnect_on_error` option to `read_response()` (issues
[#2506](redis/redis-py#2506),
[#2624](redis/redis-py#2624))
* Add `address_remap` parameter to `RedisCluster`
* Fix incorrect usage of once flag in async Sentinel
* asyncio: Fix memory leak caused by hiredis
([#2693](redis/redis-py#2693))
* Allow data to drain from async PythonParser when reading during a
disconnect()
* Use asyncio.timeout() instead of async_timeout.timeout() for python
&gt;= 3.11 ([#2602](redis/redis-py#2602))
* Add a Dependabot configuration to auto-update GitHub action versions.
* Add test and fix async HiredisParser when reading during a
disconnect() ([#2349](redis/redis-py#2349))
* Use hiredis-py pack_command if available.
* Support `.unlink()` in ClusterPipeline
* Simplify synchronous SocketBuffer state management
* Fix string cleanse in Redis Graph
* Make PythonParser resumable in case of error
([#2510](redis/redis-py#2510))
* Add `timeout=None` in `SentinelConnectionManager.read_response`
* Documentation fix: password protected socket connection
([#2374](redis/redis-py#2374))
* Allow `timeout=None` in `PubSub.get_message()` to wait forever
* add `nowait` flag to `asyncio.Connection.disconnect()`
* Update README.md links
* Fix timezone handling for datetime to unixtime conversions
* Fix start_id type for XAUTOCLAIM
* Remove verbose logging from cluster.py
* Add retry mechanism to async version of Connection
* Compare commands case-insensitively in the asyncio command parser
* Allow negative `retries` for `Retry` class to retry forever
* Add `items` parameter to `hset` signature
* Create codeql-analysis.yml
([#1988](redis/redis-py#1988)). Thanks @chayim
* Add limited support for Lua scripting with RedisCluster
* Implement `.lock()` method on RedisCluster
* Fix cursor returned by SCAN for RedisCluster &amp; change default
target to PRIMARIES
* Fix scan_iter for RedisCluster
* Remove verbose logging when initializing ClusterPubSub,
ClusterPipeline or RedisCluster
* Fix broken connection writer lock-up for asyncio
([#2065](redis/redis-py#2065))
* Fix auth bug when provided with no username
([#2086](redis/redis-py#2086))
* Fix missing ClusterPipeline._lock
([#2189](redis/redis-py#2189))
* Added dynaminc_startup_nodes configuration to RedisCluster
* Fix reusing the old nodes' connections when cluster topology refresh
is being done
* Fix RedisCluster to immediately raise AuthenticationError without a
retry
* ClusterPipeline Doesn't Handle ConnectionError for Dead Hosts
([#2225](redis/redis-py#2225))
* Remove compatibility code for old versions of Hiredis, drop Packaging
dependency
* The `deprecated` library is no longer a dependency
* Failover handling improvements for RedisCluster and Async RedisCluster
([#2377](redis/redis-py#2377))
* Fixed &quot;cannot pickle '_thread.lock' object&quot; bug
([#2354](redis/redis-py#2354),
[#2297](redis/redis-py#2297))
* Added CredentialsProvider class to support password rotation
</code></pre>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/redis/redis-py/commit/28cc65c18cc4fb37ef14497c963eb181dba8d25d"><code>28cc65c</code></a>
Updating all client licenses to clearly be MIT (<a
href="https://redirect.github.com/redis/redis-py/issues/2884">#2884</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/2f679261b7ef0e7372868cacd8ba8721406eb495"><code>2f67926</code></a>
Version 5.0.0 (<a
href="https://redirect.github.com/redis/redis-py/issues/2874">#2874</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/f121cf29e7d7fb5c85c5915ba5ce10a20826e8c0"><code>f121cf2</code></a>
Add support for <code>CLIENT SETINFO</code> (<a
href="https://redirect.github.com/redis/redis-py/issues/2857">#2857</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/d5c2d1d42ed9f653d450e6127cb6f673f43fb2d0"><code>d5c2d1d</code></a>
Adding support for triggered functions (TFUNCTION) (<a
href="https://redirect.github.com/redis/redis-py/issues/2861">#2861</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/b0abd555770bba42c57881b488b5fe5b188f088e"><code>b0abd55</code></a>
RESP 3 feature documentation (<a
href="https://redirect.github.com/redis/redis-py/issues/2872">#2872</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/a532f89adcd5b790e2811588a2d7c34a79b095d5"><code>a532f89</code></a>
Add py.typed in accordance with PEP-561 (<a
href="https://redirect.github.com/redis/redis-py/issues/2738">#2738</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/673617d2cbac265c6c8d43280d5e6898df4572b6"><code>673617d</code></a>
Bump actions/upload-artifact from 2 to 3 (<a
href="https://redirect.github.com/redis/redis-py/issues/2877">#2877</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/0ed807777cfab129904fd72fbada793f21ea0a9c"><code>0ed8077</code></a>
Bump pypa/gh-action-pip-audit from 1.0.0 to 1.0.8 (<a
href="https://redirect.github.com/redis/redis-py/issues/2879">#2879</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/38c7de617a482c9dd2d40699fbdd7ce44736cae9"><code>38c7de6</code></a>
Dependabot label change (<a
href="https://redirect.github.com/redis/redis-py/issues/2880">#2880</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/8370c4ac20835002fd1044e1742986072f19289c"><code>8370c4a</code></a>
Add a Dependabot config to auto-update GitHub action versions (<a
href="https://redirect.github.com/redis/redis-py/issues/2847">#2847</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/redis/redis-py/compare/v4.6.0...v5.0.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=redis&package-manager=pip&previous-version=4.6.0&new-version=5.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Connection class disconnects on BaseException
7 participants