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

async fixes, remove __del__ and other things #2870

Merged
merged 8 commits into from
Sep 20, 2023

Conversation

kristjanvalur
Copy link
Contributor

@kristjanvalur kristjanvalur commented Aug 2, 2023

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

__del__ handlers are rarely needed. in asyncio they should not be used to perform IO cleanup, only emit resource usage
warnings. Code executing at __del__ time can be very fragile and is best avoided.
This PR fixes those warning emitters present, making them more "shutdown" safe.

  • It also removes a redundant __del__ handler from the async parser. There is no need to explicitly clear member variables.
  • It robustifies the callback system for PubSub, eliminating the need for a __del__ handler there.
  • It adds a few fixes to the unittests, when run locally.

@codecov-commenter
Copy link

codecov-commenter commented Aug 2, 2023

Codecov Report

Patch coverage: 77.50% and project coverage change: -13.66% ⚠️

Comparison is base (0acd0e7) 91.38% compared to head (43b3b83) 77.72%.
Report is 2 commits behind head on master.

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@             Coverage Diff             @@
##           master    #2870       +/-   ##
===========================================
- Coverage   91.38%   77.72%   -13.66%     
===========================================
  Files         126      126               
  Lines       32469    32474        +5     
===========================================
- Hits        29671    25240     -4431     
- Misses       2798     7234     +4436     
Files Changed Coverage Δ
redis/_parsers/base.py 90.83% <ø> (+1.23%) ⬆️
redis/cluster.py 18.38% <ø> (-74.43%) ⬇️
redis/asyncio/cluster.py 16.98% <25.00%> (-74.68%) ⬇️
redis/asyncio/connection.py 83.02% <80.00%> (-0.69%) ⬇️
redis/asyncio/client.py 92.30% <88.88%> (ø)
redis/client.py 91.64% <100.00%> (-0.31%) ⬇️
redis/connection.py 81.34% <100.00%> (-0.76%) ⬇️
...s/test_asyncio/test_sentinel_managed_connection.py 100.00% <100.00%> (ø)

... and 23 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@kristjanvalur kristjanvalur marked this pull request as draft August 2, 2023 15:28
@kristjanvalur kristjanvalur marked this pull request as ready for review August 25, 2023 13:25
@@ -958,17 +960,18 @@ def __eq__(self, obj: Any) -> bool:

_DEL_MESSAGE = "Unclosed ClusterNode object"

def __del__(self) -> None:
def __del__(
self, _warn: Any = warnings.warn, _grl: Any = asyncio.get_running_loop
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we split these lines to too (how did black pass this!). I found it.. very difficult to find where _grl was defined - so IMHO there's an ergonomic issue here. I fully accept that this is a nit + preference.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure. This is a pattern seen in the standard lib, the idea is to capture some methods into the function so that they are available even during module teardown. Pretty ugly.

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 can't split the args, black formats it straight back to one line :(

Copy link

Choose a reason for hiding this comment

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

you need to add comma after last arg to make black put them on separate lines. same for list, tuples etc. final comma splits line


def clear_connect_callbacks(self):
self._connect_callbacks = []
def deregister_connect_callback(self, callback):
Copy link
Contributor

Choose a reason for hiding this comment

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

Given the single use, I'd argue that this isn't a breaking change - but as it's meant to be internal to the library and not reused, let's fix that here. WDYT about an underscore prefix? Yes, I could argue that register_connect_callback might have the same need :(

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fair point

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, also for non-async to keep consistency.

reader = mock.AsyncMock()
writer = mock.AsyncMock()
writer.transport = mock.Mock()
reader = mock.Mock(spec=asyncio.StreamReader)
Copy link
Contributor

Choose a reason for hiding this comment

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

Teach we swami? Why is this pattern better than AsyncMock?

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 think we can keep the AsyncMock the key here is the "spec". When a spec is used, they become synonymous.
The use of 'spec' is essential when mocking classes with some methods sync, ad some async, since it will create the
correct mock methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, this went away when I rebased. But yes, when using "spec", to mock a class instance, it will create async/sync methods as appropritate. Here is the salient text:

Setting the spec of a Mock, MagicMock, or AsyncMock to a class with asynchronous and synchronous functions will automatically detect the synchronous functions and set them as MagicMock (if the parent mock is AsyncMock or MagicMock) or Mock (if the parent mock is Mock). All asynchronous functions will be AsyncMock.

self.task.cancel()
try:
await self.task
except asyncio.CancelledError:
pass
await self.server.wait_closed()
Copy link
Contributor

Choose a reason for hiding this comment

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

definitely a better idea

Copy link
Contributor

@chayim chayim left a comment

Choose a reason for hiding this comment

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

@kristjanvalur I have some questions in the PR - I think they weren't sent because it was draft? Mind checking -I see them

@kristjanvalur kristjanvalur force-pushed the kristjan/async-cleanup branch 3 times, most recently from 0357301 to 044aa9d Compare September 17, 2023 12:36
@dvora-h dvora-h added the maintenance Maintenance (CI, Releases, etc) label Sep 18, 2023
@dvora-h
Copy link
Collaborator

dvora-h commented Sep 18, 2023

@kristjanvalur Conflicts here too...

@dvora-h
Copy link
Collaborator

dvora-h commented Sep 19, 2023

@kristjanvalur The CI failed

@kristjanvalur
Copy link
Contributor Author

TestPubSubAutoReconnect , I guess this test could do with a review, I think there is a race condition there, causing sporadic failure.

@dvora-h
Copy link
Collaborator

dvora-h commented Sep 20, 2023

@kristjanvalur conflicts again...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
maintenance Maintenance (CI, Releases, etc)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants