From 3fe9d187e386eb04c6667512b0bf5e0ef81ed49a Mon Sep 17 00:00:00 2001 From: baronkobama Date: Sun, 24 Jul 2022 16:34:32 -0500 Subject: [PATCH] Merge pull request #1476 from baronkobama/code-cleanup Large code/documentation cleanup --- discord/abc.py | 48 +++---- discord/activity.py | 17 ++- discord/audit_logs.py | 2 +- discord/automod.py | 13 +- discord/bot.py | 35 +++-- discord/channel.py | 226 +++++++++++++++++++----------- discord/client.py | 9 +- discord/cog.py | 42 ++++-- discord/colour.py | 12 +- discord/commands/context.py | 60 +++++--- discord/commands/core.py | 24 ++-- discord/commands/options.py | 20 ++- discord/commands/permissions.py | 2 +- discord/embeds.py | 29 +++- discord/emoji.py | 4 +- discord/enums.py | 4 + discord/errors.py | 8 +- discord/ext/bridge/context.py | 2 +- discord/ext/commands/bot.py | 8 +- discord/ext/commands/context.py | 10 +- discord/ext/commands/converter.py | 11 +- discord/ext/commands/cooldowns.py | 6 +- discord/ext/commands/core.py | 25 ++-- discord/ext/commands/flags.py | 14 +- discord/ext/commands/help.py | 26 ++-- discord/ext/commands/view.py | 4 +- discord/ext/pages/pagination.py | 52 ++++--- discord/ext/tasks/__init__.py | 7 +- discord/file.py | 4 +- discord/flags.py | 14 +- discord/gateway.py | 6 +- discord/guild.py | 114 ++++++++------- discord/http.py | 3 +- discord/integrations.py | 2 +- discord/interactions.py | 36 +++-- discord/invite.py | 2 +- discord/mentions.py | 10 +- discord/message.py | 47 ++++--- discord/opus.py | 8 +- discord/permissions.py | 1 + discord/player.py | 5 +- discord/raw_models.py | 10 +- discord/role.py | 8 +- discord/scheduled_events.py | 9 +- discord/shard.py | 9 +- discord/sinks/errors.py | 14 +- discord/sinks/m4a.py | 2 +- discord/sinks/mka.py | 1 - discord/sinks/mkv.py | 3 +- discord/sinks/mp3.py | 3 - discord/sinks/mp4.py | 2 +- discord/sinks/ogg.py | 1 - discord/sinks/wave.py | 2 - discord/stage_instance.py | 8 +- discord/state.py | 4 +- discord/template.py | 12 +- discord/threads.py | 14 +- discord/types/automod.py | 2 +- discord/types/threads.py | 3 +- discord/ui/input_text.py | 1 - discord/ui/modal.py | 6 +- discord/ui/view.py | 11 +- discord/user.py | 6 +- discord/utils.py | 33 +++-- discord/voice_client.py | 14 +- discord/webhook/async_.py | 12 +- discord/webhook/sync.py | 8 +- discord/welcome_screen.py | 11 +- discord/widget.py | 4 +- docs/api.rst | 71 ++++++---- 70 files changed, 722 insertions(+), 534 deletions(-) diff --git a/discord/abc.py b/discord/abc.py index 90a7256c8e..00a6a13c10 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -175,14 +175,6 @@ async def _purge_messages_helper( return ret -class _Undefined: - def __repr__(self) -> str: - return "see-below" - - -_undefined: Any = _Undefined() - - @runtime_checkable class Snowflake(Protocol): """An ABC that details the common operations on a Discord model. @@ -382,7 +374,7 @@ async def _move( payload = [] for index, c in enumerate(channels): d: Dict[str, Any] = {"id": c.id, "position": index} - if parent_id is not _undefined and c.id == self.id: + if parent_id is not MISSING and c.id == self.id: d.update(parent_id=parent_id, lock_permissions=lock_permissions) payload.append(d) @@ -392,7 +384,7 @@ async def _edit(self, options: Dict[str, Any], reason: Optional[str]) -> Optiona try: parent = options.pop("category") except KeyError: - parent_id = _undefined + parent_id = MISSING else: parent_id = parent and parent.id @@ -420,7 +412,7 @@ async def _edit(self, options: Dict[str, Any], reason: Optional[str]) -> Optiona try: position = options.pop("position") except KeyError: - if parent_id is not _undefined: + if parent_id is not MISSING: if lock_permissions: category = self.guild.get_channel(parent_id) if category: @@ -603,7 +595,7 @@ def category(self) -> Optional[CategoryChannel]: @property def permissions_synced(self) -> bool: - """:class:`bool`: Whether or not the permissions for this channel are synced with the + """:class:`bool`: Whether the permissions for this channel are synced with the category it belongs to. If there is no category then this is ``False``. @@ -658,7 +650,7 @@ def permissions_for(self, obj: Union[Member, Role], /) -> Permissions: # (or otherwise) are then OR'd together. # After the role permissions are resolved, the member permissions # have to take into effect. - # After all that is done.. you have to do the following: + # After all that is done, you have to do the following: # If manage permissions is True, then all permissions are set to True. @@ -781,7 +773,7 @@ async def set_permissions( self, target: Union[Member, Role], *, - overwrite: Optional[Union[PermissionOverwrite, _Undefined]] = ..., + overwrite: Optional[PermissionOverwrite] = ..., reason: Optional[str] = ..., ) -> None: ... @@ -796,7 +788,7 @@ async def set_permissions( ) -> None: ... - async def set_permissions(self, target, *, overwrite=_undefined, reason=None, **permissions): + async def set_permissions(self, target, *, overwrite=MISSING, reason=None, **permissions): r"""|coro| Sets the channel specific permission overwrites for a target in the @@ -874,7 +866,7 @@ async def set_permissions(self, target, *, overwrite=_undefined, reason=None, ** else: raise InvalidArgument("target parameter must be either Member or Role") - if overwrite is _undefined: + if overwrite is MISSING: if len(permissions) == 0: raise InvalidArgument("No overwrite provided.") try: @@ -1046,7 +1038,7 @@ async def move(self, **kwargs) -> None: Raises ------- InvalidArgument - An invalid position was given or a bad mix of arguments were passed. + An invalid position was given or a bad mix of arguments was passed. Forbidden You do not have permissions to move the channel. HTTPException @@ -1152,20 +1144,22 @@ async def create_invite( .. versionadded:: 2.0 target_user: Optional[:class:`User`] - The user whose stream to display for this invite, required if `target_type` is `TargetType.stream`. The user must be streaming in the channel. + The user whose stream to display for this invite, required if `target_type` is `TargetType.stream`. + The user must be streaming in the channel. .. versionadded:: 2.0 target_application_id: Optional[:class:`int`] - The id of the embedded application for the invite, required if `target_type` is `TargetType.embedded_application`. + The id of the embedded application for the invite, required if `target_type` is + `TargetType.embedded_application`. .. versionadded:: 2.0 - target_event: Optional[:class:`ScheduledEvent`] + target_event: Optional[:class:`.ScheduledEvent`] The scheduled event object to link to the event. - Shortcut to :meth:`Invite.set_scheduled_event` + Shortcut to :meth:`.Invite.set_scheduled_event` - See :meth:`Invite.set_scheduled_event` for more + See :meth:`.Invite.set_scheduled_event` for more info on event invite linking. .. versionadded:: 2.0 @@ -1383,11 +1377,13 @@ async def send( .. versionadded:: 1.4 - reference: Union[:class:`~discord.Message`, :class:`~discord.MessageReference`, :class:`~discord.PartialMessage`] + reference: Union[:class:`~discord.Message`, :class:`~discord.MessageReference`, + :class:`~discord.PartialMessage`] A reference to the :class:`~discord.Message` to which you are replying, this can be created using :meth:`~discord.Message.to_reference` or passed directly as a :class:`~discord.Message`. You can control - whether this mentions the author of the referenced message using the :attr:`~discord.AllowedMentions.replied_user` - attribute of ``allowed_mentions`` or by setting ``mention_author``. + whether this mentions the author of the referenced message using the + :attr:`~discord.AllowedMentions.replied_user` attribute of ``allowed_mentions`` or by + setting ``mention_author``. .. versionadded:: 1.6 @@ -1732,7 +1728,7 @@ def history( If a datetime is provided, it is recommended to use a UTC aware datetime. If the datetime is naive, it is assumed to be local time. When using this argument, the maximum limit is 101. Note that if the limit is an - even number then this will return at most limit + 1 messages. + even number, then this will return at most limit + 1 messages. oldest_first: Optional[:class:`bool`] If set to ``True``, return messages in oldest->newest order. Defaults to ``True`` if ``after`` is specified, otherwise ``False``. diff --git a/discord/activity.py b/discord/activity.py index 2aa6a1739b..0ad4482c8f 100644 --- a/discord/activity.py +++ b/discord/activity.py @@ -97,7 +97,6 @@ from .types.activity import Activity as ActivityPayload from .types.activity import ( ActivityAssets, - ActivityButton, ActivityParty, ActivityTimestamps, ) @@ -166,7 +165,7 @@ class Activity(BaseActivity): The user's current state. For example, "In Game". details: Optional[:class:`str`] The detail of the user's current activity. - timestamps: :class:`dict` + timestamps: Dict[:class:`str`, :class:`int`] A dictionary of timestamps. It contains the following optional keys: - ``start``: Corresponds to when the user started doing the @@ -174,7 +173,7 @@ class Activity(BaseActivity): - ``end``: Corresponds to when the user will finish doing the activity in milliseconds since Unix epoch. - assets: :class:`dict` + assets: Dict[:class:`str`, :class:`str`] A dictionary representing the images and their hover text of an activity. It contains the following optional keys: @@ -183,12 +182,12 @@ class Activity(BaseActivity): - ``small_image``: A string representing the ID for the small image asset. - ``small_text``: A string representing the text when hovering over the small image asset. - party: :class:`dict` + party: Dict[:class:`str`, Union[:class:`str`, List[:class:`int`]]] A dictionary representing the activity party. It contains the following optional keys: - ``id``: A string representing the party ID. - ``size``: A list of up to two integer elements denoting (current_size, maximum_size). - buttons: Union[List[:class:`dict`], List[:class:`str`]] + buttons: Union[List[Dict[:class:`str`, :class:`str`]], List[:class:`str`]] A list of dictionaries representing custom buttons shown in a rich presence. Each dictionary contains the following keys: @@ -197,7 +196,7 @@ class Activity(BaseActivity): .. note:: - Bots cannot access a user's activity button URLs. Therefore the type of this attribute + Bots cannot access a user's activity button URLs. Therefore, the type of this attribute will be List[:class:`str`] when received through the gateway. .. versionadded:: 2.0 @@ -475,8 +474,8 @@ class Streaming(BaseActivity): url: :class:`str` The stream's URL. - assets: :class:`dict` - A dictionary comprising of similar keys than those in :attr:`Activity.assets`. + assets: Dict[:class:`str`, :class:`str`] + A dictionary comprised of similar keys than those in :attr:`Activity.assets`. """ __slots__ = ("platform", "name", "game", "url", "details", "assets") @@ -509,7 +508,7 @@ def twitch_name(self): """Optional[:class:`str`]: If provided, the twitch name of the user streaming. This corresponds to the ``large_image`` key of the :attr:`Streaming.assets` - dictionary if it starts with ``twitch:``. Typically set by the Discord client. + dictionary if it starts with ``twitch:``. Typically this is set by the Discord client. """ try: diff --git a/discord/audit_logs.py b/discord/audit_logs.py index 34263abbe7..6868f99a8d 100644 --- a/discord/audit_logs.py +++ b/discord/audit_logs.py @@ -412,7 +412,7 @@ class AuditLogEntry(Hashable): The reason this action was done. extra: Any Extra information that this entry has that might be useful. - For most actions, this is ``None``. However in some cases it + For most actions, this is ``None``. However, in some cases it contains extra information. See :class:`AuditLogAction` for which actions have this field filled out. """ diff --git a/discord/automod.py b/discord/automod.py index 4eeee9a46e..b002189c6b 100644 --- a/discord/automod.py +++ b/discord/automod.py @@ -70,9 +70,11 @@ class AutoModActionMetadata: Attributes ----------- channel_id: :class:`int` - The ID of the channel to send the message to. Only for actions of type :attr:`AutoModActionType.send_alert_message`. + The ID of the channel to send the message to. + Only for actions of type :attr:`AutoModActionType.send_alert_message`. timeout_duration: :class:`datetime.timedelta` - How long the member that triggered the action should be timed out for. Only for actions of type :attr:`AutoModActionType.timeout`. + How long the member that triggered the action should be timed out for. + Only for actions of type :attr:`AutoModActionType.timeout`. """ # maybe add a table of action types and attributes? @@ -124,7 +126,6 @@ def __repr__(self) -> str: return f"" - class AutoModAction: """Represents an action for a guild's auto moderation rule. @@ -200,7 +201,7 @@ def to_dict(self) -> Dict: return data @classmethod - def from_dict(cls, data: AutoModActionMetadataPayload): + def from_dict(cls, data: AutoModTriggerMetadataPayload): kwargs = {} if (keyword_filter := data.get("keyword_filter")) is not None: @@ -339,8 +340,8 @@ def exempt_roles(self) -> List[Union[Role, Object]]: @cached_property def exempt_channels(self) -> List[Union[Union[TextChannel, ForumChannel, VoiceChannel], Object]]: - """List[Union[Union[:class:`TextChannel`, :class:`ForumChannel`, :class:`VoiceChannel`], :class:`Object`]]: The channels - that are exempt from this rule. + """List[Union[Union[:class:`TextChannel`, :class:`ForumChannel`, :class:`VoiceChannel`], :class:`Object`]]: + The channels that are exempt from this rule. If a channel is not found in the guild's cache, then it will be returned as an :class:`Object`. diff --git a/discord/bot.py b/discord/bot.py index 912bc2d510..e4011434a3 100644 --- a/discord/bot.py +++ b/discord/bot.py @@ -211,7 +211,11 @@ def get_application_command( return return command - async def get_desynced_commands(self, guild_id: Optional[int] = None, prefetched=None) -> List[Dict[str, Any]]: + async def get_desynced_commands( + self, + guild_id: Optional[int] = None, + prefetched: Optional[List[ApplicationCommand]] = None + ) -> List[Dict[str, Any]]: """|coro| Gets the list of commands that are desynced from discord. If ``guild_id`` is specified, it will only return @@ -228,12 +232,12 @@ async def get_desynced_commands(self, guild_id: Optional[int] = None, prefetched ---------- guild_id: Optional[:class:`int`] The guild id to get the desynced commands for, else global commands if unspecified. - prefetched + prefetched: Optional[List[:class:`.ApplicationCommand`]] If you already fetched the commands, you can pass them here to be used. Not recommended for typical usage. Returns ------- - List[Dict[str, Any]] + List[Dict[:class:`str`, Any]] A list of the desynced commands. Each will come with at least the ``cmd`` and ``action`` keys, which respectively contain the command and the action to perform. Other keys may also be present depending on the action, including ``id``. @@ -355,8 +359,8 @@ async def register_command( ) -> None: """|coro| - Registers a command. If the command has ``guild_ids`` set, or if the ``guild_ids`` parameter is passed, the command will - be registered as a guild command for those guilds. + Registers a command. If the command has ``guild_ids`` set, or if the ``guild_ids`` parameter is passed, + the command will be registered as a guild command for those guilds. Parameters ---------- @@ -644,8 +648,6 @@ async def sync_commands( guild_commands, guild_id=guild_id, method=method, force=force, delete_existing=delete_existing ) - global_permissions: List = [] - for i in registered_commands: cmd = get( self.pending_application_commands, @@ -925,7 +927,7 @@ async def get_application_context(self, interaction: Interaction, cls=None) -> A Returns the invocation context from the interaction. This is a more low-level counter-part for :meth:`.process_application_commands` - to allow users more fine grained control over the processing. + to allow users more fine-grained control over the processing. Parameters ----------- @@ -953,7 +955,7 @@ async def get_autocomplete_context(self, interaction: Interaction, cls=None) -> Returns the autocomplete context from the interaction. This is a more low-level counter-part for :meth:`.process_application_commands` - to allow users more fine grained control over the processing. + to allow users more fine-grained control over the processing. Parameters ----------- @@ -1006,10 +1008,7 @@ def _bot(self) -> Union["Bot", "AutoShardedBot"]: class BotBase(ApplicationCommandMixin, CogMixin, ABC): _supports_prefixed_commands = False - # TODO I think def __init__(self, description=None, *args, **options): - # super(Client, self).__init__(*args, **kwargs) - # I replaced ^ with v and it worked super().__init__(*args, **options) self.extra_events = {} # TYPE: Dict[str, List[CoroFunc]] self.__cogs = {} # TYPE: Dict[str, Cog] @@ -1048,7 +1047,7 @@ async def on_application_command_error(self, context: ApplicationContext, except The default command error handler provided by the bot. - By default this prints to :data:`sys.stderr` however it could be + By default, this prints to :data:`sys.stderr` however it could be overridden to have a different implementation. This only fires if you do not specify any listeners for command error. @@ -1072,7 +1071,7 @@ async def on_application_command_error(self, context: ApplicationContext, except def check(self, func): """A decorator that adds a global check to the bot. A global check is similar to a :func:`.check` that is - applied on a per command basis except it is run before any command checks have been verified and applies to + applied on a per-command basis except it is run before any command checks have been verified and applies to every command the bot has. .. note:: @@ -1126,10 +1125,10 @@ def remove_check(self, func, *, call_once: bool = False) -> None: the :meth:`.Bot.add_check` call or using :meth:`.check_once`. """ - l = self._check_once if call_once else self._checks + checks = self._check_once if call_once else self._checks try: - l.remove(func) + checks.remove(func) except ValueError: pass @@ -1374,7 +1373,7 @@ class Bot(BotBase, Client): anything that you can do with a :class:`discord.Client` you can do with this bot. - This class also subclasses :class:`.ApplicationCommandMixin` to provide the functionality + This class also subclasses ``ApplicationCommandMixin`` to provide the functionality to manage commands. .. versionadded:: 2.0 @@ -1401,7 +1400,7 @@ class Bot(BotBase, Client): .. versionadded:: 2.0 auto_sync_commands: :class:`bool` - Whether or not to automatically sync slash commands. This will call sync_commands in on_connect, and in + Whether to automatically sync slash commands. This will call sync_commands in on_connect, and in :attr:`.process_application_commands` if the command is not found. Defaults to ``True``. .. versionadded:: 2.0 diff --git a/discord/channel.py b/discord/channel.py index 22d55e0edb..dc4f88e45d 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -100,65 +100,6 @@ class _TextChannel(discord.abc.GuildChannel, Hashable): - """Represents a Discord text channel. - - .. container:: operations - - .. describe:: x == y - - Checks if two channels are equal. - - .. describe:: x != y - - Checks if two channels are not equal. - - .. describe:: hash(x) - - Returns the channel's hash. - - .. describe:: str(x) - - Returns the channel's name. - - Attributes - ----------- - name: :class:`str` - The channel name. - guild: :class:`Guild` - The guild the channel belongs to. - id: :class:`int` - The channel ID. - category_id: Optional[:class:`int`] - The category channel ID this channel belongs to, if applicable. - topic: Optional[:class:`str`] - The channel's topic. ``None`` if it doesn't exist. - position: Optional[:class:`int`] - The position in the channel list. This is a number that starts at 0. e.g. the - top channel is position 0. Can be ``None`` if the channel was received in an interaction. - last_message_id: Optional[:class:`int`] - The last message ID of the message sent to this channel. It may - *not* point to an existing or valid message. - slowmode_delay: :class:`int` - The number of seconds a member must wait between sending messages - in this channel. A value of `0` denotes that it is disabled. - Bots and users with :attr:`~Permissions.manage_channels` or - :attr:`~Permissions.manage_messages` bypass slowmode. - nsfw: :class:`bool` - If the channel is marked as "not safe for work". - - .. note:: - - To check if the channel or the guild of that channel are marked as NSFW, consider :meth:`is_nsfw` instead. - default_auto_archive_duration: :class:`int` - The default auto archive duration in minutes for threads created in this channel. - - .. versionadded:: 2.0 - flags: :class:`ChannelFlags` - Extra features of the channel. - - .. versionadded:: 2.0 - """ - __slots__ = ( "name", "id", @@ -329,9 +270,8 @@ async def edit(self, *, reason=None, **options): is only available to guilds that contain ``NEWS`` in :attr:`Guild.features`. reason: Optional[:class:`str`] The reason for editing this channel. Shows up on the audit log. - overwrites: :class:`Mapping` - A :class:`Mapping` of target (either a role or a member) to - :class:`PermissionOverwrite` to apply to the channel. + overwrites: Dict[Union[:class:`Role`, :class:`Member`, :class:`Snowflake`], :class:`PermissionOverwrite`] + The overwrites to apply to channel permissions. Useful for creating secret channels. default_auto_archive_duration: :class:`int` The new default auto archive duration in minutes for threads created in this channel. Must be one of ``60``, ``1440``, ``4320``, or ``10080``. @@ -706,6 +646,65 @@ def archived_threads( class TextChannel(discord.abc.Messageable, _TextChannel): + """Represents a Discord text channel. + + .. container:: operations + + .. describe:: x == y + + Checks if two channels are equal. + + .. describe:: x != y + + Checks if two channels are not equal. + + .. describe:: hash(x) + + Returns the channel's hash. + + .. describe:: str(x) + + Returns the channel's name. + + Attributes + ----------- + name: :class:`str` + The channel name. + guild: :class:`Guild` + The guild the channel belongs to. + id: :class:`int` + The channel ID. + category_id: Optional[:class:`int`] + The category channel ID this channel belongs to, if applicable. + topic: Optional[:class:`str`] + The channel's topic. ``None`` if it doesn't exist. + position: Optional[:class:`int`] + The position in the channel list. This is a number that starts at 0. e.g. the + top channel is position 0. Can be ``None`` if the channel was received in an interaction. + last_message_id: Optional[:class:`int`] + The last message ID of the message sent to this channel. It may + *not* point to an existing or valid message. + slowmode_delay: :class:`int` + The number of seconds a member must wait between sending messages + in this channel. A value of `0` denotes that it is disabled. + Bots and users with :attr:`~Permissions.manage_channels` or + :attr:`~Permissions.manage_messages` bypass slowmode. + nsfw: :class:`bool` + If the channel is marked as "not safe for work". + + .. note:: + + To check if the channel or the guild of that channel are marked as NSFW, consider :meth:`is_nsfw` instead. + default_auto_archive_duration: :class:`int` + The default auto archive duration in minutes for threads created in this channel. + + .. versionadded:: 2.0 + flags: :class:`ChannelFlags` + Extra features of the channel. + + .. versionadded:: 2.0 + """ + def __init__(self, *, state: ConnectionState, guild: Guild, data: TextChannelPayload): super().__init__(state=state, guild=guild, data=data) @@ -720,11 +719,12 @@ async def _get_channel(self) -> "TextChannel": return self def is_news(self) -> bool: - """:class:`bool`: Checks if the channel is a news/anouncements channel.""" + """:class:`bool`: Checks if the channel is a news/announcements channel.""" return self._type == ChannelType.news.value @property def news(self) -> bool: + """Equivalent to :meth:`is_news`.""" return self.is_news() async def create_thread( @@ -759,7 +759,7 @@ async def create_thread( type: Optional[:class:`ChannelType`] The type of thread to create. If a ``message`` is passed then this parameter is ignored, as a thread created with a message is always a public thread. - By default this creates a private thread if this is ``None``. + By default, this creates a private thread if this is ``None``. reason: :class:`str` The reason for creating a new thread. Shows up on the audit log. @@ -800,6 +800,69 @@ async def create_thread( class ForumChannel(_TextChannel): + """Represents a Discord forum channel. + + .. container:: operations + + .. describe:: x == y + + Checks if two channels are equal. + + .. describe:: x != y + + Checks if two channels are not equal. + + .. describe:: hash(x) + + Returns the channel's hash. + + .. describe:: str(x) + + Returns the channel's name. + + Attributes + ----------- + name: :class:`str` + The channel name. + guild: :class:`Guild` + The guild the channel belongs to. + id: :class:`int` + The channel ID. + category_id: Optional[:class:`int`] + The category channel ID this channel belongs to, if applicable. + topic: Optional[:class:`str`] + The channel's topic. ``None`` if it doesn't exist. + + .. note:: + + :attr:`guidelines` exists as an alternative to this attribute. + position: Optional[:class:`int`] + The position in the channel list. This is a number that starts at 0. e.g. the + top channel is position 0. Can be ``None`` if the channel was received in an interaction. + last_message_id: Optional[:class:`int`] + The last message ID of the message sent to this channel. It may + *not* point to an existing or valid message. + slowmode_delay: :class:`int` + The number of seconds a member must wait between sending messages + in this channel. A value of `0` denotes that it is disabled. + Bots and users with :attr:`~Permissions.manage_channels` or + :attr:`~Permissions.manage_messages` bypass slowmode. + nsfw: :class:`bool` + If the channel is marked as "not safe for work". + + .. note:: + + To check if the channel or the guild of that channel are marked as NSFW, consider :meth:`is_nsfw` instead. + default_auto_archive_duration: :class:`int` + The default auto archive duration in minutes for threads created in this channel. + + .. versionadded:: 2.0 + flags: :class:`ChannelFlags` + Extra features of the channel. + + .. versionadded:: 2.0 + """ + def __init__(self, *, state: ConnectionState, guild: Guild, data: ForumChannelPayload): super().__init__(state=state, guild=guild, data=data) @@ -846,10 +909,16 @@ async def create_thread( The content of the message to send. embed: :class:`~discord.Embed` The rich embed for the content. + embeds: List[:class:`~discord.Embed`] + A list of embeds to upload. Must be a maximum of 10. file: :class:`~discord.File` The file to upload. files: List[:class:`~discord.File`] A list of files to upload. Must be a maximum of 10. + stickers: Sequence[Union[:class:`~discord.GuildSticker`, :class:`~discord.StickerItem`]] + A list of stickers to upload. Must be a maximum of 3. + delete_message_after: :class:`int` + The time to wait before deleting the thread. nonce: :class:`int` The nonce to use for sending this message. If the message was successfully sent, then the message will have a nonce with this value. @@ -862,10 +931,6 @@ async def create_thread( are used instead. view: :class:`discord.ui.View` A Discord UI View to add to the message. - embeds: List[:class:`~discord.Embed`] - A list of embeds to upload. Must be a maximum of 10. - stickers: Sequence[Union[:class:`~discord.GuildSticker`, :class:`~discord.StickerItem`]] - A list of stickers to upload. Must be a maximum of 3. auto_archive_duration: :class:`int` The duration in minutes before a thread is automatically archived for inactivity. If not provided, the channel's default auto archive duration is used. @@ -894,7 +959,7 @@ async def create_thread( message_content = str(content) if content is not None else None if embed is not None and embeds is not None: - raise InvalidArgument("cannot pass both embed and embeds parameter to create_post()") + raise InvalidArgument("cannot pass both embed and embeds parameter to create_thread()") if embed is not None: embed = embed.to_dict() @@ -1083,7 +1148,7 @@ def voice_states(self) -> Dict[int, VoiceState]: def permissions_for(self, obj: Union[Member, Role], /) -> Permissions: base = super().permissions_for(obj) - # voice channels cannot be edited by people who can't connect to them + # Voice channels cannot be edited by people who can't connect to them. # It also implicitly denies all other voice perms if not base.connect: denied = Permissions.voice() @@ -1484,9 +1549,8 @@ async def edit(self, *, reason=None, **options): category. reason: Optional[:class:`str`] The reason for editing this channel. Shows up on the audit log. - overwrites: :class:`Mapping` - A :class:`Mapping` of target (either a role or a member) to - :class:`PermissionOverwrite` to apply to the channel. + overwrites: Dict[Union[:class:`Role`, :class:`Member`, :class:`Snowflake`], :class:`PermissionOverwrite`] + The overwrites to apply to channel permissions. Useful for creating secret channels. rtc_region: Optional[:class:`VoiceRegion`] The new region for the voice channel's voice communication. A value of ``None`` indicates automatic voice region detection. @@ -1764,9 +1828,9 @@ async def fetch_instance(self) -> StageInstance: Raises ------- - :exc:`.NotFound` + NotFound The stage instance or channel could not be found. - :exc:`.HTTPException` + HTTPException Getting the stage instance failed. Returns @@ -1825,9 +1889,8 @@ async def edit(self, *, reason=None, **options): category. reason: Optional[:class:`str`] The reason for editing this channel. Shows up on the audit log. - overwrites: :class:`Mapping` - A :class:`Mapping` of target (either a role or a member) to - :class:`PermissionOverwrite` to apply to the channel. + overwrites: Dict[Union[:class:`Role`, :class:`Member`, :class:`Snowflake`], :class:`PermissionOverwrite`] + The overwrites to apply to channel permissions. Useful for creating secret channels. rtc_region: Optional[:class:`VoiceRegion`] The new region for the stage channel's voice communication. A value of ``None`` indicates automatic voice region detection. @@ -1994,9 +2057,8 @@ async def edit(self, *, reason=None, **options): To mark the category as NSFW or not. reason: Optional[:class:`str`] The reason for editing this category. Shows up on the audit log. - overwrites: :class:`Mapping` - A :class:`Mapping` of target (either a role or a member) to - :class:`PermissionOverwrite` to apply to the channel. + overwrites: Dict[Union[:class:`Role`, :class:`Member`, :class:`Snowflake`], :class:`PermissionOverwrite`] + The overwrites to apply to channel permissions. Useful for creating secret channels. Raises ------ @@ -2032,7 +2094,7 @@ def channels(self) -> List[GuildChannelType]: """ def comparator(channel): - return (not isinstance(channel, _TextChannel), channel.position) + return not isinstance(channel, _TextChannel), channel.position ret = [c for c in self.guild.channels if c.category_id == self.id] ret.sort(key=comparator) diff --git a/discord/client.py b/discord/client.py index 584fa3549e..2529677d49 100644 --- a/discord/client.py +++ b/discord/client.py @@ -444,7 +444,7 @@ async def on_error(self, event_method: str, *args: Any, **kwargs: Any) -> None: The default error handler provided by the client. - By default this prints to :data:`sys.stderr` however it could be + By default, this prints to :data:`sys.stderr` however it could be overridden to have a different implementation. Check :func:`~discord.on_error` for more details. """ @@ -592,7 +592,7 @@ async def connect(self, *, reconnect: bool = True) -> None: # We should only get this when an unhandled close code happens, # such as a clean disconnect (1000) or a bad state (bad token, no sharding, etc) - # sometimes, discord sends us 1000 for unknown reasons so we should reconnect + # sometimes, discord sends us 1000 for unknown reasons, so we should reconnect # regardless and rely on is_closed instead if isinstance(exc, ConnectionClosed): if exc.code == 4014: @@ -1073,7 +1073,7 @@ def check(reaction, user): Raises ------- asyncio.TimeoutError - If a timeout is provided and it was reached. + Raised if a timeout is provided and reached. Returns -------- @@ -1542,7 +1542,8 @@ async def fetch_user(self, user_id: int, /) -> User: .. note:: - This method is an API call. If you have :attr:`discord.Intents.members` and member cache enabled, consider :meth:`get_user` instead. + This method is an API call. If you have :attr:`discord.Intents.members` and member cache enabled, + consider :meth:`get_user` instead. Parameters ----------- diff --git a/discord/cog.py b/discord/cog.py index 5844c46197..9e3fea898e 100644 --- a/discord/cog.py +++ b/discord/cog.py @@ -224,7 +224,7 @@ def __new__(cls: Type[CogMeta], *args: Any, **kwargs: Any) -> CogMeta: listeners_as_list = [] for listener in listeners.values(): for listener_name in listener.__cog_listener_names__: - # I use __name__ instead of just storing the value so I can inject + # I use __name__ instead of just storing the value, so I can inject # the self attribute when the time comes to add them to the bot listeners_as_list.append((listener_name, listener.__name__)) @@ -347,7 +347,7 @@ def get_listeners(self) -> List[Tuple[str, Callable[..., Any]]]: @classmethod def _get_overridden_method(cls, method: FuncT) -> Optional[FuncT]: - """Return None if the method is not overridden. Otherwise returns the overridden method.""" + """Return None if the method is not overridden. Otherwise, returns the overridden method.""" return getattr(getattr(method, "__func__", method), "__cog_special_method__", method) @classmethod @@ -415,8 +415,12 @@ def bot_check_once(self, ctx: ApplicationContext) -> bool: """A special method that registers as a :meth:`.Bot.check_once` check. - This function **can** be a coroutine and must take a sole parameter, - ``ctx``, to represent the :class:`.Context`. + This function **can** be a coroutine. + + Parameters + ----------- + ctx: :class:`.Context` + The invocation context. """ return True @@ -425,8 +429,12 @@ def bot_check(self, ctx: ApplicationContext) -> bool: """A special method that registers as a :meth:`.Bot.check` check. - This function **can** be a coroutine and must take a sole parameter, - ``ctx``, to represent the :class:`.Context`. + This function **can** be a coroutine. + + Parameters + ----------- + ctx: :class:`.Context` + The invocation context. """ return True @@ -435,8 +443,12 @@ def cog_check(self, ctx: ApplicationContext) -> bool: """A special method that registers as a :func:`~discord.ext.commands.check` for every command and subcommand in this cog. - This function **can** be a coroutine and must take a sole parameter, - ``ctx``, to represent the :class:`.Context`. + This function **can** be a coroutine. + + Parameters + ----------- + ctx: :class:`.Context` + The invocation context. """ return True @@ -664,9 +676,9 @@ def cogs(self) -> Mapping[str, Cog]: def _remove_module_references(self, name: str) -> None: # find all references to the module # remove the cogs registered from the module - for cogname, cog in self.__cogs.copy().items(): + for cog_name, cog in self.__cogs.copy().items(): if _is_submodule(name, cog.__module__): - self.remove_cog(cogname) + self.remove_cog(cog_name) # remove all the commands from the module if self._supports_prefixed_commands: @@ -766,7 +778,7 @@ def load_extension( ----------- name: :class:`str` The extension or folder name to load. It must be dot separated - like regular Python imports if accessing a sub-module. e.g. + like regular Python imports if accessing a submodule. e.g. ``foo.test`` if you want to import ``foo/test.py``. package: Optional[:class:`str`] The package name to resolve relative imports with. @@ -874,7 +886,7 @@ def load_extensions( ----------- names: :class:`str` The extension or folder names to load. It must be dot separated - like regular Python imports if accessing a sub-module. e.g. + like regular Python imports if accessing a submodule. e.g. ``foo.test`` if you want to import ``foo/test.py``. package: Optional[:class:`str`] The package name to resolve relative imports with. @@ -947,7 +959,7 @@ def unload_extension(self, name: str, *, package: Optional[str] = None) -> None: ------------ name: :class:`str` The extension name to unload. It must be dot separated like - regular Python imports if accessing a sub-module. e.g. + regular Python imports if accessing a submodule. e.g. ``foo.test`` if you want to import ``foo/test.py``. package: Optional[:class:`str`] The package name to resolve relative imports with. @@ -979,13 +991,13 @@ def reload_extension(self, name: str, *, package: Optional[str] = None) -> None: This replaces the extension with the same extension, only refreshed. This is equivalent to a :meth:`unload_extension` followed by a :meth:`load_extension` except done in an atomic way. That is, if an operation fails mid-reload then - the bot will roll-back to the prior working state. + the bot will roll back to the prior working state. Parameters ------------ name: :class:`str` The extension name to reload. It must be dot separated like - regular Python imports if accessing a sub-module. e.g. + regular Python imports if accessing a submodule. e.g. ``foo.test`` if you want to import ``foo/test.py``. package: Optional[:class:`str`] The package name to resolve relative imports with. diff --git a/discord/colour.py b/discord/colour.py index 010c8cfa63..2c5a9f267f 100644 --- a/discord/colour.py +++ b/discord/colour.py @@ -115,7 +115,7 @@ def b(self) -> int: def to_rgb(self) -> Tuple[int, int, int]: """Tuple[:class:`int`, :class:`int`, :class:`int`]: Returns an (r, g, b) tuple representing the colour.""" - return (self.r, self.g, self.b) + return self.r, self.g, self.b @classmethod def from_rgb(cls: Type[CT], r: int, g: int, b: int) -> CT: @@ -332,10 +332,12 @@ def nitro_pink(cls: Type[CT]) -> CT: @classmethod def embed_background(cls: Type[CT], theme: str = "dark") -> CT: - """A factory method that returns a :class:`Color` corresponding to the embed colors on discord clients, with a value of - ``0x2F3136`` (dark) - ``0xf2f3f5`` (light) - ``0x000000`` (amoled). + """A factory method that returns a :class:`Color` corresponding to the + embed colors on discord clients, with a value of: + + - ``0x2F3136`` (dark) + - ``0xf2f3f5`` (light) + - ``0x000000`` (amoled). .. versionadded:: 2.0 diff --git a/discord/commands/context.py b/discord/commands/context.py index b3576c32d7..51cfab5ec6 100644 --- a/discord/commands/context.py +++ b/discord/commands/context.py @@ -24,7 +24,7 @@ """ from __future__ import annotations -from typing import TYPE_CHECKING, Dict, List, Optional, TypeVar, Union +from typing import TYPE_CHECKING, Any, Dict, List, Optional, TypeVar, Union import discord.abc from discord.interactions import InteractionMessage, InteractionResponse, Interaction @@ -144,27 +144,37 @@ def channel(self) -> Optional[InteractionChannel]: @cached_property def channel_id(self) -> Optional[int]: - """:class:`int`: Returns the ID of the channel associated with this context's command. Shorthand for :attr:`.Interaction.channel.id`.""" + """:class:`int`: Returns the ID of the channel associated with this context's command. + Shorthand for :attr:`.Interaction.channel_id`. + """ return self.interaction.channel_id @cached_property def guild(self) -> Optional[Guild]: - """Optional[:class:`.Guild`]: Returns the guild associated with this context's command. Shorthand for :attr:`.Interaction.guild`.""" + """Optional[:class:`.Guild`]: Returns the guild associated with this context's command. + Shorthand for :attr:`.Interaction.guild`. + """ return self.interaction.guild @cached_property def guild_id(self) -> Optional[int]: - """:class:`int`: Returns the ID of the guild associated with this context's command. Shorthand for :attr:`.Interaction.guild.id`.""" + """:class:`int`: Returns the ID of the guild associated with this context's command. + Shorthand for :attr:`.Interaction.guild_id`. + """ return self.interaction.guild_id @cached_property def locale(self) -> Optional[str]: - """:class:`str`: Returns the locale of the guild associated with this context's command. Shorthand for :attr:`.Interaction.locale`.""" + """:class:`str`: Returns the locale of the guild associated with this context's command. + Shorthand for :attr:`.Interaction.locale`. + """ return self.interaction.locale @cached_property def guild_locale(self) -> Optional[str]: - """:class:`str`: Returns the locale of the guild associated with this context's command. Shorthand for :attr:`.Interaction.guild_locale`.""" + """:class:`str`: Returns the locale of the guild associated with this context's command. + Shorthand for :attr:`.Interaction.guild_locale`. + """ return self.interaction.guild_locale @cached_property @@ -181,19 +191,25 @@ def me(self) -> Optional[Union[Member, ClientUser]]: @cached_property def message(self) -> Optional[Message]: - """Optional[:class:`.Message`]: Returns the message sent with this context's command. Shorthand for :attr:`.Interaction.message`, if applicable.""" + """Optional[:class:`.Message`]: Returns the message sent with this context's command. + Shorthand for :attr:`.Interaction.message`, if applicable. + """ return self.interaction.message @cached_property def user(self) -> Optional[Union[Member, User]]: - """Union[:class:`.Member`, :class:`.User`]: Returns the user that sent this context's command. Shorthand for :attr:`.Interaction.user`.""" + """Union[:class:`.Member`, :class:`.User`]: Returns the user that sent this context's command. + Shorthand for :attr:`.Interaction.user`. + """ return self.interaction.user author: Optional[Union[Member, User]] = user @property def voice_client(self) -> Optional[VoiceProtocol]: - """Optional[:class:`.VoiceProtocol`]: Returns the voice client associated with this context's command. Shorthand for :attr:`.Interaction.guild.voice_client`, if applicable.""" + """Optional[:class:`.VoiceProtocol`]: Returns the voice client associated with this context's command. + Shorthand for :attr:`Interaction.guild.voice_client<~discord.Guild.voice_client>`, if applicable. + """ if self.interaction.guild is None: return None @@ -201,18 +217,20 @@ def voice_client(self) -> Optional[VoiceProtocol]: @cached_property def response(self) -> InteractionResponse: - """:class:`.InteractionResponse`: Returns the response object associated with this context's command. Shorthand for :attr:`.Interaction.response`.""" + """:class:`.InteractionResponse`: Returns the response object associated with this context's command. + Shorthand for :attr:`.Interaction.response`.""" return self.interaction.response @property - def selected_options(self) -> Optional[List[Dict]]: + def selected_options(self) -> Optional[List[Dict[str, Any]]]: """The options and values that were selected by the user when sending the command. Returns ------- - Optional[List[Dict]] - A dictionary containing the options and values that were selected by the user when the command was processed, if applicable. - Returns ``None`` if the command has not yet been invoked, or if there are no options defined for that command. + Optional[List[Dict[:class:`str`, Any]]] + A dictionary containing the options and values that were selected by the user when the command + was processed, if applicable. Returns ``None`` if the command has not yet been invoked, + or if there are no options defined for that command. """ return self.interaction.data.get("options", None) @@ -245,7 +263,7 @@ def send_modal(self) -> Callable[..., Awaitable[Interaction]]: async def respond(self, *args, **kwargs) -> Union[Interaction, WebhookMessage]: """|coro| - Sends either a response or a message using the followup webhook depending determined by whether the interaction + Sends either a response or a message using the followup webhook determined by whether the interaction has been responded to or not. Returns @@ -288,7 +306,7 @@ def defer(self) -> Callable[..., Awaitable[None]]: @property def followup(self) -> Webhook: - """:class:`Webhook`: Returns the follow up webhook for follow up interactions.""" + """:class:`Webhook`: Returns the followup webhook for followup interactions.""" return self.interaction.followup async def delete(self, *, delay: Optional[float] = None) -> None: @@ -322,7 +340,9 @@ def edit(self) -> Callable[..., Awaitable[InteractionMessage]]: @property def cog(self) -> Optional[Cog]: - """Optional[:class:`.Cog`]: Returns the cog associated with this context's command. ``None`` if it does not exist.""" + """Optional[:class:`.Cog`]: Returns the cog associated with this context's command. + ``None`` if it does not exist. + """ if self.command is None: return None @@ -348,7 +368,7 @@ class AutocompleteContext: The option the user is currently typing. value: :class:`.str` The content of the focused option. - options: :class:`.dict` + options: Dict[:class:`str`, Any] A name to value mapping of the options that the user has selected before this option. """ @@ -365,7 +385,9 @@ def __init__(self, bot: Bot, interaction: Interaction): @property def cog(self) -> Optional[Cog]: - """Optional[:class:`.Cog`]: Returns the cog associated with this context's command. ``None`` if it does not exist.""" + """Optional[:class:`.Cog`]: Returns the cog associated with this context's command. + ``None`` if it does not exist. + """ if self.command is None: return None diff --git a/discord/commands/core.py b/discord/commands/core.py index 04e148817d..e0d2022aed 100644 --- a/discord/commands/core.py +++ b/discord/commands/core.py @@ -300,7 +300,7 @@ def is_on_cooldown(self, ctx: ApplicationContext) -> bool: Parameters ----------- ctx: :class:`.ApplicationContext` - The invocation context to use when checking the commands cooldown status. + The invocation context to use when checking the command's cooldown status. Returns -------- @@ -364,7 +364,7 @@ async def can_run(self, ctx: ApplicationContext) -> bool: predicates = self.checks if self.parent is not None: - # parent checks should be ran first + # parent checks should be run first predicates = self.parent.checks + predicates if not predicates: @@ -1288,8 +1288,7 @@ def __init__(self, func: Callable, *args, **kwargs) -> None: self.name_localizations: Optional[Dict[str, str]] = kwargs.get("name_localizations", None) - # Discord API doesn't support setting descriptions for context menu commands - # so it must be empty + # Discord API doesn't support setting descriptions for context menu commands, so it must be empty self.description = "" if not isinstance(self.name, str): raise TypeError("Name of a command must be a string.") @@ -1558,7 +1557,7 @@ def slash_command(**kwargs): Returns -------- - Callable[..., :class:`SlashCommand`] + Callable[..., :class:`.SlashCommand`] A decorator that converts the provided method into a :class:`.SlashCommand`. """ return application_command(cls=SlashCommand, **kwargs) @@ -1571,7 +1570,7 @@ def user_command(**kwargs): Returns -------- - Callable[..., :class:`UserCommand`] + Callable[..., :class:`.UserCommand`] A decorator that converts the provided method into a :class:`.UserCommand`. """ return application_command(cls=UserCommand, **kwargs) @@ -1584,7 +1583,7 @@ def message_command(**kwargs): Returns -------- - Callable[..., :class:`MessageCommand`] + Callable[..., :class:`.MessageCommand`] A decorator that converts the provided method into a :class:`.MessageCommand`. """ return application_command(cls=MessageCommand, **kwargs) @@ -1594,7 +1593,7 @@ def application_command(cls=SlashCommand, **attrs): """A decorator that transforms a function into an :class:`.ApplicationCommand`. More specifically, usually one of :class:`.SlashCommand`, :class:`.UserCommand`, or :class:`.MessageCommand`. The exact class depends on the ``cls`` parameter. - By default the ``description`` attribute is received automatically from the + By default, the ``description`` attribute is received automatically from the docstring of the function and is cleaned up with the use of ``inspect.cleandoc``. If the docstring is ``bytes``, then it is decoded into :class:`str` using utf-8 encoding. @@ -1605,7 +1604,7 @@ def application_command(cls=SlashCommand, **attrs): Parameters ----------- cls: :class:`.ApplicationCommand` - The class to construct with. By default this is :class:`.SlashCommand`. + The class to construct with. By default, this is :class:`.SlashCommand`. You usually do not change this. attrs Keyword arguments to pass into the construction of the class denoted @@ -1615,6 +1614,11 @@ def application_command(cls=SlashCommand, **attrs): ------- TypeError If the function is not a coroutine or is already a command. + + Returns + -------- + Callable[..., :class:`.ApplicationCommand`] + A decorator that converts the provided method into an :class:`.ApplicationCommand`, or subclass of it. """ def decorator(func: Callable) -> cls: @@ -1637,7 +1641,7 @@ def command(**kwargs): Returns -------- - Callable[..., :class:`ApplicationCommand`] + Callable[..., :class:`.ApplicationCommand`] A decorator that converts the provided method into an :class:`.ApplicationCommand`. """ return application_command(**kwargs) diff --git a/discord/commands/options.py b/discord/commands/options.py index 49e80d5ec8..d7c60a3f59 100644 --- a/discord/commands/options.py +++ b/discord/commands/options.py @@ -75,7 +75,9 @@ class ThreadOption: - """Represents a class that can be passed as the input_type for an Option class. + """Represents a class that can be passed as the ``input_type`` for an :class:`Option` class. + + .. versionadded:: 2.0 Parameters ----------- @@ -144,8 +146,9 @@ async def hello( The maximum length of the string that can be entered. Must be between 1 and 6000 (inclusive). Only applies to Options with an input_type of ``str``. autocomplete: Optional[:class:`Any`] - The autocomplete handler for the option. Accepts an iterable of :class:`str`, a callable (sync or async) that takes a - single argument of :class:`AutocompleteContext`, or a coroutine. Must resolve to an iterable of :class:`str`. + The autocomplete handler for the option. Accepts an iterable of :class:`str`, a callable (sync or async) + that takes a single argument of :class:`AutocompleteContext`, or a coroutine. + Must resolve to an iterable of :class:`str`. .. note:: @@ -250,12 +253,14 @@ def __init__(self, input_type: InputType = str, /, description: Optional[str] = if self.min_length is not None: if not isinstance(self.min_length, minmax_length_types): - raise TypeError(f'Expected {minmax_length_typehint} for min_length, got "{type(self.min_length).__name__}"') + raise TypeError(f'Expected {minmax_length_typehint} for min_length,' + f' got "{type(self.min_length).__name__}"') if self.min_length < 0 or self.min_length > 6000: raise AttributeError("min_length must be between 0 and 6000 (inclusive)") if self.max_length is not None: if not isinstance(self.max_length, minmax_length_types): - raise TypeError(f'Expected {minmax_length_typehint} for max_length, got "{type(self.max_length).__name__}"') + raise TypeError(f'Expected {minmax_length_typehint} for max_length,' + f' got "{type(self.max_length).__name__}"') if self.max_length < 1 or self.max_length > 6000: raise AttributeError("max_length must between 1 and 6000 (inclusive)") @@ -330,7 +335,10 @@ def to_dict(self) -> Dict[str, Union[str, int, float]]: def option(name, type=None, **kwargs): - """A decorator that can be used instead of typehinting Option""" + """A decorator that can be used instead of typehinting :class:`Option`. + + .. versionadded:: 2.0 + """ def decorator(func): nonlocal type diff --git a/discord/commands/permissions.py b/discord/commands/permissions.py index 86bd0df63a..e14f9cb715 100644 --- a/discord/commands/permissions.py +++ b/discord/commands/permissions.py @@ -48,7 +48,7 @@ def default_permissions(**perms: bool) -> Callable: Parameters ------------ - perms + **perms: Dict[:class:`str`, :class:`bool`] An argument list of permissions to check for. Example diff --git a/discord/embeds.py b/discord/embeds.py index 07cebbfec4..d3b8f976d2 100644 --- a/discord/embeds.py +++ b/discord/embeds.py @@ -158,7 +158,13 @@ def from_dict(cls: Type[E], data: Mapping[str, Any]) -> E: return self def to_dict(self) -> Dict[str, Union[str, bool]]: - """Converts this EmbedField object into a dict.""" + """Converts this EmbedField object into a dict. + + Returns + -------- + Dict[:class:`str`, Union[:class:`str`, :class:`bool`]] + A dictionary of :class:`str` embed field keys bound to the respective value. + """ return { "name": self.name, "value": self.value, @@ -286,6 +292,11 @@ def from_dict(cls: Type[E], data: Mapping[str, Any]) -> E: ----------- data: :class:`dict` The dictionary to convert into an embed. + + Returns + -------- + :class:`Embed` + The converted embed object. """ # we are bypassing __init__ here since it doesn't apply here self: E = cls.__new__(cls) @@ -341,7 +352,13 @@ def from_dict(cls: Type[E], data: Mapping[str, Any]) -> E: return self def copy(self: E) -> E: - """Returns a shallow copy of the embed.""" + """Creates a shallow copy of the :class:`Embed` object. + + Returns + -------- + :class:`Embed` + The copied embed object. + """ return self.__class__.from_dict(self.to_dict()) def __len__(self) -> int: @@ -818,7 +835,13 @@ def set_field_at(self: E, index: int, *, name: Any, value: Any, inline: bool = T return self def to_dict(self) -> EmbedData: - """Converts this embed object into a dict.""" + """Converts this embed object into a dict. + + Returns + -------- + Dict[:class:`str`, Union[:class:`str`, :class:`int`, :class:`bool`]] + A dictionary of :class:`str` embed keys bound to the respective value. + """ # add in the raw data into the dict result = { diff --git a/discord/emoji.py b/discord/emoji.py index 0b2cf788d3..a73427af8f 100644 --- a/discord/emoji.py +++ b/discord/emoji.py @@ -47,7 +47,7 @@ class Emoji(_EmojiTag, AssetMixin): """Represents a custom emoji. - Depending on the way this object was created, some of the attributes can + Depending on the way this object was created, some attributes can have a value of ``None``. .. container:: operations @@ -131,7 +131,7 @@ def __iter__(self) -> Iterator[Tuple[str, Any]]: if attr[0] != "_": value = getattr(self, attr, None) if value is not None: - yield (attr, value) + yield attr, value def __str__(self) -> str: if self.animated: diff --git a/discord/enums.py b/discord/enums.py index 950d33cbf1..eb0ac79cc5 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -72,6 +72,10 @@ "ScheduledEventLocationType", "InputTextStyle", "SlashCommandOptionType", + "AutoModTriggerType", + "AutoModEventType", + "AutoModActionType", + "AutoModKeywordPresetType", ) diff --git a/discord/errors.py b/discord/errors.py index e4e6fe570e..c3263b5567 100644 --- a/discord/errors.py +++ b/discord/errors.py @@ -208,7 +208,7 @@ class InvalidArgument(ClientException): """Exception that's raised when an argument to a function is invalid some way (e.g. wrong value or wrong type). - This could be considered the analogous of ``ValueError`` and + This could be considered the parallel of ``ValueError`` and ``TypeError`` except inherited from :exc:`ClientException` and thus :exc:`DiscordException`. """ @@ -256,11 +256,11 @@ def __init__( class PrivilegedIntentsRequired(ClientException): - """Exception that's raised when the gateway is requesting privileged intents - but they're not ticked in the developer page yet. + """Exception that's raised when the gateway is requesting privileged intents, but + they're not ticked in the developer page yet. Go to https://discord.com/developers/applications/ and enable the intents - that are required. Currently these are as follows: + that are required. Currently, these are as follows: - :attr:`Intents.members` - :attr:`Intents.presences` diff --git a/discord/ext/bridge/context.py b/discord/ext/bridge/context.py index 5024d370dd..80b2052730 100644 --- a/discord/ext/bridge/context.py +++ b/discord/ext/bridge/context.py @@ -23,7 +23,7 @@ DEALINGS IN THE SOFTWARE. """ from abc import ABC, abstractmethod -from typing import TYPE_CHECKING, Any, Optional, Union +from typing import Any, Optional, Union from discord.commands import ApplicationContext from discord.interactions import Interaction, InteractionMessage diff --git a/discord/ext/commands/bot.py b/discord/ext/commands/bot.py index 121ebdf438..c3af75c236 100644 --- a/discord/ext/commands/bot.py +++ b/discord/ext/commands/bot.py @@ -156,7 +156,7 @@ async def on_command_error(self, context: Context, exception: errors.CommandErro The default command error handler provided by the bot. - By default this prints to :data:`sys.stderr` however it could be + By default, this prints to :data:`sys.stderr` however it could be overridden to have a different implementation. This only fires if you do not specify any listeners for command error. @@ -253,7 +253,7 @@ async def get_context(self, message: Message, *, cls: Type[CXT] = Context) -> CX Returns the invocation context from the message. This is a more low-level counter-part for :meth:`.process_commands` - to allow users more fine grained control over the processing. + to allow users more fine-grained control over the processing. The returned context is not guaranteed to be a valid invocation context, :attr:`.Context.valid` must be checked to make sure it is. @@ -430,9 +430,9 @@ class Bot(BotBase, discord.Bot): when passing an empty string, it should always be last as no prefix after it will be matched. case_insensitive: :class:`bool` - Whether the commands should be case insensitive. Defaults to ``False``. This + Whether the commands should be case-insensitive. Defaults to ``False``. This attribute does not carry over to groups. You must set it to every group if - you require group commands to be case insensitive as well. + you require group commands to be case-insensitive as well. help_command: Optional[:class:`.HelpCommand`] The help command implementation to use. This can be dynamically set at runtime. To remove the help command pass ``None``. For more diff --git a/discord/ext/commands/context.py b/discord/ext/commands/context.py index de2097f3f3..019e7b8bee 100644 --- a/discord/ext/commands/context.py +++ b/discord/ext/commands/context.py @@ -66,7 +66,7 @@ class Context(discord.abc.Messageable, Generic[BotT]): r"""Represents the context in which a command is being invoked under. - This class contains a lot of meta data to help you understand more about + This class contains a lot of metadata to help you understand more about the invocation context. This class is not created manually and is instead passed around to commands as the first parameter. @@ -264,7 +264,7 @@ def clean_prefix(self) -> str: return "" user = self.me - # this breaks if the prefix mention is not the bot itself but I + # this breaks if the prefix mention is not the bot itself, but I # consider this to be an *incredibly* strange use case. I'd rather go # for this common use case rather than waste performance for the # odd one. @@ -273,7 +273,8 @@ def clean_prefix(self) -> str: @property def cog(self) -> Optional[Cog]: - """Optional[:class:`.Cog`]: Returns the cog associated with this context's command. None if it does not exist.""" + """Optional[:class:`.Cog`]: Returns the cog associated with this context's command. + None if it does not exist.""" if self.command is None: return None @@ -281,7 +282,8 @@ def cog(self) -> Optional[Cog]: @discord.utils.cached_property def guild(self) -> Optional[Guild]: - """Optional[:class:`.Guild`]: Returns the guild associated with this context's command. None if not available.""" + """Optional[:class:`.Guild`]: Returns the guild associated with this context's command. + None if not available.""" return self.message.guild @discord.utils.cached_property diff --git a/discord/ext/commands/converter.py b/discord/ext/commands/converter.py index 1de137b2ce..5ec807f417 100644 --- a/discord/ext/commands/converter.py +++ b/discord/ext/commands/converter.py @@ -276,8 +276,8 @@ class UserConverter(IDConverter[discord.User]): Raise :exc:`.UserNotFound` instead of generic :exc:`.BadArgument` .. versionchanged:: 1.6 - This converter now lazily fetches users from the HTTP APIs if an ID is passed - and it's not available in cache. + This converter now lazily fetches users from the HTTP APIs if an ID is + passed, and it's not available in cache. """ async def convert(self, ctx: Context, argument: str) -> discord.User: @@ -393,7 +393,8 @@ class MessageConverter(IDConverter[discord.Message]): 3. Lookup by message URL .. versionchanged:: 1.5 - Raise :exc:`.ChannelNotFound`, :exc:`.MessageNotFound` or :exc:`.ChannelNotReadable` instead of generic :exc:`.BadArgument` + Raise :exc:`.ChannelNotFound`, :exc:`.MessageNotFound` or :exc:`.ChannelNotReadable` + instead of generic :exc:`.BadArgument` """ async def convert(self, ctx: Context, argument: str) -> discord.Message: @@ -1145,8 +1146,8 @@ async def run_converters(ctx: Context, converter, argument: str, param: inspect. _NoneType = type(None) union_args = converter.__args__ for conv in union_args: - # if we got to this part in the code, then the previous conversions have failed - # so we should just undo the view, return the default, and allow parsing to continue + # if we got to this part in the code, then the previous conversions have failed, so + # we should just undo the view, return the default, and allow parsing to continue # with the other parameters if conv is _NoneType and param.kind != param.VAR_POSITIONAL: ctx.view.undo() diff --git a/discord/ext/commands/cooldowns.py b/discord/ext/commands/cooldowns.py index 7fb348833e..c22121c63e 100644 --- a/discord/ext/commands/cooldowns.py +++ b/discord/ext/commands/cooldowns.py @@ -67,13 +67,13 @@ def get_key(self, msg: Message) -> Any: elif self is BucketType.channel: return msg.channel.id elif self is BucketType.member: - return ((msg.guild and msg.guild.id), msg.author.id) + return (msg.guild and msg.guild.id), msg.author.id elif self is BucketType.category: return (msg.channel.category or msg.channel).id # type: ignore elif self is BucketType.role: # we return the channel id of a private-channel as there are only roles in guilds # and that yields the same result as for a guild with only the @everyone role - # NOTE: PrivateChannel doesn't actually have an id attribute but we assume we are + # NOTE: PrivateChannel doesn't actually have an id attribute, but we assume we are # receiving a DMChannel or GroupChannel which inherit from PrivateChannel and do return (msg.channel if isinstance(msg.channel, PrivateChannel) else msg.author.top_role).id # type: ignore @@ -231,7 +231,7 @@ def _bucket_key(self, msg: Message) -> Any: def _verify_cache_integrity(self, current: Optional[float] = None) -> None: # we want to delete all cache objects that haven't been used # in a cooldown window. e.g. if we have a command that has a - # cooldown of 60s and it has not been used in 60s then that key should be deleted + # cooldown of 60s, and it has not been used in 60s then that key should be deleted current = current or time.time() dead_keys = [k for k, v in self._cache.items() if current > v._last + v.per] for k in dead_keys: diff --git a/discord/ext/commands/core.py b/discord/ext/commands/core.py index 582c6aa73b..e3c2b5adfd 100644 --- a/discord/ext/commands/core.py +++ b/discord/ext/commands/core.py @@ -589,7 +589,7 @@ async def transform(self, ctx: Context, param: inspect.Parameter) -> Any: view.skip_ws() # The greedy converter is simple -- it keeps going until it fails in which case, - # it undos the view ready for the next parameter to use instead + # it undoes the view ready for the next parameter to use instead if isinstance(converter, Greedy): if param.kind in (param.POSITIONAL_OR_KEYWORD, param.POSITIONAL_ONLY): return await self._transform_greedy_pos(ctx, param, required, converter.converter) @@ -888,7 +888,7 @@ def is_on_cooldown(self, ctx: Context) -> bool: Parameters ----------- ctx: :class:`.Context` - The invocation context to use when checking the commands cooldown status. + The invocation context to use when checking the command's cooldown status. Returns -------- @@ -1108,7 +1108,7 @@ def signature(self) -> str: if origin is Literal: name = "|".join(f'"{v}"' if isinstance(v, str) else str(v) for v in annotation.__args__) if param.default is not param.empty: - # We don't want None or '' to trigger the [name=value] case and instead it should + # We don't want None or '' to trigger the [name=value] case, and instead it should # do [name] since [name=None] or [name=] are not exactly useful for the user. should_print = param.default if isinstance(param.default, str) else param.default is not None if should_print: @@ -1199,7 +1199,7 @@ class GroupMixin(Generic[CogT]): A mapping of command name to :class:`.Command` objects. case_insensitive: :class:`bool` - Whether the commands should be case insensitive. Defaults to ``False``. + Whether the commands should be case-insensitive. Defaults to ``False``. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -1288,7 +1288,7 @@ def remove_command(self, name: str) -> Optional[Command[CogT, Any, Any]]: return None if name in command.aliases: - # we're removing an alias so we don't want to remove the rest + # we're removing an alias, so we don't want to remove the rest return command # we're not removing the alias so let's delete the rest of them. @@ -1389,7 +1389,8 @@ def command( *args: Any, **kwargs: Any, ) -> Callable[ - [Callable[ + [ + Callable[ [Concatenate[ContextT, P]], Coro[Any] ] @@ -1502,7 +1503,7 @@ class Group(GroupMixin[CogT], Command[CogT, P, T]): that the checks and the parsing dictated by its parameters will be executed. Defaults to ``False``. case_insensitive: :class:`bool` - Indicates if the group's commands should be case insensitive. + Indicates if the group's commands should be case-insensitive. Defaults to ``False``. """ @@ -1675,10 +1676,10 @@ def command( Parameters ----------- name: :class:`str` - The name to create the command with. By default this uses the + The name to create the command with. By default, this uses the function name unchanged. cls - The class to construct with. By default this is :class:`.Command`. + The class to construct with. By default, this is :class:`.Command`. You usually do not change this. attrs Keyword arguments to pass into the construction of the class denoted @@ -2060,7 +2061,7 @@ def bot_has_any_role(*items: int) -> Callable[[T], T]: .. versionchanged:: 1.1 Raise :exc:`.BotMissingAnyRole` or :exc:`.NoPrivateMessage` - instead of generic checkfailure + instead of generic :exc:`.CheckFailure`. """ def predicate(ctx): @@ -2431,14 +2432,14 @@ async def record_usage(ctx): @bot.command() @commands.before_invoke(record_usage) async def who(ctx): # Output: used who at