From 9ca683ba4fed9478fd52431220d2a57f99c7d02b Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Sat, 1 Nov 2025 18:06:22 +0100 Subject: [PATCH 1/4] fix: refactor typing imports and event loop handling Replaced usage of typing_extensions with standard typing imports for TypedDict, ParamSpec, Concatenate, and related types where supported. Updated asyncio event loop initialization in Client to avoid deprecation warnings on Python 3.11+. Removed unused PY_310 constant and related conditional logic in utils.py. --- discord/_version.py | 3 ++- discord/client.py | 25 +++++++++++++++++--- discord/commands/context.py | 5 ++-- discord/commands/core.py | 8 +++---- discord/commands/options.py | 1 + discord/ext/commands/context.py | 3 ++- discord/ext/commands/core.py | 3 ++- discord/types/activity.py | 4 +++- discord/types/appinfo.py | 4 +++- discord/types/application_role_connection.py | 4 +++- discord/types/audit_log.py | 4 +++- discord/types/automod.py | 4 +++- discord/types/channel.py | 4 +++- discord/types/collectibles.py | 1 + discord/types/components.py | 4 +++- discord/types/embed.py | 4 +++- discord/types/guild.py | 4 +++- discord/types/integration.py | 4 +++- discord/types/interactions.py | 4 +++- discord/types/invite.py | 4 +++- discord/types/message.py | 4 +++- discord/types/monetization.py | 4 +++- discord/types/raw_models.py | 4 +++- discord/types/role.py | 4 +++- discord/types/soundboard.py | 4 +++- discord/types/sticker.py | 4 +++- discord/types/team.py | 1 + discord/types/template.py | 1 + discord/types/threads.py | 4 +++- discord/types/voice.py | 4 +++- discord/types/webhook.py | 4 +++- discord/types/widget.py | 4 +++- discord/utils.py | 8 ++----- 33 files changed, 105 insertions(+), 42 deletions(-) diff --git a/discord/_version.py b/discord/_version.py index ba68799dfe..88bcefd2dd 100644 --- a/discord/_version.py +++ b/discord/_version.py @@ -30,7 +30,7 @@ import warnings from importlib.metadata import PackageNotFoundError, version -from typing_extensions import TypedDict +from typing import TypedDict __all__ = ("__version__", "VersionInfo", "version_info") @@ -155,3 +155,4 @@ def date(self) -> datetime.date | None: commit=raw_info["commit"], date=date_info, ) + diff --git a/discord/client.py b/discord/client.py index f339cbfe92..3672e3996a 100644 --- a/discord/client.py +++ b/discord/client.py @@ -246,9 +246,28 @@ 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 - ) + # Prefer an explicitly provided loop. If none is provided, try to use + # a running loop (when constructed inside async code) and otherwise + # fall back to the event loop policy's get_event_loop implementation + # to avoid the deprecation warning for asyncio.get_event_loop(). + if loop is not None: + self.loop: asyncio.AbstractEventLoop = loop + else: + try: + self.loop = asyncio.get_running_loop() + except RuntimeError: + # No running loop in this thread; explicitly create a new + # event loop and set it as the current event loop for this + # thread. This mirrors the previous behavior of + # asyncio.get_event_loop() (which would create and set a loop) + # but avoids emitting the deprecation warning on Python >=3.11. + self.loop = asyncio.new_event_loop() + try: + asyncio.set_event_loop(self.loop) + except Exception: + # If for some reason setting the loop fails, continue + # using the locally created loop without setting it. + pass self._listeners: dict[str, list[tuple[asyncio.Future, Callable[..., bool]]]] = ( {} ) diff --git a/discord/commands/context.py b/discord/commands/context.py index 73a6b39a45..c55f736b40 100644 --- a/discord/commands/context.py +++ b/discord/commands/context.py @@ -32,9 +32,7 @@ from discord.webhook.async_ import Webhook if TYPE_CHECKING: - from typing import Awaitable, Callable - - from typing_extensions import ParamSpec + from typing import Awaitable, Callable, ParamSpec import discord @@ -439,3 +437,4 @@ def command(self) -> ApplicationCommand | None: @command.setter def command(self, value: ApplicationCommand | None) -> None: self.interaction.command = value + diff --git a/discord/commands/core.py b/discord/commands/core.py index a184a6fcae..9f35418fad 100644 --- a/discord/commands/core.py +++ b/discord/commands/core.py @@ -72,10 +72,7 @@ from .context import ApplicationContext, AutocompleteContext from .options import Option, OptionChoice -if sys.version_info >= (3, 11): - from typing import Annotated, Literal, get_args, get_origin -else: - from typing_extensions import Annotated, Literal, get_args, get_origin +from typing import Annotated, Literal, get_args, get_origin __all__ = ( "_BaseCommand", @@ -93,7 +90,7 @@ ) if TYPE_CHECKING: - from typing_extensions import Concatenate, ParamSpec + from typing import Concatenate, ParamSpec from .. import Permissions from ..cog import Cog @@ -2159,3 +2156,4 @@ def validate_chat_input_description(description: Any, locale: str | None = None) if locale: error.args = (f"{error.args[0]} in locale {locale}",) raise error + diff --git a/discord/commands/options.py b/discord/commands/options.py index 1613630bc0..801d63f6c8 100644 --- a/discord/commands/options.py +++ b/discord/commands/options.py @@ -554,3 +554,4 @@ def decorator(func): return func return decorator + diff --git a/discord/ext/commands/context.py b/discord/ext/commands/context.py index afd023d351..015085e071 100644 --- a/discord/ext/commands/context.py +++ b/discord/ext/commands/context.py @@ -34,7 +34,7 @@ from discord.message import Message if TYPE_CHECKING: - from typing_extensions import ParamSpec + from typing import ParamSpec from discord.abc import MessageableChannel from discord.guild import Guild @@ -409,3 +409,4 @@ async def forward_to( self, channel: discord.abc.Messageable, **kwargs: Any ) -> Message: return await self.message.forward_to(channel, **kwargs) + diff --git a/discord/ext/commands/core.py b/discord/ext/commands/core.py index 1a0d8a09a2..439338f053 100644 --- a/discord/ext/commands/core.py +++ b/discord/ext/commands/core.py @@ -67,7 +67,7 @@ from .errors import * if TYPE_CHECKING: - from typing_extensions import Concatenate, ParamSpec, TypeGuard + from typing import Concatenate, ParamSpec, TypeGuard from discord.message import Message @@ -2501,3 +2501,4 @@ def decorator(func: Command | CoroFunc) -> Command | CoroFunc: return func return decorator # type: ignore + diff --git a/discord/types/activity.py b/discord/types/activity.py index c19e9b18c1..27d50de152 100644 --- a/discord/types/activity.py +++ b/discord/types/activity.py @@ -27,7 +27,8 @@ from typing import Literal -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from .snowflake import Snowflake from .user import PartialUser @@ -109,3 +110,4 @@ class Activity(_BaseActivity, total=False): session_id: str | None instance: bool buttons: list[str] + diff --git a/discord/types/appinfo.py b/discord/types/appinfo.py index c22f665745..e32b289989 100644 --- a/discord/types/appinfo.py +++ b/discord/types/appinfo.py @@ -25,7 +25,8 @@ from __future__ import annotations -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from .snowflake import Snowflake from .team import Team @@ -65,3 +66,4 @@ class PartialAppInfo(BaseAppInfo): class AppInstallParams(TypedDict): scopes: list[str] permissions: str + diff --git a/discord/types/application_role_connection.py b/discord/types/application_role_connection.py index cf797b8efa..b7987e1c27 100644 --- a/discord/types/application_role_connection.py +++ b/discord/types/application_role_connection.py @@ -26,7 +26,8 @@ from typing import Literal -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired ApplicationRoleConnectionMetadataType = Literal[1, 2, 3, 4, 5, 6, 7, 8] @@ -38,3 +39,4 @@ class ApplicationRoleConnectionMetadata(TypedDict): name_localizations: NotRequired[dict[str, str]] description: str description_localizations: NotRequired[dict[str, str]] + diff --git a/discord/types/audit_log.py b/discord/types/audit_log.py index 0575457e7a..97ee3448ad 100644 --- a/discord/types/audit_log.py +++ b/discord/types/audit_log.py @@ -27,7 +27,8 @@ from typing import Literal, Union -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from .automod import AutoModRule from .channel import ChannelType, PermissionOverwrite, VideoQualityMode @@ -294,3 +295,4 @@ class AuditLog(TypedDict): threads: list[Thread] scheduled_events: list[ScheduledEvent] auto_moderation_rules: list[AutoModRule] + diff --git a/discord/types/automod.py b/discord/types/automod.py index 0417e78497..21be835f19 100644 --- a/discord/types/automod.py +++ b/discord/types/automod.py @@ -24,7 +24,8 @@ from typing import Literal -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from .snowflake import Snowflake @@ -89,3 +90,4 @@ class EditAutoModRule(TypedDict, total=False): enabled: bool exempt_roles: list[Snowflake] exempt_channels: list[Snowflake] + diff --git a/discord/types/channel.py b/discord/types/channel.py index d4661cf8c4..7bcbce15af 100644 --- a/discord/types/channel.py +++ b/discord/types/channel.py @@ -27,7 +27,8 @@ from typing import Literal, Union -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from ..enums import SortOrder from ..flags import ChannelFlags @@ -194,3 +195,4 @@ class VoiceChannelEffectSendEvent(TypedDict): animation_id: NotRequired[int] sound_id: NotRequired[Snowflake | int] sound_volume: NotRequired[float] + diff --git a/discord/types/collectibles.py b/discord/types/collectibles.py index ae035b0ec9..aedbcfbf46 100644 --- a/discord/types/collectibles.py +++ b/discord/types/collectibles.py @@ -34,3 +34,4 @@ class Nameplate(TypedDict): asset: str label: str palette: str + diff --git a/discord/types/components.py b/discord/types/components.py index f78d3c78a1..11da647479 100644 --- a/discord/types/components.py +++ b/discord/types/components.py @@ -27,7 +27,8 @@ from typing import Literal, Union -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from .channel import ChannelType from .emoji import PartialEmoji @@ -187,3 +188,4 @@ class FileUploadComponent(BaseComponent): SeparatorComponent, SectionComponent, ] + diff --git a/discord/types/embed.py b/discord/types/embed.py index 7d39c1630d..65d315e873 100644 --- a/discord/types/embed.py +++ b/discord/types/embed.py @@ -27,7 +27,8 @@ from typing import Literal -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired class EmbedFooter(TypedDict): @@ -101,3 +102,4 @@ class Embed(TypedDict, total=False): provider: EmbedProvider author: EmbedAuthor fields: list[EmbedField] + diff --git a/discord/types/guild.py b/discord/types/guild.py index 3c71c8647e..b88a92d3c4 100644 --- a/discord/types/guild.py +++ b/discord/types/guild.py @@ -27,7 +27,8 @@ from typing import Literal -from typing_extensions import NotRequired, Required, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired, Required from .activity import PartialPresenceUpdate from .channel import GuildChannel @@ -210,3 +211,4 @@ class IncidentsData(TypedDict, total=False): class ModifyIncidents(TypedDict, total=False): invites_disabled_until: str | None dms_disabled_until: str | None + diff --git a/discord/types/integration.py b/discord/types/integration.py index 1a6c8b70f1..528f3ae366 100644 --- a/discord/types/integration.py +++ b/discord/types/integration.py @@ -27,7 +27,8 @@ from typing import Literal, Union -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from .snowflake import Snowflake from .user import User @@ -81,3 +82,4 @@ class BotIntegration(BaseIntegration): Integration = Union[BaseIntegration, StreamIntegration, BotIntegration] + diff --git a/discord/types/interactions.py b/discord/types/interactions.py index 3f45e35c19..b83834bb35 100644 --- a/discord/types/interactions.py +++ b/discord/types/interactions.py @@ -42,7 +42,8 @@ from .message import AllowedMentions, Message from ..interactions import InteractionChannel -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired ApplicationCommandType = Literal[1, 2, 3] @@ -294,3 +295,4 @@ class InteractionCallbackResource(TypedDict): # This is not fully typed as activities are out of scope activity_instance: NotRequired[dict] message: NotRequired[Message] + diff --git a/discord/types/invite.py b/discord/types/invite.py index 796d27ccb4..a685eed54e 100644 --- a/discord/types/invite.py +++ b/discord/types/invite.py @@ -27,7 +27,8 @@ from typing import Literal, Union -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from .appinfo import PartialAppInfo from .channel import PartialChannel @@ -92,3 +93,4 @@ class GatewayInviteDelete(TypedDict): GatewayInvite = Union[GatewayInviteCreate, GatewayInviteDelete] + diff --git a/discord/types/message.py b/discord/types/message.py index c6a48881c7..23b407d0be 100644 --- a/discord/types/message.py +++ b/discord/types/message.py @@ -41,7 +41,8 @@ if TYPE_CHECKING: from .interactions import InteractionMetadata, MessageInteraction -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired class ChannelMention(TypedDict): @@ -194,3 +195,4 @@ class AllowedMentions(TypedDict): roles: SnowflakeList users: SnowflakeList replied_user: bool + diff --git a/discord/types/monetization.py b/discord/types/monetization.py index 13ed22ccc3..62f23f2a00 100644 --- a/discord/types/monetization.py +++ b/discord/types/monetization.py @@ -27,7 +27,8 @@ from typing import Literal -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from .snowflake import Snowflake @@ -76,3 +77,4 @@ class Subscription(TypedDict): status: SubscriptionStatus canceled_at: str | None country: NotRequired[str] + diff --git a/discord/types/raw_models.py b/discord/types/raw_models.py index 1a7feee059..e65bee367c 100644 --- a/discord/types/raw_models.py +++ b/discord/types/raw_models.py @@ -25,7 +25,8 @@ from __future__ import annotations -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from .automod import AutoModAction, AutoModTriggerType from .emoji import PartialEmoji @@ -163,3 +164,4 @@ class MessagePollVoteEvent(TypedDict): channel_id: Snowflake message_id: Snowflake answer_id: int + diff --git a/discord/types/role.py b/discord/types/role.py index 09e718e173..131f51bc9c 100644 --- a/discord/types/role.py +++ b/discord/types/role.py @@ -25,7 +25,8 @@ from __future__ import annotations -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from .snowflake import Snowflake @@ -54,3 +55,4 @@ class RoleTags(TypedDict, total=False): bot_id: Snowflake integration_id: Snowflake premium_subscriber: None + diff --git a/discord/types/soundboard.py b/discord/types/soundboard.py index 9a4c19b0ed..97e2f7ddd0 100644 --- a/discord/types/soundboard.py +++ b/discord/types/soundboard.py @@ -24,7 +24,8 @@ from __future__ import annotations -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from discord.types.user import User @@ -40,3 +41,4 @@ class SoundboardSound(TypedDict): guild_id: NotRequired[Snowflake] user: NotRequired[User] available: bool + diff --git a/discord/types/sticker.py b/discord/types/sticker.py index 95945462e6..e46720918c 100644 --- a/discord/types/sticker.py +++ b/discord/types/sticker.py @@ -27,7 +27,8 @@ from typing import Literal, Union -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from .snowflake import Snowflake from .user import User @@ -89,3 +90,4 @@ class EditGuildSticker(TypedDict, total=False): class ListPremiumStickerPacks(TypedDict): sticker_packs: list[StickerPack] + diff --git a/discord/types/team.py b/discord/types/team.py index 3fe78aad86..4eee59e04c 100644 --- a/discord/types/team.py +++ b/discord/types/team.py @@ -44,3 +44,4 @@ class Team(TypedDict): owner_id: Snowflake members: list[TeamMember] icon: str | None + diff --git a/discord/types/template.py b/discord/types/template.py index 8561836ecc..af8e2f4142 100644 --- a/discord/types/template.py +++ b/discord/types/template.py @@ -49,3 +49,4 @@ class Template(TypedDict): source_guild_id: Snowflake serialized_source_guild: Guild is_dirty: bool | None + diff --git a/discord/types/threads.py b/discord/types/threads.py index 447027183b..acde56df98 100644 --- a/discord/types/threads.py +++ b/discord/types/threads.py @@ -27,7 +27,8 @@ from typing import Literal -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from ..flags import ChannelFlags from .snowflake import Snowflake @@ -74,3 +75,4 @@ class ThreadPaginationPayload(TypedDict): threads: list[Thread] members: list[ThreadMember] has_more: bool + diff --git a/discord/types/voice.py b/discord/types/voice.py index 68d99ccd48..d55e95fe79 100644 --- a/discord/types/voice.py +++ b/discord/types/voice.py @@ -27,7 +27,8 @@ from typing import Literal -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from .member import MemberWithUser from .snowflake import Snowflake @@ -90,3 +91,4 @@ class VoiceReady(TypedDict): port: int modes: list[SupportedModes] heartbeat_interval: int + diff --git a/discord/types/webhook.py b/discord/types/webhook.py index a312b30a41..cdbab9e01b 100644 --- a/discord/types/webhook.py +++ b/discord/types/webhook.py @@ -27,7 +27,8 @@ from typing import Literal -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from .channel import PartialChannel from .snowflake import Snowflake @@ -63,3 +64,4 @@ class Webhook(PartialWebhook): avatar: NotRequired[str | None] channel_id: NotRequired[Snowflake] application_id: NotRequired[Snowflake | None] + diff --git a/discord/types/widget.py b/discord/types/widget.py index d327fa58fb..0f7bff469d 100644 --- a/discord/types/widget.py +++ b/discord/types/widget.py @@ -25,7 +25,8 @@ from __future__ import annotations -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict +from typing_extensions import NotRequired from .activity import Activity from .snowflake import Snowflake @@ -62,3 +63,4 @@ class Widget(TypedDict): class WidgetSettings(TypedDict): enabled: bool channel_id: Snowflake | None + diff --git a/discord/utils.py b/discord/utils.py index 37b7c5ffdf..5d689cfb03 100644 --- a/discord/utils.py +++ b/discord/utils.py @@ -154,8 +154,7 @@ def __repr__(self) -> str: MISSING: Any = _MissingSentinel() if TYPE_CHECKING: - from typing_extensions import ParamSpec - + from typing import ParamSpec from .abc import Snowflake from .commands.context import AutocompleteContext from .commands.options import OptionChoice @@ -1308,7 +1307,6 @@ def as_chunks(iterator: _Iter[T], max_size: int) -> _Iter[list[T]]: return _chunk(iterator, max_size) -PY_310 = sys.version_info >= (3, 10) def flatten_literal_params(parameters: Iterable[Any]) -> tuple[Any, ...]: @@ -1352,7 +1350,7 @@ def evaluate_annotation( is_literal = False args = tp.__args__ if not hasattr(tp, "__origin__"): - if PY_310 and tp.__class__ is types.UnionType: # type: ignore + if tp.__class__ is types.UnionType: # type: ignore converted = Union[args] # type: ignore return evaluate_annotation(converted, globals, locals, cache) @@ -1364,8 +1362,6 @@ def evaluate_annotation( except ValueError: pass if tp.__origin__ is Literal: - if not PY_310: - args = flatten_literal_params(tp.__args__) implicit_str = False is_literal = True From 29f63581db428284720f1bc50371a2cd38017800 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 1 Nov 2025 17:07:48 +0000 Subject: [PATCH 2/4] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/_version.py | 2 -- discord/commands/context.py | 1 - discord/commands/core.py | 8 ++++---- discord/commands/options.py | 1 - discord/ext/commands/context.py | 1 - discord/ext/commands/core.py | 1 - discord/types/activity.py | 4 +--- discord/types/appinfo.py | 2 +- discord/types/application_role_connection.py | 4 +--- discord/types/audit_log.py | 4 +--- discord/types/automod.py | 4 +--- discord/types/channel.py | 4 +--- discord/types/collectibles.py | 1 - discord/types/components.py | 4 +--- discord/types/embed.py | 4 +--- discord/types/guild.py | 4 +--- discord/types/integration.py | 4 +--- discord/types/interactions.py | 2 +- discord/types/invite.py | 4 +--- discord/types/message.py | 2 +- discord/types/monetization.py | 4 +--- discord/types/raw_models.py | 2 +- discord/types/role.py | 2 +- discord/types/soundboard.py | 2 +- discord/types/sticker.py | 4 +--- discord/types/team.py | 1 - discord/types/template.py | 1 - discord/types/threads.py | 4 +--- discord/types/voice.py | 4 +--- discord/types/webhook.py | 4 +--- discord/types/widget.py | 2 +- discord/utils.py | 4 +--- 32 files changed, 27 insertions(+), 68 deletions(-) diff --git a/discord/_version.py b/discord/_version.py index 88bcefd2dd..666a20e33f 100644 --- a/discord/_version.py +++ b/discord/_version.py @@ -29,7 +29,6 @@ import re import warnings from importlib.metadata import PackageNotFoundError, version - from typing import TypedDict __all__ = ("__version__", "VersionInfo", "version_info") @@ -155,4 +154,3 @@ def date(self) -> datetime.date | None: commit=raw_info["commit"], date=date_info, ) - diff --git a/discord/commands/context.py b/discord/commands/context.py index c55f736b40..dc20469f2f 100644 --- a/discord/commands/context.py +++ b/discord/commands/context.py @@ -437,4 +437,3 @@ def command(self) -> ApplicationCommand | None: @command.setter def command(self, value: ApplicationCommand | None) -> None: self.interaction.command = value - diff --git a/discord/commands/core.py b/discord/commands/core.py index 9f35418fad..a330915be1 100644 --- a/discord/commands/core.py +++ b/discord/commands/core.py @@ -30,19 +30,22 @@ import functools import inspect import re -import sys import types from collections import OrderedDict from enum import Enum from typing import ( TYPE_CHECKING, + Annotated, Any, Callable, Coroutine, Generator, Generic, + Literal, TypeVar, Union, + get_args, + get_origin, ) from ..channel import PartialMessageable, _threaded_guild_channel_factory @@ -72,8 +75,6 @@ from .context import ApplicationContext, AutocompleteContext from .options import Option, OptionChoice -from typing import Annotated, Literal, get_args, get_origin - __all__ = ( "_BaseCommand", "ApplicationCommand", @@ -2156,4 +2157,3 @@ def validate_chat_input_description(description: Any, locale: str | None = None) if locale: error.args = (f"{error.args[0]} in locale {locale}",) raise error - diff --git a/discord/commands/options.py b/discord/commands/options.py index 801d63f6c8..1613630bc0 100644 --- a/discord/commands/options.py +++ b/discord/commands/options.py @@ -554,4 +554,3 @@ def decorator(func): return func return decorator - diff --git a/discord/ext/commands/context.py b/discord/ext/commands/context.py index 015085e071..51cbd8a9fc 100644 --- a/discord/ext/commands/context.py +++ b/discord/ext/commands/context.py @@ -409,4 +409,3 @@ async def forward_to( self, channel: discord.abc.Messageable, **kwargs: Any ) -> Message: return await self.message.forward_to(channel, **kwargs) - diff --git a/discord/ext/commands/core.py b/discord/ext/commands/core.py index 439338f053..e0c073b984 100644 --- a/discord/ext/commands/core.py +++ b/discord/ext/commands/core.py @@ -2501,4 +2501,3 @@ def decorator(func: Command | CoroFunc) -> Command | CoroFunc: return func return decorator # type: ignore - diff --git a/discord/types/activity.py b/discord/types/activity.py index 27d50de152..d36aae2c06 100644 --- a/discord/types/activity.py +++ b/discord/types/activity.py @@ -25,9 +25,8 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing import TypedDict from typing_extensions import NotRequired from .snowflake import Snowflake @@ -110,4 +109,3 @@ class Activity(_BaseActivity, total=False): session_id: str | None instance: bool buttons: list[str] - diff --git a/discord/types/appinfo.py b/discord/types/appinfo.py index e32b289989..24739fd639 100644 --- a/discord/types/appinfo.py +++ b/discord/types/appinfo.py @@ -26,6 +26,7 @@ from __future__ import annotations from typing import TypedDict + from typing_extensions import NotRequired from .snowflake import Snowflake @@ -66,4 +67,3 @@ class PartialAppInfo(BaseAppInfo): class AppInstallParams(TypedDict): scopes: list[str] permissions: str - diff --git a/discord/types/application_role_connection.py b/discord/types/application_role_connection.py index b7987e1c27..95439f9371 100644 --- a/discord/types/application_role_connection.py +++ b/discord/types/application_role_connection.py @@ -24,9 +24,8 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing import TypedDict from typing_extensions import NotRequired ApplicationRoleConnectionMetadataType = Literal[1, 2, 3, 4, 5, 6, 7, 8] @@ -39,4 +38,3 @@ class ApplicationRoleConnectionMetadata(TypedDict): name_localizations: NotRequired[dict[str, str]] description: str description_localizations: NotRequired[dict[str, str]] - diff --git a/discord/types/audit_log.py b/discord/types/audit_log.py index 97ee3448ad..777e6244c6 100644 --- a/discord/types/audit_log.py +++ b/discord/types/audit_log.py @@ -25,9 +25,8 @@ from __future__ import annotations -from typing import Literal, Union +from typing import Literal, TypedDict, Union -from typing import TypedDict from typing_extensions import NotRequired from .automod import AutoModRule @@ -295,4 +294,3 @@ class AuditLog(TypedDict): threads: list[Thread] scheduled_events: list[ScheduledEvent] auto_moderation_rules: list[AutoModRule] - diff --git a/discord/types/automod.py b/discord/types/automod.py index 21be835f19..6b0390a308 100644 --- a/discord/types/automod.py +++ b/discord/types/automod.py @@ -22,9 +22,8 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing import TypedDict from typing_extensions import NotRequired from .snowflake import Snowflake @@ -90,4 +89,3 @@ class EditAutoModRule(TypedDict, total=False): enabled: bool exempt_roles: list[Snowflake] exempt_channels: list[Snowflake] - diff --git a/discord/types/channel.py b/discord/types/channel.py index 7bcbce15af..fec01de125 100644 --- a/discord/types/channel.py +++ b/discord/types/channel.py @@ -25,9 +25,8 @@ from __future__ import annotations -from typing import Literal, Union +from typing import Literal, TypedDict, Union -from typing import TypedDict from typing_extensions import NotRequired from ..enums import SortOrder @@ -195,4 +194,3 @@ class VoiceChannelEffectSendEvent(TypedDict): animation_id: NotRequired[int] sound_id: NotRequired[Snowflake | int] sound_volume: NotRequired[float] - diff --git a/discord/types/collectibles.py b/discord/types/collectibles.py index aedbcfbf46..ae035b0ec9 100644 --- a/discord/types/collectibles.py +++ b/discord/types/collectibles.py @@ -34,4 +34,3 @@ class Nameplate(TypedDict): asset: str label: str palette: str - diff --git a/discord/types/components.py b/discord/types/components.py index 11da647479..bfc3fe46e5 100644 --- a/discord/types/components.py +++ b/discord/types/components.py @@ -25,9 +25,8 @@ from __future__ import annotations -from typing import Literal, Union +from typing import Literal, TypedDict, Union -from typing import TypedDict from typing_extensions import NotRequired from .channel import ChannelType @@ -188,4 +187,3 @@ class FileUploadComponent(BaseComponent): SeparatorComponent, SectionComponent, ] - diff --git a/discord/types/embed.py b/discord/types/embed.py index 65d315e873..cf8b0d3568 100644 --- a/discord/types/embed.py +++ b/discord/types/embed.py @@ -25,9 +25,8 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing import TypedDict from typing_extensions import NotRequired @@ -102,4 +101,3 @@ class Embed(TypedDict, total=False): provider: EmbedProvider author: EmbedAuthor fields: list[EmbedField] - diff --git a/discord/types/guild.py b/discord/types/guild.py index b88a92d3c4..fe82b48446 100644 --- a/discord/types/guild.py +++ b/discord/types/guild.py @@ -25,9 +25,8 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing import TypedDict from typing_extensions import NotRequired, Required from .activity import PartialPresenceUpdate @@ -211,4 +210,3 @@ class IncidentsData(TypedDict, total=False): class ModifyIncidents(TypedDict, total=False): invites_disabled_until: str | None dms_disabled_until: str | None - diff --git a/discord/types/integration.py b/discord/types/integration.py index 528f3ae366..9b909cd79b 100644 --- a/discord/types/integration.py +++ b/discord/types/integration.py @@ -25,9 +25,8 @@ from __future__ import annotations -from typing import Literal, Union +from typing import Literal, TypedDict, Union -from typing import TypedDict from typing_extensions import NotRequired from .snowflake import Snowflake @@ -82,4 +81,3 @@ class BotIntegration(BaseIntegration): Integration = Union[BaseIntegration, StreamIntegration, BotIntegration] - diff --git a/discord/types/interactions.py b/discord/types/interactions.py index b83834bb35..b0b52e133a 100644 --- a/discord/types/interactions.py +++ b/discord/types/interactions.py @@ -43,6 +43,7 @@ from ..interactions import InteractionChannel from typing import TypedDict + from typing_extensions import NotRequired ApplicationCommandType = Literal[1, 2, 3] @@ -295,4 +296,3 @@ class InteractionCallbackResource(TypedDict): # This is not fully typed as activities are out of scope activity_instance: NotRequired[dict] message: NotRequired[Message] - diff --git a/discord/types/invite.py b/discord/types/invite.py index a685eed54e..714bf39f8d 100644 --- a/discord/types/invite.py +++ b/discord/types/invite.py @@ -25,9 +25,8 @@ from __future__ import annotations -from typing import Literal, Union +from typing import Literal, TypedDict, Union -from typing import TypedDict from typing_extensions import NotRequired from .appinfo import PartialAppInfo @@ -93,4 +92,3 @@ class GatewayInviteDelete(TypedDict): GatewayInvite = Union[GatewayInviteCreate, GatewayInviteDelete] - diff --git a/discord/types/message.py b/discord/types/message.py index 23b407d0be..9ebf7d16ab 100644 --- a/discord/types/message.py +++ b/discord/types/message.py @@ -42,6 +42,7 @@ from .interactions import InteractionMetadata, MessageInteraction from typing import TypedDict + from typing_extensions import NotRequired @@ -195,4 +196,3 @@ class AllowedMentions(TypedDict): roles: SnowflakeList users: SnowflakeList replied_user: bool - diff --git a/discord/types/monetization.py b/discord/types/monetization.py index 62f23f2a00..e53a7d7749 100644 --- a/discord/types/monetization.py +++ b/discord/types/monetization.py @@ -25,9 +25,8 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing import TypedDict from typing_extensions import NotRequired from .snowflake import Snowflake @@ -77,4 +76,3 @@ class Subscription(TypedDict): status: SubscriptionStatus canceled_at: str | None country: NotRequired[str] - diff --git a/discord/types/raw_models.py b/discord/types/raw_models.py index e65bee367c..d87fcd0b05 100644 --- a/discord/types/raw_models.py +++ b/discord/types/raw_models.py @@ -26,6 +26,7 @@ from __future__ import annotations from typing import TypedDict + from typing_extensions import NotRequired from .automod import AutoModAction, AutoModTriggerType @@ -164,4 +165,3 @@ class MessagePollVoteEvent(TypedDict): channel_id: Snowflake message_id: Snowflake answer_id: int - diff --git a/discord/types/role.py b/discord/types/role.py index 131f51bc9c..7c4286fae8 100644 --- a/discord/types/role.py +++ b/discord/types/role.py @@ -26,6 +26,7 @@ from __future__ import annotations from typing import TypedDict + from typing_extensions import NotRequired from .snowflake import Snowflake @@ -55,4 +56,3 @@ class RoleTags(TypedDict, total=False): bot_id: Snowflake integration_id: Snowflake premium_subscriber: None - diff --git a/discord/types/soundboard.py b/discord/types/soundboard.py index 97e2f7ddd0..fbf858683a 100644 --- a/discord/types/soundboard.py +++ b/discord/types/soundboard.py @@ -25,6 +25,7 @@ from __future__ import annotations from typing import TypedDict + from typing_extensions import NotRequired from discord.types.user import User @@ -41,4 +42,3 @@ class SoundboardSound(TypedDict): guild_id: NotRequired[Snowflake] user: NotRequired[User] available: bool - diff --git a/discord/types/sticker.py b/discord/types/sticker.py index e46720918c..591ee03053 100644 --- a/discord/types/sticker.py +++ b/discord/types/sticker.py @@ -25,9 +25,8 @@ from __future__ import annotations -from typing import Literal, Union +from typing import Literal, TypedDict, Union -from typing import TypedDict from typing_extensions import NotRequired from .snowflake import Snowflake @@ -90,4 +89,3 @@ class EditGuildSticker(TypedDict, total=False): class ListPremiumStickerPacks(TypedDict): sticker_packs: list[StickerPack] - diff --git a/discord/types/team.py b/discord/types/team.py index 4eee59e04c..3fe78aad86 100644 --- a/discord/types/team.py +++ b/discord/types/team.py @@ -44,4 +44,3 @@ class Team(TypedDict): owner_id: Snowflake members: list[TeamMember] icon: str | None - diff --git a/discord/types/template.py b/discord/types/template.py index af8e2f4142..8561836ecc 100644 --- a/discord/types/template.py +++ b/discord/types/template.py @@ -49,4 +49,3 @@ class Template(TypedDict): source_guild_id: Snowflake serialized_source_guild: Guild is_dirty: bool | None - diff --git a/discord/types/threads.py b/discord/types/threads.py index acde56df98..9b71f2fd1c 100644 --- a/discord/types/threads.py +++ b/discord/types/threads.py @@ -25,9 +25,8 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing import TypedDict from typing_extensions import NotRequired from ..flags import ChannelFlags @@ -75,4 +74,3 @@ class ThreadPaginationPayload(TypedDict): threads: list[Thread] members: list[ThreadMember] has_more: bool - diff --git a/discord/types/voice.py b/discord/types/voice.py index d55e95fe79..6424cdc1bb 100644 --- a/discord/types/voice.py +++ b/discord/types/voice.py @@ -25,9 +25,8 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing import TypedDict from typing_extensions import NotRequired from .member import MemberWithUser @@ -91,4 +90,3 @@ class VoiceReady(TypedDict): port: int modes: list[SupportedModes] heartbeat_interval: int - diff --git a/discord/types/webhook.py b/discord/types/webhook.py index cdbab9e01b..a857cd596c 100644 --- a/discord/types/webhook.py +++ b/discord/types/webhook.py @@ -25,9 +25,8 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing import TypedDict from typing_extensions import NotRequired from .channel import PartialChannel @@ -64,4 +63,3 @@ class Webhook(PartialWebhook): avatar: NotRequired[str | None] channel_id: NotRequired[Snowflake] application_id: NotRequired[Snowflake | None] - diff --git a/discord/types/widget.py b/discord/types/widget.py index 0f7bff469d..c4fb19b209 100644 --- a/discord/types/widget.py +++ b/discord/types/widget.py @@ -26,6 +26,7 @@ from __future__ import annotations from typing import TypedDict + from typing_extensions import NotRequired from .activity import Activity @@ -63,4 +64,3 @@ class Widget(TypedDict): class WidgetSettings(TypedDict): enabled: bool channel_id: Snowflake | None - diff --git a/discord/utils.py b/discord/utils.py index 5d689cfb03..1a3612659a 100644 --- a/discord/utils.py +++ b/discord/utils.py @@ -35,7 +35,6 @@ import json import logging import re -import sys import types import unicodedata import warnings @@ -155,6 +154,7 @@ def __repr__(self) -> str: if TYPE_CHECKING: from typing import ParamSpec + from .abc import Snowflake from .commands.context import AutocompleteContext from .commands.options import OptionChoice @@ -1307,8 +1307,6 @@ def as_chunks(iterator: _Iter[T], max_size: int) -> _Iter[list[T]]: return _chunk(iterator, max_size) - - def flatten_literal_params(parameters: Iterable[Any]) -> tuple[Any, ...]: params = [] literal_cls = type(Literal[0]) From 4be31e32a67f0101114569ec6b5132582f9d9d4d Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Sun, 2 Nov 2025 04:18:27 +0100 Subject: [PATCH 3/4] Update discord/client.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Lala Sabathil --- discord/client.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/discord/client.py b/discord/client.py index 3672e3996a..8133a86f96 100644 --- a/discord/client.py +++ b/discord/client.py @@ -264,10 +264,10 @@ def __init__( self.loop = asyncio.new_event_loop() try: asyncio.set_event_loop(self.loop) - except Exception: - # If for some reason setting the loop fails, continue + except Exception as exc: + # If for some reason setting the loop fails, log the exception and continue # using the locally created loop without setting it. - pass + logging.exception("Failed to set event loop: %s", exc) self._listeners: dict[str, list[tuple[asyncio.Future, Callable[..., bool]]]] = ( {} ) From e41a8b06c36b84b8b0351f2bd0bf9341cdbd62d0 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sun, 2 Nov 2025 04:26:47 +0100 Subject: [PATCH 4/4] Remove unused flatten_literal_params function (#2989) * Initial plan * Remove unused flatten_literal_params function Co-authored-by: Lulalaby <14029133+Lulalaby@users.noreply.github.com> --------- Co-Authored-By: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-Authored-By: Lulalaby <14029133+Lulalaby@users.noreply.github.com> --- discord/utils.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/discord/utils.py b/discord/utils.py index 1a3612659a..1c4561f224 100644 --- a/discord/utils.py +++ b/discord/utils.py @@ -1307,17 +1307,6 @@ def as_chunks(iterator: _Iter[T], max_size: int) -> _Iter[list[T]]: return _chunk(iterator, max_size) -def flatten_literal_params(parameters: Iterable[Any]) -> tuple[Any, ...]: - params = [] - literal_cls = type(Literal[0]) - for p in parameters: - if isinstance(p, literal_cls): - params.extend(p.__args__) - else: - params.append(p) - return tuple(params) - - def normalise_optional_params(parameters: Iterable[Any]) -> tuple[Any, ...]: none_cls = type(None) return tuple(p for p in parameters if p is not none_cls) + (none_cls,)