Browse Source

merge master

pull/10166/head
DA-344 4 weeks ago
parent
commit
d5d3348518
  1. 4
      discord/activity.py
  2. 6
      discord/app_commands/installs.py
  3. 6
      discord/app_commands/models.py
  4. 8
      discord/app_commands/transformers.py
  5. 6
      discord/client.py
  6. 83
      discord/colour.py
  7. 3
      discord/components.py
  8. 8
      discord/embeds.py
  9. 8
      discord/ext/commands/context.py
  10. 3
      discord/ext/commands/parameters.py
  11. 5
      discord/guild.py
  12. 7
      discord/http.py
  13. 11
      discord/interactions.py
  14. 3
      discord/message.py
  15. 10
      discord/permissions.py
  16. 4
      discord/shard.py
  17. 6
      discord/template.py
  18. 1
      discord/types/interactions.py
  19. 3
      discord/ui/view.py
  20. 6
      docs/api.rst
  21. 2
      tests/test_app_commands_invoke.py
  22. 13
      tests/test_colour.py
  23. 11
      tests/test_embed.py

4
discord/activity.py

@ -418,7 +418,7 @@ class Game(BaseActivity):
return str(self.name) return str(self.name)
def __repr__(self) -> str: def __repr__(self) -> str:
return f'<Game name={self.name!r}>' return f'<Game name={self.name!r} platform={self.platform!r}>'
def to_dict(self) -> Dict[str, Any]: def to_dict(self) -> Dict[str, Any]:
timestamps: Dict[str, Any] = {} timestamps: Dict[str, Any] = {}
@ -514,7 +514,7 @@ class Streaming(BaseActivity):
return str(self.name) return str(self.name)
def __repr__(self) -> str: def __repr__(self) -> str:
return f'<Streaming name={self.name!r}>' return f'<Streaming name={self.name!r} platform={self.platform!r}>'
@property @property
def twitch_name(self) -> Optional[str]: def twitch_name(self) -> Optional[str]:

6
discord/app_commands/installs.py

@ -57,6 +57,9 @@ class AppInstallationType:
self._guild: Optional[bool] = guild self._guild: Optional[bool] = guild
self._user: Optional[bool] = user self._user: Optional[bool] = user
def __repr__(self):
return f'<AppInstallationType guild={self.guild!r} user={self.user!r}>'
@property @property
def guild(self) -> bool: def guild(self) -> bool:
""":class:`bool`: Whether the integration is a guild install.""" """:class:`bool`: Whether the integration is a guild install."""
@ -142,6 +145,9 @@ class AppCommandContext:
self._dm_channel: Optional[bool] = dm_channel self._dm_channel: Optional[bool] = dm_channel
self._private_channel: Optional[bool] = private_channel self._private_channel: Optional[bool] = private_channel
def __repr__(self) -> str:
return f'<AppCommandContext guild={self.guild!r} dm_channel={self.dm_channel!r} private_channel={self.private_channel!r}>'
@property @property
def guild(self) -> bool: def guild(self) -> bool:
""":class:`bool`: Whether the context allows usage in a guild.""" """:class:`bool`: Whether the context allows usage in a guild."""

6
discord/app_commands/models.py

@ -1063,6 +1063,9 @@ class AppCommandPermissions:
self.target: Union[Object, User, Member, Role, AllChannels, GuildChannel] = _object self.target: Union[Object, User, Member, Role, AllChannels, GuildChannel] = _object
def __repr__(self) -> str:
return f'<AppCommandPermissions id={self.id} type={self.type!r} guild={self.guild!r} permission={self.permission}>'
def to_dict(self) -> ApplicationCommandPermissions: def to_dict(self) -> ApplicationCommandPermissions:
return { return {
'id': self.target.id, 'id': self.target.id,
@ -1106,6 +1109,9 @@ class GuildAppCommandPermissions:
AppCommandPermissions(data=value, guild=guild, state=self._state) for value in data['permissions'] AppCommandPermissions(data=value, guild=guild, state=self._state) for value in data['permissions']
] ]
def __repr__(self) -> str:
return f'<GuildAppCommandPermissions id={self.id!r} guild_id={self.guild_id!r} permissions={self.permissions!r}>'
def to_dict(self) -> Dict[str, Any]: def to_dict(self) -> Dict[str, Any]:
return {'permissions': [p.to_dict() for p in self.permissions]} return {'permissions': [p.to_dict() for p in self.permissions]}

