Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions discord/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,13 @@
from .threads import Thread
from .ui.view import BaseView
from .user import ClientUser, User
from .utils import _D, _FETCHABLE, MISSING, warn_if_voice_dependencies_missing
from .utils import (
_D,
_FETCHABLE,
MISSING,
_get_event_loop,
warn_if_voice_dependencies_missing,
)
from .webhook import Webhook
from .widget import Widget

Expand Down Expand Up @@ -147,7 +153,7 @@ class Client:
loop: Optional[:class:`asyncio.AbstractEventLoop`]
The :class:`asyncio.AbstractEventLoop` to use for asynchronous operations.
Defaults to ``None``, in which case the default event loop is used via
:func:`asyncio.get_event_loop()`.
:func:`asyncio.get_event_loop()` if it exists or one is created via :func:`asyncio.new_event_loop()`.
connector: Optional[:class:`aiohttp.BaseConnector`]
The connector to use for connection pooling.
proxy: Optional[:class:`str`]
Expand Down Expand Up @@ -245,7 +251,7 @@ def __init__(
# self.ws is set in the connect method
self.ws: DiscordWebSocket = None # type: ignore
self.loop: asyncio.AbstractEventLoop = (
asyncio.get_event_loop() if loop is None else loop
_get_event_loop() if loop is None else loop
)
self._listeners: dict[str, list[tuple[asyncio.Future, Callable[..., bool]]]] = (
{}
Expand Down
3 changes: 2 additions & 1 deletion discord/ext/commands/cooldowns.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

import discord.abc
from discord.enums import Enum
from discord.utils import _get_event_loop

from ...abc import PrivateChannel
from .errors import MaxConcurrencyReached
Expand Down Expand Up @@ -308,7 +309,7 @@ class _Semaphore:

def __init__(self, number: int) -> None:
self.value: int = number
self.loop: asyncio.AbstractEventLoop = asyncio.get_event_loop()
self.loop: asyncio.AbstractEventLoop = _get_event_loop()
self._waiters: Deque[asyncio.Future] = deque()

def __repr__(self) -> str:
Expand Down
8 changes: 4 additions & 4 deletions discord/ext/tasks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

import discord
from discord.backoff import ExponentialBackoff
from discord.utils import MISSING
from discord.utils import MISSING, _get_event_loop

__all__ = ("loop",)

Expand Down Expand Up @@ -384,7 +384,7 @@ def start(self, *args: Any, **kwargs: Any) -> asyncio.Task[None]:
args = (self._injected, *args)

if self.loop is MISSING:
self.loop = asyncio.get_event_loop()
self.loop = _get_event_loop()

self._task = self.loop.create_task(self._loop(*args, **kwargs))
return self._task
Expand Down Expand Up @@ -825,8 +825,8 @@ def loop(
using an exponential back-off algorithm similar to the
one used in :meth:`discord.Client.connect`.
loop: :class:`asyncio.AbstractEventLoop`
The loop to use to register the task, if not given
defaults to :func:`asyncio.get_event_loop`.
The loop to use to register the task, if not given the default event loop is used via
:func:`asyncio.get_event_loop()` if it exists or one is created via :func:`asyncio.new_event_loop()`.
overlap: Union[:class:`bool`, :class:`int`]
Controls whether overlapping executions of the task loop are allowed.
Set to False (default) to run iterations one at a time, True for unlimited overlap, or an int to cap the number of concurrent runs.
Expand Down
4 changes: 2 additions & 2 deletions discord/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
from .file import VoiceMessage
from .gateway import DiscordClientWebSocketResponse
from .soundboard import PartialSoundboardSound, SoundboardSound
from .utils import MISSING
from .utils import MISSING, _get_event_loop

_log = logging.getLogger(__name__)

Expand Down Expand Up @@ -192,7 +192,7 @@ def __init__(
unsync_clock: bool = True,
) -> None:
self.loop: asyncio.AbstractEventLoop = (
asyncio.get_event_loop() if loop is None else loop
_get_event_loop() if loop is None else loop
)
self.connector = connector
self.__session: aiohttp.ClientSession = MISSING # filled in static_login
Expand Down
4 changes: 2 additions & 2 deletions discord/ui/modal.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from typing import TYPE_CHECKING, Any, Iterator, TypeVar

from ..enums import ComponentType
from ..utils import find
from ..utils import _get_event_loop, find
from .core import ItemInterface
from .input_text import InputText
from .item import ModalItem
Expand Down Expand Up @@ -91,7 +91,7 @@ def __init__(
for item in children:
self.add_item(item)
self._title = title
self.loop = asyncio.get_event_loop()
self.loop = _get_event_loop()

def __repr__(self) -> str:
attrs = " ".join(
Expand Down
21 changes: 21 additions & 0 deletions discord/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1665,3 +1665,24 @@ def warn_if_voice_dependencies_missing() -> None:
deps,
"is" if len(missing) == 1 else "are",
)


def _get_event_loop() -> asyncio.AbstractEventLoop:
"""Get the current event loop, creating one if necessary.

If no event loop is running and none is set, a new event loop
is created and set as the current event loop.

Returns
-------
asyncio.AbstractEventLoop
The current event loop.
"""
if sys.version_info >= (3, 14):
try:
loop = asyncio.get_event_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
return loop
return asyncio.get_event_loop()
7 changes: 2 additions & 5 deletions examples/basic_voice.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,8 @@ def __init__(self, source: discord.AudioSource, *, data: dict, volume: float = 0
self.url = data.get("url")

@classmethod
async def from_url(cls, url, *, loop=None, stream=False):
loop = loop or asyncio.get_event_loop()
data = await loop.run_in_executor(
None, lambda: ytdl.extract_info(url, download=not stream)
)
async def from_url(cls, url, *, stream=False):
data = await asyncio.to_thread(ytdl.extract_info, url, download=not stream)

if "entries" in data:
# Takes the first item from a playlist
Expand Down
Loading