-
-
Notifications
You must be signed in to change notification settings - Fork 478
refactor: Update Client.run
to have a better async I/O usage
#2645
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
base: master
Are you sure you want to change the base?
Conversation
Co-authored-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com> Signed-off-by: DA344 <108473820+DA-344@users.noreply.github.com>
Co-authored-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com> Signed-off-by: DA344 <108473820+DA-344@users.noreply.github.com>
Applied all the changes Dorukyum requested. Before merging, I would like some feedback on this discussion message |
Signed-off-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com>
…se Client._closed asyncio.Event object
Signed-off-by: DA344 <108473820+DA-344@users.noreply.github.com>
@DA-344 can u fix merge conflicts for the changelog? |
…into fix/client-run
Okay, it should be fixed now. 👍 |
i tested this pr on my prod bot for some hours and nothing to issue to signal |
Signed-off-by: DA344 <108473820+DA-344@users.noreply.github.com>
I've done some testing and it has been working as expected. Can this pr get any review more/merge ? |
This is required if we ever want py 3.14 support, see my pr about that |
Not just for 3.14 support, but to fix all asyncio related issues that can be presented in any version due to how the AbstractEventLoop is currently handled. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@@ -221,14 +226,12 @@ class Client: | |||
def __init__( | |||
self, | |||
*, | |||
loop: asyncio.AbstractEventLoop | None = None, | |||
loop: asyncio.AbstractEventLoop = MISSING, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like I've said this before, but I can't find my comment.
MISSING
has a very specific use case, None
should work fine here. (Haven't tested.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's MISSING because the loop is empty, and not null, empty because it is set later on the code, and will always have a value after start.
Also, this is more user friendly, instead of them having to do if bot.loop
checks or assert bot.loop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also not certain I get this. MISSING
is (as far as I'm concerned) used when there is a need to differentiate None
from another singleton. Here, that is not the case. But I might be missing something, tell me if that's the case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify my reasoning a lil bit more: MISSING
is used because a loop is not null in a async context, just not initialized. The idea of it is that it will always hold a valid event loop once the bot has started, but if not, then it is just not available.
And as I said, this also simplifies the user interface so they dont need to do if/assert X
checks, because it is safe to assume that after start a loop will always be available, and will never be None
.
But if using None
is preferred then yeah i could revert the change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that's your reasoning, I understand but I think None
's usage shouldn't be limited to representing literally nothing. As for the loop being always available and not None
or MISSING
, the only way of doing it in a typesafe manner afaik is something like:
class Foo:
def __init__(self):
self._bar_: Type | None = None
@property
def bar(self) -> Type:
if not self._bar:
raise ValueError("Foo.bar is not initialized")
return self._bar
@bar.setter
def bar(self, val: Type):
self._bar = val
Currently, with your change to MISSING
, Client.loop
's type hints are not representative of its actual value anymore, which shouldn't be the case.
If you want, you could implement the @property
solution to make the API easier for users, or just leave the | None
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could also pull a dpy and make it raise a special error when someone tries to access something from the loop instead of the literal attribute:
https://github.com/Rapptz/discord.py/blob/26855160f8a8f0dfade609cce6b1bc97f8b8fa14/discord/client.py#L138-L152
But that's a bit overkill imo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is indeed overkill imo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I will change it to be a property, that would be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DA-344 Could you also change it to None
? Thx
@@ -107,6 +107,8 @@ These changes are available on the `master` branch, but have not yet been releas | |||
([#2767])(https://github.com/Pycord-Development/pycord/pull/2767) | |||
- Fixed `Webhook.edit` not working with `attachments=[]`. | |||
([#2779])(https://github.com/Pycord-Development/pycord/pull/2779) | |||
- Fixed Async I/O errors that could be raised when using `Client.run`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idk if this is the best wording, the scope of this pr seems to be broader than just fixing errors. But idk this is also probably good enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm as long as that MISSING
comment is resolved in some way or another, nice pr
_cleanup_loop(self.loop) | ||
# asyncio.run automatically does the cleanup tasks, so if we use | ||
# it we don't need to clean up the tasks. | ||
if requires_cleanup: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't you just do if run == asyncio.run
?
Summary
This PR refactors the
Client.run
logic to fix problems involving asyncio due to how the library used the loop:Needs testing
Exception
Information
examples, ...).
Checklist
type: ignore
comments were used, a comment is also left explaining why.