8
discord/app_commands/transformers.py

@ -52,7 +52,7 @@ from ..channel import StageChannel, VoiceChannel, TextChannel, CategoryChannel,
from ..abc import GuildChannel from ..abc import GuildChannel
from ..threads import Thread from ..threads import Thread
from ..enums import Enum as InternalEnum, AppCommandOptionType, ChannelType, Locale from ..enums import Enum as InternalEnum, AppCommandOptionType, ChannelType, Locale
from ..utils import MISSING, maybe_coroutine from ..utils import MISSING, maybe_coroutine, _human_join
from ..user import User from ..user import User
from ..role import Role from ..role import Role
from ..member import Member from ..member import Member
@ -631,7 +631,7 @@ class BaseChannelTransformer(Transformer[ClientT]):
display_name = channel_types[0].__name__ display_name = channel_types[0].__name__
types = CHANNEL_TO_TYPES[channel_types[0]] types = CHANNEL_TO_TYPES[channel_types[0]]
else: else:
display_name = '{}, and {}'.format(', '.join(t.__name__ for t in channel_types[:-1]), channel_types[-1].__name__) display_name = _human_join([t.__name__ for t in channel_types])
types = [] types = []
for t in channel_types: for t in channel_types:
@ -689,6 +689,7 @@ CHANNEL_TO_TYPES: Dict[Any, List[ChannelType]] = {
ChannelType.news, ChannelType.news,
ChannelType.category, ChannelType.category,
ChannelType.forum, ChannelType.forum,
ChannelType.media,
], ],
GuildChannel: [ GuildChannel: [
ChannelType.stage_voice, ChannelType.stage_voice,
@ -697,6 +698,7 @@ CHANNEL_TO_TYPES: Dict[Any, List[ChannelType]] = {
ChannelType.news, ChannelType.news,
ChannelType.category, ChannelType.category,
ChannelType.forum, ChannelType.forum,
ChannelType.media,
], ],
AppCommandThread: [ChannelType.news_thread, ChannelType.private_thread, ChannelType.public_thread], AppCommandThread: [ChannelType.news_thread, ChannelType.private_thread, ChannelType.public_thread],
Thread: [ChannelType.news_thread, ChannelType.private_thread, ChannelType.public_thread], Thread: [ChannelType.news_thread, ChannelType.private_thread, ChannelType.public_thread],
@ -704,7 +706,7 @@ CHANNEL_TO_TYPES: Dict[Any, List[ChannelType]] = {
VoiceChannel: [ChannelType.voice], VoiceChannel: [ChannelType.voice],
TextChannel: [ChannelType.text, ChannelType.news], TextChannel: [ChannelType.text, ChannelType.news],
CategoryChannel: [ChannelType.category], CategoryChannel: [ChannelType.category],
ForumChannel: [ChannelType.forum], ForumChannel: [ChannelType.forum, ChannelType.media],
} }
BUILT_IN_TRANSFORMERS: Dict[Any, Transformer] = { BUILT_IN_TRANSFORMERS: Dict[Any, Transformer] = {

6
discord/client.py

@ -67,7 +67,7 @@ from .voice_client import VoiceClient
from .http import HTTPClient from .http import HTTPClient
from .state import ConnectionState from .state import ConnectionState
from . import utils from . import utils
from .utils import MISSING, time_snowflake from .utils import MISSING, time_snowflake, deprecated
from .object import Object from .object import Object
from .backoff import ExponentialBackoff from .backoff import ExponentialBackoff
from .webhook import Webhook from .webhook import Webhook
@ -2388,6 +2388,7 @@ class Client:
data = await self.http.get_guild_preview(guild_id) data = await self.http.get_guild_preview(guild_id)
return GuildPreview(data=data, state=self._connection) return GuildPreview(data=data, state=self._connection)
@deprecated()
async def create_guild( async def create_guild(
self, self,
*, *,
@ -2408,6 +2409,9 @@ class Client:
This function will now raise :exc:`ValueError` instead of This function will now raise :exc:`ValueError` instead of
``InvalidArgument``. ``InvalidArgument``.
.. deprecated:: 2.6
This function is deprecated and will be removed in a future version.
Parameters Parameters
---------- ----------
name: :class:`str` name: :class:`str`

83
discord/colour.py

@ -21,6 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
""" """
from __future__ import annotations from __future__ import annotations
import colorsys import colorsys
@ -457,20 +458,59 @@ class Colour:
""" """
return cls(0x99AAB5) return cls(0x99AAB5)
@classmethod
def ash_theme(cls) -> Self:
"""A factory method that returns a :class:`Colour` with a value of ``0x2E2E34``.
This will appear transparent on Discord's ash theme.
.. colour:: #2E2E34
.. versionadded:: 2.6
"""
return cls(0x2E2E34)
@classmethod @classmethod
def dark_theme(cls) -> Self: def dark_theme(cls) -> Self:
"""A factory method that returns a :class:`Colour` with a value of ``0x313338``. """A factory method that returns a :class:`Colour` with a value of ``0x1A1A1E``.
This will appear transparent on Discord's dark theme. This will appear transparent on Discord's dark theme.
.. colour:: #313338 .. colour:: #1A1A1E
.. versionadded:: 1.5 .. versionadded:: 1.5
.. versionchanged:: 2.2 .. versionchanged:: 2.2
Updated colour from previous ``0x36393F`` to reflect discord theme changes. Updated colour from previous ``0x36393F`` to reflect discord theme changes.
.. versionchanged:: 2.6
Updated colour from previous ``0x313338`` to reflect discord theme changes.
""" """
return cls(0x313338) return cls(0x1A1A1E)
@classmethod
def onyx_theme(cls) -> Self:
"""A factory method that returns a :class:`Colour` with a value of ``0x070709``.
This will appear transparent on Discord's onyx theme.
.. colour:: #070709
.. versionadded:: 2.6
"""
return cls(0x070709)
@classmethod
def light_theme(cls) -> Self:
"""A factory method that returns a :class:`Colour` with a value of ``0xFBFBFB``.
This will appear transparent on Discord's light theme.
.. colour:: #FBFBFB
.. versionadded:: 2.6
"""
return cls(0xFBFBFB)
@classmethod @classmethod
def fuchsia(cls) -> Self: def fuchsia(cls) -> Self:
@ -492,25 +532,52 @@ class Colour:
""" """
return cls(0xFEE75C) return cls(0xFEE75C)
@classmethod
def ash_embed(cls) -> Self:
"""A factory method that returns a :class:`Colour` with a value of ``0x37373E``.
.. colour:: #37373E
.. versionadded:: 2.6
"""
return cls(0x37373E)
@classmethod @classmethod
def dark_embed(cls) -> Self: def dark_embed(cls) -> Self:
"""A factory method that returns a :class:`Colour` with a value of ``0x2B2D31``. """A factory method that returns a :class:`Colour` with a value of ``0x242429``.
.. colour:: #2B2D31 .. colour:: #242429
.. versionadded:: 2.2 .. versionadded:: 2.2
.. versionchanged:: 2.6
Updated colour from previous ``0x2B2D31`` to reflect discord theme changes.
"""
return cls(0x242429)
@classmethod
def onyx_embed(cls) -> Self:
"""A factory method that returns a :class:`Colour` with a value of ``0x131416``.
.. colour:: #131416
.. versionadded:: 2.6
""" """
return cls(0x2B2D31) return cls(0x131416)
@classmethod @classmethod
def light_embed(cls) -> Self: def light_embed(cls) -> Self:
"""A factory method that returns a :class:`Colour` with a value of ``0xEEEFF1``. """A factory method that returns a :class:`Colour` with a value of ``0xFFFFFF``.
.. colour:: #EEEFF1 .. colour:: #EEEFF1
.. versionadded:: 2.2 .. versionadded:: 2.2
.. versionchanged:: 2.6
Updated colour from previous ``0xEEEFF1`` to reflect discord theme changes.
""" """
return cls(0xEEEFF1) return cls(0xFFFFFF)
@classmethod @classmethod
def pink(cls) -> Self: def pink(cls) -> Self:

3
discord/components.py

@ -527,6 +527,9 @@ class SelectOption:
return payload return payload
def copy(self) -> SelectOption:
return self.__class__.from_dict(self.to_dict())
class TextInput(Component): class TextInput(Component):
"""Represents a text input from the Discord Bot UI Kit. """Represents a text input from the Discord Bot UI Kit.

8
discord/embeds.py

@ -61,6 +61,12 @@ class EmbedMediaProxy(EmbedProxy):
super().__init__(layer) super().__init__(layer)
self._flags = self.__dict__.pop('flags', 0) self._flags = self.__dict__.pop('flags', 0)
def __bool__(self) -> bool:
# This is a nasty check to see if we only have the `_flags` attribute which is created regardless in init.
# Had we had any of the other items, like image/video data this would be >1 and therefor
# would not be "empty".
return len(self.__dict__) > 1
@property @property
def flags(self) -> AttachmentFlags: def flags(self) -> AttachmentFlags:
return AttachmentFlags._from_value(self._flags or 0) return AttachmentFlags._from_value(self._flags or 0)
@ -737,7 +743,7 @@ class Embed:
# fmt: off # fmt: off
result = { result = {
key[1:]: getattr(self, key) key[1:]: getattr(self, key)
for key in self.__slots__ for key in Embed.__slots__
if key[0] == '_' and hasattr(self, key) if key[0] == '_' and hasattr(self, key)
} }
# fmt: on # fmt: on

8
discord/ext/commands/context.py

@ -992,7 +992,7 @@ class Context(discord.abc.Messageable, Generic[BotT]):
suppress_embeds: bool = False, suppress_embeds: bool = False,
ephemeral: bool = False, ephemeral: bool = False,
silent: bool = False, silent: bool = False,
poll: Poll = MISSING, poll: Optional[Poll] = None,
) -> Message: ) -> Message:
"""|coro| """|coro|
@ -1084,10 +1084,12 @@ class Context(discord.abc.Messageable, Generic[BotT]):
.. versionadded:: 2.2 .. versionadded:: 2.2
poll: :class:`~discord.Poll` poll: Optional[:class:`~discord.Poll`]
The poll to send with this message. The poll to send with this message.
.. versionadded:: 2.4 .. versionadded:: 2.4
.. versionchanged:: 2.6
This can now be ``None`` and defaults to ``None`` instead of ``MISSING``.
Raises Raises
-------- --------
@ -1142,7 +1144,7 @@ class Context(discord.abc.Messageable, Generic[BotT]):
'suppress_embeds': suppress_embeds, 'suppress_embeds': suppress_embeds,
'ephemeral': ephemeral, 'ephemeral': ephemeral,
'silent': silent, 'silent': silent,
'poll': poll, 'poll': MISSING if poll is None else poll,
} }
if self.interaction.response.is_done(): if self.interaction.response.is_done():

