From a67fd61352f0f9b64b6f44e0d65b31225f555f33 Mon Sep 17 00:00:00 2001 From: elenakrittik Date: Wed, 15 May 2024 21:34:01 +0300 Subject: [PATCH 1/7] refactor: Improve webhook typing. --- disnake/interactions/base.py | 6 ++- disnake/webhook/__init__.py | 5 ++- disnake/webhook/interaction.py | 73 ++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 disnake/webhook/interaction.py diff --git a/disnake/interactions/base.py b/disnake/interactions/base.py index ce3b5cc89b..ee07b20eff 100644 --- a/disnake/interactions/base.py +++ b/disnake/interactions/base.py @@ -19,6 +19,8 @@ overload, ) +from disnake.webhook.interaction import InteractionFollowupWebhook + from .. import utils from ..app_commands import OptionChoice from ..channel import PartialMessageable, _threaded_guild_channel_factory @@ -310,14 +312,14 @@ def response(self) -> InteractionResponse: return InteractionResponse(self) @utils.cached_slot_property("_cs_followup") - def followup(self) -> Webhook: + def followup(self) -> InteractionFollowupWebhook: """:class:`Webhook`: Returns the follow up webhook for follow up interactions.""" payload = { "id": self.application_id, "type": WebhookType.application.value, "token": self.token, } - return Webhook.from_state(data=payload, state=self._state) + return Webhook.from_state(data=payload, state=self._state) # type: ignore @utils.cached_slot_property("_cs_expires_at") def expires_at(self) -> datetime: diff --git a/disnake/webhook/__init__.py b/disnake/webhook/__init__.py index 42e0a37918..bbbd48a2ff 100644 --- a/disnake/webhook/__init__.py +++ b/disnake/webhook/__init__.py @@ -9,10 +9,13 @@ :license: MIT, see LICENSE for more details. """ -from . import async_, sync + +from . import async_, interaction, sync from .async_ import * +from .interaction import * from .sync import * __all__ = [] __all__.extend(async_.__all__) +__all__.extend(interaction.__all__) __all__.extend(sync.__all__) diff --git a/disnake/webhook/interaction.py b/disnake/webhook/interaction.py new file mode 100644 index 0000000000..baa7350e54 --- /dev/null +++ b/disnake/webhook/interaction.py @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: MIT + +from collections.abc import Sequence +from typing import List, Optional + +from disnake.abc import Snowflake +from disnake.embeds import Embed +from disnake.file import File +from disnake.flags import MessageFlags +from disnake.mentions import AllowedMentions +from disnake.ui.action_row import Components, MessageUIComponent +from disnake.ui.view import View +from disnake.utils import MISSING +from disnake.webhook.async_ import Webhook, WebhookMessage + +__all__ = ("InteractionFollowupWebhook",) + + +class InteractionFollowupWebhook(Webhook): + """A 1:1 copy of :class:`Webhook` meant for :attr:`Interaction.followup`\\'s annotations.""" + + async def send( + self, + content: Optional[str] = MISSING, + *, + tts: bool = MISSING, + ephemeral: bool = MISSING, + suppress_embeds: bool = MISSING, + flags: MessageFlags = MISSING, + file: File = MISSING, + files: List[File] = MISSING, + embed: Embed = MISSING, + embeds: List[Embed] = MISSING, + allowed_mentions: AllowedMentions = MISSING, + view: View = MISSING, + components: Components[MessageUIComponent] = MISSING, + thread: Snowflake = MISSING, + thread_name: str = MISSING, + applied_tags: Sequence[Snowflake] = MISSING, + delete_after: float = MISSING, + ) -> WebhookMessage: + """|coro| + + Sends a message using the webhook. + + This is the same as :meth:`Webhook.send` but with type hints changed. Namely, + the return type is :class:`WebhookMessage` instead of :class:`Message` because + ``wait=True`` for interaction webhooks, and ``username`` and ``avatar_url`` are + not supported. + + Returns + ------- + :class:`WebhookMessage` + The message that was sent. + """ + return await super().send( + content=content, + tts=tts, + ephemeral=ephemeral, + embeds=embeds, + embed=embed, + file=file, + files=files, + view=view, + components=components, + allowed_mentions=allowed_mentions, + thread=thread, + thread_name=thread_name, + applied_tags=applied_tags, + delete_after=delete_after, + suppress_embeds=suppress_embeds, + flags=flags, + ) # type: ignore From 168d93f54f81c57bb562ff1a489deab08ae04c68 Mon Sep 17 00:00:00 2001 From: elenakrittik Date: Wed, 15 May 2024 21:38:05 +0300 Subject: [PATCH 2/7] fix: remove dangerous type ignore --- disnake/webhook/interaction.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/disnake/webhook/interaction.py b/disnake/webhook/interaction.py index baa7350e54..5ad2079d88 100644 --- a/disnake/webhook/interaction.py +++ b/disnake/webhook/interaction.py @@ -70,4 +70,5 @@ async def send( delete_after=delete_after, suppress_embeds=suppress_embeds, flags=flags, - ) # type: ignore + wait=True, + ) From 245e65fbfba980b06001ed2b6f41b407fb8b8747 Mon Sep 17 00:00:00 2001 From: elenakrittik Date: Wed, 15 May 2024 21:40:18 +0300 Subject: [PATCH 3/7] fix: add future import --- disnake/webhook/interaction.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/disnake/webhook/interaction.py b/disnake/webhook/interaction.py index 5ad2079d88..5d2b4fccf4 100644 --- a/disnake/webhook/interaction.py +++ b/disnake/webhook/interaction.py @@ -1,5 +1,7 @@ # SPDX-License-Identifier: MIT +from __future__ import annotations + from collections.abc import Sequence from typing import List, Optional From dc3dbdc2a6d8ff547b45f6e0a5e494ea45e4b99d Mon Sep 17 00:00:00 2001 From: elenakrittik Date: Wed, 15 May 2024 21:45:31 +0300 Subject: [PATCH 4/7] docs: add chanelog entry --- changelog/626.misc.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/626.misc.rst diff --git a/changelog/626.misc.rst b/changelog/626.misc.rst new file mode 100644 index 0000000000..917b57057a --- /dev/null +++ b/changelog/626.misc.rst @@ -0,0 +1 @@ +Improve type annotations for :attr:`Interaction.followup`\'s ``.send`` method. From 886028058deb5f9ec2704b028b54298e975f0be6 Mon Sep 17 00:00:00 2001 From: elenakrittik Date: Sun, 19 May 2024 15:41:58 +0300 Subject: [PATCH 5/7] misc: Move what's possible into a TYPE_CHECKING block, change imports to be relative. --- disnake/webhook/interaction.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/disnake/webhook/interaction.py b/disnake/webhook/interaction.py index 5d2b4fccf4..bada5aa9c8 100644 --- a/disnake/webhook/interaction.py +++ b/disnake/webhook/interaction.py @@ -3,17 +3,22 @@ from __future__ import annotations from collections.abc import Sequence -from typing import List, Optional +from typing import TYPE_CHECKING -from disnake.abc import Snowflake -from disnake.embeds import Embed -from disnake.file import File -from disnake.flags import MessageFlags -from disnake.mentions import AllowedMentions -from disnake.ui.action_row import Components, MessageUIComponent -from disnake.ui.view import View -from disnake.utils import MISSING -from disnake.webhook.async_ import Webhook, WebhookMessage +from ..utils import MISSING +from .async_ import Webhook + +if TYPE_CHECKING: + from typing import List, Optional + + from ..abc import Snowflake + from ..embeds import Embed + from ..file import File + from ..flags import MessageFlags + from ..mentions import AllowedMentions + from ..ui.action_row import Components, MessageUIComponent + from ..ui.view import View + from ..webhook.async_ import WebhookMessage __all__ = ("InteractionFollowupWebhook",) From c66ff87b9f6470ee8dd36b70d94ead705d4adb3d Mon Sep 17 00:00:00 2001 From: elenakrittik Date: Sun, 19 May 2024 15:43:17 +0300 Subject: [PATCH 6/7] docs: Fix .send descriptions --- disnake/webhook/interaction.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/disnake/webhook/interaction.py b/disnake/webhook/interaction.py index bada5aa9c8..8e801f5cc7 100644 --- a/disnake/webhook/interaction.py +++ b/disnake/webhook/interaction.py @@ -51,9 +51,8 @@ async def send( Sends a message using the webhook. This is the same as :meth:`Webhook.send` but with type hints changed. Namely, - the return type is :class:`WebhookMessage` instead of :class:`Message` because - ``wait=True`` for interaction webhooks, and ``username`` and ``avatar_url`` are - not supported. + this method always returns a :class:`WebhookMessage` because ``wait=True`` for + interaction webhooks, and ``username`` and ``avatar_url`` are not supported. Returns ------- From ec9a610259e3a4aa1c4eaa50ecdbcfe0ab81af72 Mon Sep 17 00:00:00 2001 From: elenakrittik Date: Sun, 19 May 2024 16:29:11 +0300 Subject: [PATCH 7/7] misc: move .send into a TYPE_CHECKING block --- disnake/interactions/base.py | 4 +- disnake/webhook/async_.py | 4 +- disnake/webhook/interaction.py | 100 +++++++++++++++++---------------- 3 files changed, 56 insertions(+), 52 deletions(-) diff --git a/disnake/interactions/base.py b/disnake/interactions/base.py index ee07b20eff..fd268923bf 100644 --- a/disnake/interactions/base.py +++ b/disnake/interactions/base.py @@ -54,7 +54,7 @@ from ..role import Role from ..ui.action_row import components_to_dict from ..user import ClientUser, User -from ..webhook.async_ import Webhook, async_context, handle_message_parameters +from ..webhook.async_ import async_context, handle_message_parameters __all__ = ( "Interaction", @@ -319,7 +319,7 @@ def followup(self) -> InteractionFollowupWebhook: "type": WebhookType.application.value, "token": self.token, } - return Webhook.from_state(data=payload, state=self._state) # type: ignore + return InteractionFollowupWebhook.from_state(data=payload, state=self._state) @utils.cached_slot_property("_cs_expires_at") def expires_at(self) -> datetime: diff --git a/disnake/webhook/async_.py b/disnake/webhook/async_.py index 7e1228a529..a3763e628b 100644 --- a/disnake/webhook/async_.py +++ b/disnake/webhook/async_.py @@ -54,6 +54,8 @@ import datetime from types import TracebackType + from typing_extensions import Self + from ..abc import Snowflake from ..asset import AssetBytes from ..channel import ForumChannel, MediaChannel, StageChannel, TextChannel, VoiceChannel @@ -1255,7 +1257,7 @@ def _as_follower(cls, data, *, channel, user) -> Webhook: return cls(feed, session=session, state=state, token=state.http.token) @classmethod - def from_state(cls, data, state) -> Webhook: + def from_state(cls, data, state) -> Self: session = state.http._HTTPClient__session return cls(data, session=session, state=state, token=state.http.token) diff --git a/disnake/webhook/interaction.py b/disnake/webhook/interaction.py index 8e801f5cc7..5d8e4399fd 100644 --- a/disnake/webhook/interaction.py +++ b/disnake/webhook/interaction.py @@ -26,55 +26,57 @@ class InteractionFollowupWebhook(Webhook): """A 1:1 copy of :class:`Webhook` meant for :attr:`Interaction.followup`\\'s annotations.""" - async def send( - self, - content: Optional[str] = MISSING, - *, - tts: bool = MISSING, - ephemeral: bool = MISSING, - suppress_embeds: bool = MISSING, - flags: MessageFlags = MISSING, - file: File = MISSING, - files: List[File] = MISSING, - embed: Embed = MISSING, - embeds: List[Embed] = MISSING, - allowed_mentions: AllowedMentions = MISSING, - view: View = MISSING, - components: Components[MessageUIComponent] = MISSING, - thread: Snowflake = MISSING, - thread_name: str = MISSING, - applied_tags: Sequence[Snowflake] = MISSING, - delete_after: float = MISSING, - ) -> WebhookMessage: - """|coro| + if TYPE_CHECKING: - Sends a message using the webhook. + async def send( + self, + content: Optional[str] = MISSING, + *, + tts: bool = MISSING, + ephemeral: bool = MISSING, + suppress_embeds: bool = MISSING, + flags: MessageFlags = MISSING, + file: File = MISSING, + files: List[File] = MISSING, + embed: Embed = MISSING, + embeds: List[Embed] = MISSING, + allowed_mentions: AllowedMentions = MISSING, + view: View = MISSING, + components: Components[MessageUIComponent] = MISSING, + thread: Snowflake = MISSING, + thread_name: str = MISSING, + applied_tags: Sequence[Snowflake] = MISSING, + delete_after: float = MISSING, + ) -> WebhookMessage: + """|coro| - This is the same as :meth:`Webhook.send` but with type hints changed. Namely, - this method always returns a :class:`WebhookMessage` because ``wait=True`` for - interaction webhooks, and ``username`` and ``avatar_url`` are not supported. + Sends a message using the webhook. - Returns - ------- - :class:`WebhookMessage` - The message that was sent. - """ - return await super().send( - content=content, - tts=tts, - ephemeral=ephemeral, - embeds=embeds, - embed=embed, - file=file, - files=files, - view=view, - components=components, - allowed_mentions=allowed_mentions, - thread=thread, - thread_name=thread_name, - applied_tags=applied_tags, - delete_after=delete_after, - suppress_embeds=suppress_embeds, - flags=flags, - wait=True, - ) + This is the same as :meth:`Webhook.send` but with type hints changed. Namely, + this method always returns a :class:`WebhookMessage` because ``wait=True`` for + interaction webhooks, and ``username`` and ``avatar_url`` are not supported. + + Returns + ------- + :class:`WebhookMessage` + The message that was sent. + """ + return await super().send( + content=content, + tts=tts, + ephemeral=ephemeral, + embeds=embeds, + embed=embed, + file=file, + files=files, + view=view, + components=components, + allowed_mentions=allowed_mentions, + thread=thread, + thread_name=thread_name, + applied_tags=applied_tags, + delete_after=delete_after, + suppress_embeds=suppress_embeds, + flags=flags, + wait=True, + )