From 3e77a7b29efbaf1a333a3b55f7462dc5a369d2bf Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Thu, 17 Mar 2022 20:25:10 +0900 Subject: [PATCH] Forbid wait_until_ready inside setup_hook --- discord/client.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/discord/client.py b/discord/client.py index 5126d9dd6..600655d89 100644 --- a/discord/client.py +++ b/discord/client.py @@ -29,6 +29,7 @@ import datetime import logging import sys import traceback +from contextvars import ContextVar from typing import ( Any, AsyncIterator, @@ -95,6 +96,8 @@ __all__ = ( Coro = TypeVar('Coro', bound=Callable[..., Coroutine[Any, Any, Any]]) +_inside_setup_hook: ContextVar[bool] = ContextVar('_inside_setup_hook', default=False) + _log = logging.getLogger(__name__) @@ -482,6 +485,11 @@ class Client: any events are dispatched, making it a better solution than doing such setup in the :func:`~discord.on_ready` event. + .. warning:: + + Calling :meth:`wait_until_ready` inside this coroutine raises + an exception to prevent a deadlock. + .. versionadded:: 2.0 """ pass @@ -518,7 +526,11 @@ class Client: data = await self.http.static_login(token.strip()) self._connection.user = ClientUser(state=self._connection, data=data) - await self.setup_hook() + try: + ctx_token = _inside_setup_hook.set(True) + await self.setup_hook() + finally: + _inside_setup_hook.reset(ctx_token) async def connect(self, *, reconnect: bool = True) -> None: """|coro| @@ -949,7 +961,14 @@ class Client: """|coro| Waits until the client's internal cache is all ready. + + Raises + ------- + ClientException + If this coroutine was called inside :meth:`setup_hook`. """ + if _inside_setup_hook.get(): + raise ClientException('wait_until_ready cannot be called inside setup_hook.') if self._ready is not MISSING: await self._ready.wait()