3
discord/ext/commands/parameters.py

@ -109,6 +109,9 @@ class Parameter(inspect.Parameter):
self._fallback = False self._fallback = False
self._displayed_name = displayed_name self._displayed_name = displayed_name
def __repr__(self) -> str:
return f'<{self.__class__.__name__} name={self._name!r} required={self.required}>'
def replace( def replace(
self, self,
*, *,

5
discord/guild.py

@ -2921,6 +2921,11 @@ class Guild(Hashable):
The name of the template. The name of the template.
description: :class:`str` description: :class:`str`
The description of the template. The description of the template.
Returns
--------
:class:`Template`
The created template.
""" """
from .template import Template from .template import Template

7
discord/http.py

@ -467,7 +467,12 @@ class Ratelimit:
future = self._loop.create_future() future = self._loop.create_future()
self._pending_requests.append(future) self._pending_requests.append(future)
try: try:
await future while not future.done():
# 30 matches the smallest allowed max_ratelimit_timeout
max_wait_time = self.expires - self._loop.time() if self.expires else 30
await asyncio.wait([future], timeout=max_wait_time)
if not future.done():
await self._refresh()
except: except:
future.cancel() future.cancel()
if self.remaining > 0 and not future.cancelled(): if self.remaining > 0 and not future.cancelled():

11
discord/interactions.py

@ -154,6 +154,10 @@ class Interaction(Generic[ClientT]):
The context of the interaction. The context of the interaction.
.. versionadded:: 2.4 .. versionadded:: 2.4
filesize_limit: int
The maximum number of bytes a file can have when responding to this interaction.
.. versionadded:: 2.6
""" """
__slots__: Tuple[str, ...] = ( __slots__: Tuple[str, ...] = (
@ -172,7 +176,8 @@ class Interaction(Generic[ClientT]):
'command_failed', 'command_failed',
'entitlement_sku_ids', 'entitlement_sku_ids',
'entitlements', 'entitlements',
"context", 'context',
'filesize_limit',
'_integration_owners', '_integration_owners',
'_permissions', '_permissions',
'_app_permissions', '_app_permissions',
@ -214,6 +219,7 @@ class Interaction(Generic[ClientT]):
self.application_id: int = int(data['application_id']) self.application_id: int = int(data['application_id'])
self.entitlement_sku_ids: List[int] = [int(x) for x in data.get('entitlement_skus', []) or []] self.entitlement_sku_ids: List[int] = [int(x) for x in data.get('entitlement_skus', []) or []]
self.entitlements: List[Entitlement] = [Entitlement(self._state, x) for x in data.get('entitlements', [])] self.entitlements: List[Entitlement] = [Entitlement(self._state, x) for x in data.get('entitlements', [])]
self.filesize_limit: int = data['attachment_size_limit']
# This is not entirely useful currently, unsure how to expose it in a way that it is. # This is not entirely useful currently, unsure how to expose it in a way that it is.
self._integration_owners: Dict[int, Snowflake] = { self._integration_owners: Dict[int, Snowflake] = {
int(k): int(v) for k, v in data.get('authorizing_integration_owners', {}).items() int(k): int(v) for k, v in data.get('authorizing_integration_owners', {}).items()
@ -730,6 +736,9 @@ class InteractionCallbackResponse(Generic[ClientT]):
self.type: InteractionResponseType = type self.type: InteractionResponseType = type
self._update(data) self._update(data)
def __repr__(self) -> str:
return f'<InteractionCallbackResponse id={self.id} type={self.type!r}>'
def _update(self, data: InteractionCallbackPayload) -> None: def _update(self, data: InteractionCallbackPayload) -> None:
interaction = data['interaction'] interaction = data['interaction']

3
discord/message.py

@ -988,6 +988,9 @@ class MessageApplication:
self._icon: Optional[str] = data['icon'] self._icon: Optional[str] = data['icon']
self._cover_image: Optional[str] = data.get('cover_image') self._cover_image: Optional[str] = data.get('cover_image')
def __str__(self) -> str:
return self.name
def __repr__(self) -> str: def __repr__(self) -> str:
return f'<MessageApplication id={self.id} name={self.name!r}>' return f'<MessageApplication id={self.id} name={self.name!r}>'

10
discord/permissions.py

@ -363,6 +363,16 @@ class Permissions(BaseFlags):
""" """
return cls(0b0000_0000_0000_0000_0000_0001_0000_0100_0111_0000_0000_0000_0010_0000_0011_1110) return cls(0b0000_0000_0000_0000_0000_0001_0000_0100_0111_0000_0000_0000_0010_0000_0011_1110)
@classmethod
def apps(cls) -> Self:
"""A factory method that creates a :class:`Permissions` with all
"Apps" permissions from the official Discord UI set to ``True``.
.. versionadded:: 2.6
"""
return cls(0b0000_0000_0000_0100_0000_0000_1000_0000_1000_0000_0000_0000_0000_0000_0000_0000)
@classmethod @classmethod
def events(cls) -> Self: def events(cls) -> Self:
"""A factory method that creates a :class:`Permissions` with all """A factory method that creates a :class:`Permissions` with all

4
discord/shard.py

@ -517,10 +517,10 @@ class AutoShardedClient(Client):
if item.type == EventType.close: if item.type == EventType.close:
await self.close() await self.close()
if isinstance(item.error, ConnectionClosed): if isinstance(item.error, ConnectionClosed):
if item.error.code != 1000:
raise item.error
if item.error.code == 4014: if item.error.code == 4014:
raise PrivilegedIntentsRequired(item.shard.id) from None raise PrivilegedIntentsRequired(item.shard.id) from None
if item.error.code != 1000:
raise item.error
return return
elif item.type in (EventType.identify, EventType.resume): elif item.type in (EventType.identify, EventType.resume):
await item.shard.reidentify(item.error) await item.shard.reidentify(item.error)

6
discord/template.py

@ -25,7 +25,7 @@ DEALINGS IN THE SOFTWARE.
from __future__ import annotations from __future__ import annotations
from typing import Any, Optional, TYPE_CHECKING, List from typing import Any, Optional, TYPE_CHECKING, List
from .utils import parse_time, _bytes_to_base64_data, MISSING from .utils import parse_time, _bytes_to_base64_data, MISSING, deprecated
from .guild import Guild from .guild import Guild
# fmt: off # fmt: off
@ -164,6 +164,7 @@ class Template:
f' creator={self.creator!r} source_guild={self.source_guild!r} is_dirty={self.is_dirty}>' f' creator={self.creator!r} source_guild={self.source_guild!r} is_dirty={self.is_dirty}>'
) )
@deprecated()
async def create_guild(self, name: str, icon: bytes = MISSING) -> Guild: async def create_guild(self, name: str, icon: bytes = MISSING) -> Guild:
"""|coro| """|coro|
@ -178,6 +179,9 @@ class Template:
This function will now raise :exc:`ValueError` instead of This function will now raise :exc:`ValueError` instead of
``InvalidArgument``. ``InvalidArgument``.
.. deprecated:: 2.6
This function is deprecated and will be removed in a future version.
Parameters Parameters
---------- ----------
name: :class:`str` name: :class:`str`

1
discord/types/interactions.py

@ -233,6 +233,7 @@ class _BaseInteraction(TypedDict):
entitlements: NotRequired[List[Entitlement]] entitlements: NotRequired[List[Entitlement]]
authorizing_integration_owners: Dict[Literal['0', '1'], Snowflake] authorizing_integration_owners: Dict[Literal['0', '1'], Snowflake]
context: NotRequired[InteractionContextType] context: NotRequired[InteractionContextType]
attachment_size_limit: int
class PingInteraction(_BaseInteraction): class PingInteraction(_BaseInteraction):

3
discord/ui/view.py

@ -51,6 +51,7 @@ import os
import copy import copy
from .item import Item, ItemCallbackType from .item import Item, ItemCallbackType
from .select import Select
from .dynamic import DynamicItem from .dynamic import DynamicItem
from ..components import ( from ..components import (
Component, Component,
@ -385,6 +386,8 @@ class BaseView:
item: Item = raw.__discord_ui_model_type__(**raw.__discord_ui_model_kwargs__) item: Item = raw.__discord_ui_model_type__(**raw.__discord_ui_model_kwargs__)
item.callback = _ViewCallback(raw, self, item) # type: ignore item.callback = _ViewCallback(raw, self, item) # type: ignore
item._view = self item._view = self
if isinstance(item, Select):
item.options = [option.copy() for option in item.options]
setattr(self, raw.__name__, item) setattr(self, raw.__name__, item)
parent = getattr(raw, '__discord_ui_parent__', None) parent = getattr(raw, '__discord_ui_parent__', None)
if parent: if parent:

6
docs/api.rst

@ -1354,8 +1354,10 @@ Soundboard
.. versionadded:: 2.5 .. versionadded:: 2.5
:param sound: The soundboard sound that was updated. :param before: The soundboard sound before the update.
:type sound: :class:`SoundboardSound` :type before: :class:`SoundboardSound`
:param after: The soundboard sound after the update.
:type after: :class:`SoundboardSound`
Stages Stages

2
tests/test_app_commands_invoke.py

@ -21,6 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
""" """
from __future__ import annotations from __future__ import annotations
@ -90,6 +91,7 @@ class MockCommandInteraction(discord.Interaction):
"version": 1, "version": 1,
"type": 2, "type": 2,
"data": self._get_command_data(command, self._get_command_options(**options)), "data": self._get_command_data(command, self._get_command_options(**options)),
"attachment_size_limit": 0,
} }
super().__init__(data=data, state=client._connection) super().__init__(data=data, state=client._connection)

13
tests/test_colour.py

@ -106,11 +106,16 @@ def test_from_str_failures(value):
(discord.Colour.og_blurple(), 0x7289DA), (discord.Colour.og_blurple(), 0x7289DA),
(discord.Colour.blurple(), 0x5865F2), (discord.Colour.blurple(), 0x5865F2),
(discord.Colour.greyple(), 0x99AAB5), (discord.Colour.greyple(), 0x99AAB5),
(discord.Colour.dark_theme(), 0x313338), (discord.Colour.ash_theme(), 0x2E2E34),
(discord.Colour.dark_theme(), 0x1A1A1E),
(discord.Colour.onyx_theme(), 0x070709),
(discord.Colour.light_theme(), 0xFBFBFB),
(discord.Colour.fuchsia(), 0xEB459E), (discord.Colour.fuchsia(), 0xEB459E),
(discord.Colour.yellow(), 0xFEE75C), (discord.Colour.yellow(), 0xFEE75C),
(discord.Colour.dark_embed(), 0x2B2D31), (discord.Colour.ash_embed(), 0x37373E),
(discord.Colour.light_embed(), 0xEEEFF1), (discord.Colour.dark_embed(), 0x242429),
(discord.Colour.onyx_embed(), 0x131416),
(discord.Colour.light_embed(), 0xFFFFFF),
(discord.Colour.pink(), 0xEB459F), (discord.Colour.pink(), 0xEB459F),
], ],
) )
@ -118,8 +123,6 @@ def test_static_colours(value, expected):
assert value.value == expected assert value.value == expected
@pytest.mark.parametrize( @pytest.mark.parametrize(
('value', 'property', 'expected'), ('value', 'property', 'expected'),
[ [

11
tests/test_embed.py

@ -267,3 +267,14 @@ def test_embed_colour_setter_failure(value):
embed = discord.Embed() embed = discord.Embed()
with pytest.raises(TypeError): with pytest.raises(TypeError):
embed.colour = value embed.colour = value
@pytest.mark.parametrize(
('title', 'return_val'),
[
('test', True),
(None, False)
]
)
def test_embed_truthiness(title: str, return_val: bool) -> None:
embed = discord.Embed(title=title)
assert bool(embed) is return_val

Loading…
Cancel
Save