diff --git a/discord/_version.py b/discord/_version.py index ba68799dfe..666a20e33f 100644 --- a/discord/_version.py +++ b/discord/_version.py @@ -29,8 +29,7 @@ import re import warnings from importlib.metadata import PackageNotFoundError, version - -from typing_extensions import TypedDict +from typing import TypedDict __all__ = ("__version__", "VersionInfo", "version_info") diff --git a/discord/client.py b/discord/client.py index f339cbfe92..8133a86f96 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 as exc: + # If for some reason setting the loop fails, log the exception and continue + # using the locally created loop without setting it. + logging.exception("Failed to set event loop: %s", exc) self._listeners: dict[str, list[tuple[asyncio.Future, Callable[..., bool]]]] = ( {} ) diff --git a/discord/commands/context.py b/discord/commands/context.py index 73a6b39a45..dc20469f2f 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 diff --git a/discord/commands/core.py b/discord/commands/core.py index a184a6fcae..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,11 +75,6 @@ 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 - __all__ = ( "_BaseCommand", "ApplicationCommand", @@ -93,7 +91,7 @@ ) if TYPE_CHECKING: - from typing_extensions import Concatenate, ParamSpec + from typing import Concatenate, ParamSpec from .. import Permissions from ..cog import Cog diff --git a/discord/ext/commands/context.py b/discord/ext/commands/context.py index afd023d351..51cbd8a9fc 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 diff --git a/discord/ext/commands/core.py b/discord/ext/commands/core.py index 1a0d8a09a2..e0c073b984 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 diff --git a/discord/types/activity.py b/discord/types/activity.py index c19e9b18c1..d36aae2c06 100644 --- a/discord/types/activity.py +++ b/discord/types/activity.py @@ -25,9 +25,9 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing_extensions import NotRequired, TypedDict +from typing_extensions import NotRequired from .snowflake import Snowflake from .user import PartialUser diff --git a/discord/types/appinfo.py b/discord/types/appinfo.py index c22f665745..24739fd639 100644 --- a/discord/types/appinfo.py +++ b/discord/types/appinfo.py @@ -25,7 +25,9 @@ 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 diff --git a/discord/types/application_role_connection.py b/discord/types/application_role_connection.py index cf797b8efa..95439f9371 100644 --- a/discord/types/application_role_connection.py +++ b/discord/types/application_role_connection.py @@ -24,9 +24,9 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing_extensions import NotRequired, TypedDict +from typing_extensions import NotRequired ApplicationRoleConnectionMetadataType = Literal[1, 2, 3, 4, 5, 6, 7, 8] diff --git a/discord/types/audit_log.py b/discord/types/audit_log.py index 0575457e7a..777e6244c6 100644 --- a/discord/types/audit_log.py +++ b/discord/types/audit_log.py @@ -25,9 +25,9 @@ from __future__ import annotations -from typing import Literal, Union +from typing import Literal, TypedDict, Union -from typing_extensions import NotRequired, TypedDict +from typing_extensions import NotRequired from .automod import AutoModRule from .channel import ChannelType, PermissionOverwrite, VideoQualityMode diff --git a/discord/types/automod.py b/discord/types/automod.py index 0417e78497..6b0390a308 100644 --- a/discord/types/automod.py +++ b/discord/types/automod.py @@ -22,9 +22,9 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing_extensions import NotRequired, TypedDict +from typing_extensions import NotRequired from .snowflake import Snowflake diff --git a/discord/types/channel.py b/discord/types/channel.py index d4661cf8c4..fec01de125 100644 --- a/discord/types/channel.py +++ b/discord/types/channel.py @@ -25,9 +25,9 @@ from __future__ import annotations -from typing import Literal, Union +from typing import Literal, TypedDict, Union -from typing_extensions import NotRequired, TypedDict +from typing_extensions import NotRequired from ..enums import SortOrder from ..flags import ChannelFlags diff --git a/discord/types/components.py b/discord/types/components.py index f78d3c78a1..bfc3fe46e5 100644 --- a/discord/types/components.py +++ b/discord/types/components.py @@ -25,9 +25,9 @@ from __future__ import annotations -from typing import Literal, Union +from typing import Literal, TypedDict, Union -from typing_extensions import NotRequired, TypedDict +from typing_extensions import NotRequired from .channel import ChannelType from .emoji import PartialEmoji diff --git a/discord/types/embed.py b/discord/types/embed.py index 7d39c1630d..cf8b0d3568 100644 --- a/discord/types/embed.py +++ b/discord/types/embed.py @@ -25,9 +25,9 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing_extensions import NotRequired, TypedDict +from typing_extensions import NotRequired class EmbedFooter(TypedDict): diff --git a/discord/types/guild.py b/discord/types/guild.py index 3c71c8647e..fe82b48446 100644 --- a/discord/types/guild.py +++ b/discord/types/guild.py @@ -25,9 +25,9 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing_extensions import NotRequired, Required, TypedDict +from typing_extensions import NotRequired, Required from .activity import PartialPresenceUpdate from .channel import GuildChannel diff --git a/discord/types/integration.py b/discord/types/integration.py index 1a6c8b70f1..9b909cd79b 100644 --- a/discord/types/integration.py +++ b/discord/types/integration.py @@ -25,9 +25,9 @@ from __future__ import annotations -from typing import Literal, Union +from typing import Literal, TypedDict, Union -from typing_extensions import NotRequired, TypedDict +from typing_extensions import NotRequired from .snowflake import Snowflake from .user import User diff --git a/discord/types/interactions.py b/discord/types/interactions.py index 3f45e35c19..b0b52e133a 100644 --- a/discord/types/interactions.py +++ b/discord/types/interactions.py @@ -42,7 +42,9 @@ 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] diff --git a/discord/types/invite.py b/discord/types/invite.py index 796d27ccb4..714bf39f8d 100644 --- a/discord/types/invite.py +++ b/discord/types/invite.py @@ -25,9 +25,9 @@ from __future__ import annotations -from typing import Literal, Union +from typing import Literal, TypedDict, Union -from typing_extensions import NotRequired, TypedDict +from typing_extensions import NotRequired from .appinfo import PartialAppInfo from .channel import PartialChannel diff --git a/discord/types/message.py b/discord/types/message.py index c6a48881c7..9ebf7d16ab 100644 --- a/discord/types/message.py +++ b/discord/types/message.py @@ -41,7 +41,9 @@ 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): diff --git a/discord/types/monetization.py b/discord/types/monetization.py index 13ed22ccc3..e53a7d7749 100644 --- a/discord/types/monetization.py +++ b/discord/types/monetization.py @@ -25,9 +25,9 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing_extensions import NotRequired, TypedDict +from typing_extensions import NotRequired from .snowflake import Snowflake diff --git a/discord/types/raw_models.py b/discord/types/raw_models.py index 1a7feee059..d87fcd0b05 100644 --- a/discord/types/raw_models.py +++ b/discord/types/raw_models.py @@ -25,7 +25,9 @@ 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 diff --git a/discord/types/role.py b/discord/types/role.py index 09e718e173..7c4286fae8 100644 --- a/discord/types/role.py +++ b/discord/types/role.py @@ -25,7 +25,9 @@ from __future__ import annotations -from typing_extensions import NotRequired, TypedDict +from typing import TypedDict + +from typing_extensions import NotRequired from .snowflake import Snowflake diff --git a/discord/types/soundboard.py b/discord/types/soundboard.py index 9a4c19b0ed..fbf858683a 100644 --- a/discord/types/soundboard.py +++ b/discord/types/soundboard.py @@ -24,7 +24,9 @@ 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 diff --git a/discord/types/sticker.py b/discord/types/sticker.py index 95945462e6..591ee03053 100644 --- a/discord/types/sticker.py +++ b/discord/types/sticker.py @@ -25,9 +25,9 @@ from __future__ import annotations -from typing import Literal, Union +from typing import Literal, TypedDict, Union -from typing_extensions import NotRequired, TypedDict +from typing_extensions import NotRequired from .snowflake import Snowflake from .user import User diff --git a/discord/types/threads.py b/discord/types/threads.py index 447027183b..9b71f2fd1c 100644 --- a/discord/types/threads.py +++ b/discord/types/threads.py @@ -25,9 +25,9 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing_extensions import NotRequired, TypedDict +from typing_extensions import NotRequired from ..flags import ChannelFlags from .snowflake import Snowflake diff --git a/discord/types/voice.py b/discord/types/voice.py index 68d99ccd48..6424cdc1bb 100644 --- a/discord/types/voice.py +++ b/discord/types/voice.py @@ -25,9 +25,9 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing_extensions import NotRequired, TypedDict +from typing_extensions import NotRequired from .member import MemberWithUser from .snowflake import Snowflake diff --git a/discord/types/webhook.py b/discord/types/webhook.py index a312b30a41..a857cd596c 100644 --- a/discord/types/webhook.py +++ b/discord/types/webhook.py @@ -25,9 +25,9 @@ from __future__ import annotations -from typing import Literal +from typing import Literal, TypedDict -from typing_extensions import NotRequired, TypedDict +from typing_extensions import NotRequired from .channel import PartialChannel from .snowflake import Snowflake diff --git a/discord/types/widget.py b/discord/types/widget.py index d327fa58fb..c4fb19b209 100644 --- a/discord/types/widget.py +++ b/discord/types/widget.py @@ -25,7 +25,9 @@ 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 diff --git a/discord/utils.py b/discord/utils.py index 37b7c5ffdf..1c4561f224 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 @@ -154,7 +153,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 @@ -1308,20 +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, ...]: - 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,) @@ -1352,7 +1337,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 +1349,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