From 99babf9ad3eb4d3d50b2eea48be6840d712e9d13 Mon Sep 17 00:00:00 2001 From: Jakub Kuczys Date: Sun, 10 May 2026 21:46:57 +0200 Subject: [PATCH] Update uvloop to 0.22.1 (#6705) --- redbot/__init__.py | 14 -------------- redbot/__main__.py | 6 +++--- redbot/core/_cli.py | 34 +++++++++++++++++++++++++++++++++- redbot/setup.py | 8 ++++---- requirements/base.in | 2 +- requirements/base.txt | 2 +- tests/conftest.py | 6 ++---- 7 files changed, 44 insertions(+), 28 deletions(-) diff --git a/redbot/__init__.py b/redbot/__init__.py index 671c475b0..dce7178e2 100644 --- a/redbot/__init__.py +++ b/redbot/__init__.py @@ -289,19 +289,6 @@ class VersionInfo: return version("Red-DiscordBot") -def _update_event_loop_policy(): - if _sys.implementation.name == "cpython": - # Let's not force this dependency, uvloop is much faster on cpython - try: - import uvloop - except ImportError: - pass - else: - import asyncio - - asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) - - def _ensure_no_colorama(): # a hacky way to ensure that nothing initialises colorama # if we're not running with legacy Windows command line mode @@ -334,7 +321,6 @@ def _early_init(): # This function replaces logger so we preferably (though not necessarily) want that to happen # before importing anything that calls `logging.getLogger()`, i.e. `asyncio`. _update_logger_class() - _update_event_loop_policy() _ensure_no_colorama() diff --git a/redbot/__main__.py b/redbot/__main__.py index ce9628fb8..7fe90d7fa 100644 --- a/redbot/__main__.py +++ b/redbot/__main__.py @@ -25,7 +25,7 @@ import rich import redbot.logging from redbot import __version__ from redbot.core.bot import Red, ExitCodes, _NoOwnerSet -from redbot.core._cli import interactive_config, confirm, parse_cli_flags +from redbot.core._cli import interactive_config, confirm, parse_cli_flags, new_event_loop from redbot.setup import get_data_dir, get_name, save_config from redbot.core import data_manager, _drivers, _downloader from redbot.core._debuginfo import DebugInfo @@ -250,7 +250,7 @@ def early_exit_runner( """ This one exists to not log all the things like it's a full run of the bot. """ - loop = asyncio.new_event_loop() + loop = new_event_loop() asyncio.set_event_loop(loop) try: if not cli_flags.instance_name: @@ -460,7 +460,7 @@ def main(): early_exit_runner(cli_flags, edit_instance) return try: - loop = asyncio.new_event_loop() + loop = new_event_loop() asyncio.set_event_loop(loop) if cli_flags.no_instance: diff --git a/redbot/core/_cli.py b/redbot/core/_cli.py index ffbe6482a..312d3c999 100644 --- a/redbot/core/_cli.py +++ b/redbot/core/_cli.py @@ -3,13 +3,15 @@ import asyncio import logging import sys from enum import IntEnum -from typing import Optional +from typing import Any, Coroutine, Optional, TypeVar import discord from discord import __version__ as discord_version from redbot.core.utils._internal_utils import cli_level_to_log_level +_T = TypeVar("_T") + # This needs to be an int enum to be used # with sys.exit @@ -368,3 +370,33 @@ def parse_cli_flags(args): args.logging_level = cli_level_to_log_level(args.logging_level) return args + + +def asyncio_run(coro: Coroutine[Any, Any, _T]) -> _T: + if sys.version_info >= (3, 11): + with asyncio.Runner(loop_factory=new_event_loop) as runner: + return runner.run(coro) + + if sys.implementation.name == "cpython": + # Let's not force this dependency, uvloop is much faster on cpython + try: + import uvloop + except ImportError: + pass + else: + asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) + + return asyncio.run(coro) + + +def new_event_loop() -> asyncio.AbstractEventLoop: + if sys.implementation.name == "cpython": + # Let's not force this dependency, uvloop is much faster on cpython + try: + import uvloop + except ImportError: + pass + else: + return uvloop.new_event_loop() + + return asyncio.new_event_loop() diff --git a/redbot/setup.py b/redbot/setup.py index 9ee8e9443..6d7102542 100644 --- a/redbot/setup.py +++ b/redbot/setup.py @@ -23,7 +23,7 @@ from redbot.core.utils._internal_utils import ( ) from redbot.core import config, data_manager from redbot.core._config import migrate -from redbot.core._cli import ExitCodes +from redbot.core._cli import ExitCodes, asyncio_run from redbot.core.data_manager import appdir, config_dir, config_file from redbot.core._drivers import ( BackendType, @@ -512,7 +512,7 @@ def delete( remove_datapath: Optional[bool], ) -> None: """Removes an instance.""" - asyncio.run( + asyncio_run( remove_instance( instance, interactive, delete_data, _create_backup, drop_db, remove_datapath ) @@ -534,7 +534,7 @@ def convert(instance: str, backend: str) -> None: if current_backend == BackendType.MONGOV1: raise RuntimeError("Please see the 3.2 release notes for upgrading a bot using mongo.") else: - new_storage_details = asyncio.run(do_migration(current_backend, target)) + new_storage_details = asyncio_run(do_migration(current_backend, target)) if new_storage_details is not None: default_dirs["STORAGE_TYPE"] = target.value @@ -558,7 +558,7 @@ def convert(instance: str, backend: str) -> None: ) def backup(instance: str, destination_folder: Path) -> None: """Backup instance's data.""" - asyncio.run(create_backup(instance, destination_folder)) + asyncio_run(create_backup(instance, destination_folder)) def run_cli(): diff --git a/requirements/base.in b/requirements/base.in index fea323bad..4c26fb1c8 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -19,7 +19,7 @@ typing_extensions yarl distro; sys_platform == "linux" # https://github.com/MagicStack/uvloop/issues/702 -uvloop>=0.21.0,!=0.22.0,!=0.22.1; sys_platform != "win32" and platform_python_implementation == "CPython" +uvloop; sys_platform != "win32" and platform_python_implementation == "CPython" # Used by discord.py[speedup]. See Pull request #6587 for more info. Brotli diff --git a/requirements/base.txt b/requirements/base.txt index 59b0f2432..acdf5c16f 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -88,7 +88,7 @@ importlib-metadata==8.5.0; python_version != "3.10" and python_version != "3.11" # via markdown pytz==2026.1.post1; python_version == "3.8" # via babel -uvloop==0.21.0; (sys_platform != "win32" and platform_python_implementation == "CPython") and sys_platform != "win32" +uvloop==0.22.1; (sys_platform != "win32" and platform_python_implementation == "CPython") and sys_platform != "win32" # via -r base.in zipp==3.20.2; python_version != "3.10" and python_version != "3.11" # via importlib-metadata diff --git a/tests/conftest.py b/tests/conftest.py index cb5cb7c66..f1bfd34da 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,16 +3,14 @@ import os import pytest -from redbot import _update_event_loop_policy from redbot.core import _drivers, data_manager - -_update_event_loop_policy() +from redbot.core._cli import new_event_loop @pytest.fixture(scope="session") def event_loop(request): """Create an instance of the default event loop for entire session.""" - loop = asyncio.new_event_loop() + loop = new_event_loop() asyncio.set_event_loop(loop) yield loop asyncio.set_event_loop(None)