diff --git a/changelog/1396.misc.rst b/changelog/1396.misc.rst new file mode 100644 index 0000000000..9dec064073 --- /dev/null +++ b/changelog/1396.misc.rst @@ -0,0 +1 @@ +Update all type hints across the source code to use PEP 604 style (``A | B`` instead of ``Union[A, B]``, and ``A | None`` instead of ``Optional[A]``). diff --git a/disnake/__main__.py b/disnake/__main__.py index e1a5d2cdfd..06fac9941f 100644 --- a/disnake/__main__.py +++ b/disnake/__main__.py @@ -5,7 +5,7 @@ import platform import sys from pathlib import Path -from typing import List, Tuple, Union +from typing import Union import aiohttp @@ -13,7 +13,7 @@ def show_version() -> None: - entries: List[str] = [] + entries: list[str] = [] sys_ver = sys.version_info entries.append( @@ -399,7 +399,7 @@ def add_newcog_args(subparser) -> None: parser.add_argument("--full", help="add all special methods as well", action="store_true") -def parse_args() -> Tuple[argparse.ArgumentParser, argparse.Namespace]: +def parse_args() -> tuple[argparse.ArgumentParser, argparse.Namespace]: parser = argparse.ArgumentParser(prog="disnake", description="Tools for helping with disnake") parser.add_argument("-v", "--version", action="store_true", help="shows the library version") parser.set_defaults(func=core) diff --git a/disnake/abc.py b/disnake/abc.py index 245a6ff10d..9c04f7376a 100644 --- a/disnake/abc.py +++ b/disnake/abc.py @@ -5,17 +5,13 @@ import asyncio import copy from abc import ABC +from collections.abc import Mapping, Sequence from typing import ( TYPE_CHECKING, Any, Callable, - Dict, - List, - Mapping, Optional, Protocol, - Sequence, - Tuple, TypeVar, Union, cast, @@ -264,7 +260,7 @@ class GuildChannel(ABC): category_id: Optional[int] _flags: int _state: ConnectionState - _overwrites: List[_Overwrites] + _overwrites: list[_Overwrites] if TYPE_CHECKING: @@ -279,7 +275,7 @@ def __str__(self) -> str: def _sorting_bucket(self) -> int: raise NotImplementedError - def _update(self, guild: Guild, data: Dict[str, Any]) -> None: + def _update(self, guild: Guild, data: dict[str, Any]) -> None: raise NotImplementedError async def _move( @@ -297,7 +293,7 @@ async def _move( http = self._state.http bucket = self._sorting_bucket channels = [c for c in self.guild.channels if c._sorting_bucket == bucket] - channels = cast("List[GuildChannel]", channels) + channels = cast("list[GuildChannel]", channels) channels.sort(key=lambda c: c.position) @@ -314,7 +310,7 @@ async def _move( # add ourselves at our designated position channels.insert(index, self) - payload: List[ChannelPositionUpdatePayload] = [] + payload: list[ChannelPositionUpdatePayload] = [] for index, c in enumerate(channels): d: ChannelPositionUpdatePayload = {"id": c.id, "position": index} if parent_id is not MISSING and c.id == self.id: @@ -380,7 +376,7 @@ async def _edit( lock_permissions: bool = bool(sync_permissions) - overwrites_payload: List[PermissionOverwritePayload] = MISSING + overwrites_payload: list[PermissionOverwritePayload] = MISSING if position is not MISSING: await self._move( @@ -430,7 +426,7 @@ async def _edit( else: flags_payload = MISSING - available_tags_payload: List[PartialForumTagPayload] = MISSING + available_tags_payload: list[PartialForumTagPayload] = MISSING if available_tags is not MISSING: available_tags_payload = [tag.to_dict() for tag in available_tags] @@ -455,7 +451,7 @@ async def _edit( if default_layout is not MISSING: default_layout_payload = try_enum_to_int(default_layout) - options: Dict[str, Any] = { + options: dict[str, Any] = { "name": name, "parent_id": parent_id, "topic": topic, @@ -507,11 +503,11 @@ def _fill_overwrites(self, data: GuildChannelPayload) -> None: tmp[everyone_index], tmp[0] = tmp[0], tmp[everyone_index] @property - def changed_roles(self) -> List[Role]: + def changed_roles(self) -> list[Role]: """:class:`list`\\[:class:`.Role`]: Returns a list of roles that have been overridden from their default values in the :attr:`.Guild.roles` attribute. """ - ret: List[Role] = [] + ret: list[Role] = [] g = self.guild for overwrite in filter(lambda o: o.is_role(), self._overwrites): role = g.get_role(overwrite.id) @@ -564,7 +560,7 @@ def overwrites_for(self, obj: Union[Role, User]) -> PermissionOverwrite: return PermissionOverwrite() @property - def overwrites(self) -> Dict[Union[Role, Member], PermissionOverwrite]: + def overwrites(self) -> dict[Union[Role, Member], PermissionOverwrite]: """Returns all of the channel's overwrites. This is returned as a dictionary where the key contains the target which @@ -1043,7 +1039,7 @@ async def set_permissions( async def _clone_impl( self, - base_attrs: Dict[str, Any], + base_attrs: dict[str, Any], *, name: Optional[str] = None, category: Optional[Snowflake] = MISSING, @@ -1052,7 +1048,7 @@ async def _clone_impl( ) -> Self: # if the overwrites are MISSING, defaults to the # original permissions of the channel - overwrites_payload: List[PermissionOverwritePayload] + overwrites_payload: list[PermissionOverwritePayload] if overwrites is not MISSING: if not isinstance(overwrites, dict): msg = "overwrites parameter expects a dict." @@ -1259,7 +1255,7 @@ async def move(self, **kwargs: Any) -> None: ] channels.sort(key=lambda c: (c.position, c.id)) - channels = cast("List[GuildChannel]", channels) + channels = cast("list[GuildChannel]", channels) try: # Try to remove ourselves from the channel list @@ -1283,7 +1279,7 @@ async def move(self, **kwargs: Any) -> None: raise ValueError(msg) channels.insert(max((index + offset), 0), self) - payload: List[ChannelPositionUpdatePayload] = [] + payload: list[ChannelPositionUpdatePayload] = [] lock_permissions = kwargs.get("sync_permissions", False) reason = kwargs.get("reason") for index, channel in enumerate(channels): @@ -1389,7 +1385,7 @@ async def create_invite( invite.guild_scheduled_event = guild_scheduled_event return invite - async def invites(self) -> List[Invite]: + async def invites(self) -> list[Invite]: """|coro| Returns a list of all active instant invites from this channel. @@ -1465,7 +1461,7 @@ async def send( *, tts: bool = ..., embed: Embed = ..., - files: List[File] = ..., + files: list[File] = ..., stickers: Sequence[Union[GuildSticker, StandardSticker, StickerItem]] = ..., delete_after: float = ..., nonce: Union[str, int] = ..., @@ -1485,7 +1481,7 @@ async def send( content: Optional[str] = ..., *, tts: bool = ..., - embeds: List[Embed] = ..., + embeds: list[Embed] = ..., file: File = ..., stickers: Sequence[Union[GuildSticker, StandardSticker, StickerItem]] = ..., delete_after: float = ..., @@ -1506,8 +1502,8 @@ async def send( content: Optional[str] = ..., *, tts: bool = ..., - embeds: List[Embed] = ..., - files: List[File] = ..., + embeds: list[Embed] = ..., + files: list[File] = ..., stickers: Sequence[Union[GuildSticker, StandardSticker, StickerItem]] = ..., delete_after: float = ..., nonce: Union[str, int] = ..., @@ -1527,9 +1523,9 @@ async def send( *, tts: bool = False, embed: Optional[Embed] = None, - embeds: Optional[List[Embed]] = None, + embeds: Optional[list[Embed]] = None, file: Optional[File] = None, - files: Optional[List[File]] = None, + files: Optional[list[File]] = None, stickers: Optional[Sequence[Union[GuildSticker, StandardSticker, StickerItem]]] = None, delete_after: Optional[float] = None, nonce: Optional[Union[str, int]] = None, @@ -2033,10 +2029,10 @@ class Connectable(Protocol): guild: Guild id: int - def _get_voice_client_key(self) -> Tuple[int, str]: + def _get_voice_client_key(self) -> tuple[int, str]: raise NotImplementedError - def _get_voice_state_pair(self) -> Tuple[int, int]: + def _get_voice_state_pair(self) -> tuple[int, int]: raise NotImplementedError async def connect( diff --git a/disnake/activity.py b/disnake/activity.py index b66fe5d129..04c0be1843 100644 --- a/disnake/activity.py +++ b/disnake/activity.py @@ -3,7 +3,7 @@ from __future__ import annotations import datetime -from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Union, overload +from typing import TYPE_CHECKING, Any, Literal, Optional, Union, overload from .asset import Asset from .colour import Colour @@ -339,7 +339,7 @@ def __init__( party: Optional[ActivityParty] = None, application_id: Optional[Union[str, int]] = None, flags: Optional[int] = None, - buttons: Optional[List[str]] = None, + buttons: Optional[list[str]] = None, emoji: Optional[Union[PartialEmojiPayload, ActivityEmojiPayload]] = None, id: Optional[str] = None, platform: Optional[str] = None, @@ -360,7 +360,7 @@ def __init__( self.name: Optional[str] = name self.url: Optional[str] = url self.flags: int = flags or 0 - self.buttons: List[str] = buttons or [] + self.buttons: list[str] = buttons or [] # undocumented fields: self.id: Optional[str] = id @@ -398,8 +398,8 @@ def __repr__(self) -> str: inner = " ".join(f"{k!s}={v!r}" for k, v in attrs) return f"" - def to_dict(self) -> Dict[str, Any]: - ret: Dict[str, Any] = {} + def to_dict(self) -> dict[str, Any]: + ret: dict[str, Any] = {} for attr in self.__slots__: value = getattr(self, attr, None) if value is None: @@ -608,8 +608,8 @@ def twitch_name(self) -> Optional[str]: name = self.assets["large_image"] return name[7:] if name[:7] == "twitch:" else None - def to_dict(self) -> Dict[str, Any]: - ret: Dict[str, Any] = { + def to_dict(self) -> dict[str, Any]: + ret: dict[str, Any] = { "type": ActivityType.streaming.value, "name": str(self.name), "url": str(self.url), @@ -700,7 +700,7 @@ def color(self) -> Colour: """ return self.colour - def to_dict(self) -> Dict[str, Any]: + def to_dict(self) -> dict[str, Any]: return { "flags": 48, # SYNC | PLAY "name": "Spotify", @@ -744,7 +744,7 @@ def title(self) -> str: return self._details @property - def artists(self) -> List[str]: + def artists(self) -> list[str]: """:class:`list`\\[:class:`str`]: The artists of the song being played.""" return self._state.split("; ") diff --git a/disnake/app_commands.py b/disnake/app_commands.py index ae4f323c63..74fef8d958 100644 --- a/disnake/app_commands.py +++ b/disnake/app_commands.py @@ -5,7 +5,8 @@ import math import re from abc import ABC -from typing import TYPE_CHECKING, ClassVar, List, Mapping, Optional, Sequence, Tuple, Union, cast +from collections.abc import Mapping, Sequence +from typing import TYPE_CHECKING, ClassVar, Optional, Union, cast from .enums import ( ApplicationCommandPermissionType, @@ -266,8 +267,8 @@ def __init__( type: Optional[Union[OptionType, int]] = None, required: bool = False, choices: Optional[Choices] = None, - options: Optional[List[Option]] = None, - channel_types: Optional[List[ChannelType]] = None, + options: Optional[list[Option]] = None, + channel_types: Optional[list[ChannelType]] = None, autocomplete: bool = False, min_value: Optional[float] = None, max_value: Optional[float] = None, @@ -285,7 +286,7 @@ def __init__( self.type: OptionType = enum_if_int(OptionType, type) or OptionType.string self.required: bool = required - self.options: List[Option] = options or [] + self.options: list[Option] = options or [] if min_value and self.type is OptionType.integer: min_value = math.ceil(min_value) @@ -302,9 +303,9 @@ def __init__( msg = "channel_types must be a list of `ChannelType`s" raise TypeError(msg) - self.channel_types: List[ChannelType] = channel_types or [] + self.channel_types: list[ChannelType] = channel_types or [] - self.choices: List[OptionChoice] = [] + self.choices: list[OptionChoice] = [] if choices is not None: if autocomplete: msg = "can not specify both choices and autocomplete args" @@ -399,8 +400,8 @@ def add_option( type: Optional[OptionType] = None, required: bool = False, choices: Optional[Choices] = None, - options: Optional[List[Option]] = None, - channel_types: Optional[List[ChannelType]] = None, + options: Optional[list[Option]] = None, + channel_types: Optional[list[ChannelType]] = None, autocomplete: bool = False, min_value: Optional[float] = None, max_value: Optional[float] = None, @@ -512,7 +513,7 @@ class ApplicationCommand(ABC): # noqa: B024 # this will get refactored eventua .. versionadded:: 2.10 """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( "type", "name", "default_member_permissions", @@ -708,15 +709,15 @@ def to_dict(self) -> EditApplicationCommandPayload: "nsfw": self.nsfw, } - install_types: Optional[List[ApplicationIntegrationTypePayload]] = ( - cast("List[ApplicationIntegrationTypePayload]", self._install_types_with_default.values) + install_types: Optional[list[ApplicationIntegrationTypePayload]] = ( + cast("list[ApplicationIntegrationTypePayload]", self._install_types_with_default.values) if self._install_types_with_default is not None else None ) data["integration_types"] = install_types - contexts: Optional[List[InteractionContextTypePayload]] = ( - cast("List[InteractionContextTypePayload]", self._contexts_with_default.values) + contexts: Optional[list[InteractionContextTypePayload]] = ( + cast("list[InteractionContextTypePayload]", self._contexts_with_default.values) if self._contexts_with_default is not None else None ) @@ -736,7 +737,7 @@ def localize(self, store: LocalizationProtocol) -> None: class _APIApplicationCommandMixin: - __repr_attributes__: ClassVar[Tuple[str, ...]] = ("id",) + __repr_attributes__: ClassVar[tuple[str, ...]] = ("id",) def _update_common(self, data: ApplicationCommandPayload) -> None: if not isinstance(self, ApplicationCommand): @@ -787,7 +788,7 @@ class UserCommand(ApplicationCommand): .. versionadded:: 2.10 """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = tuple( + __repr_attributes__: ClassVar[tuple[str, ...]] = tuple( n for n in ApplicationCommand.__repr_attributes__ if n != "type" ) @@ -853,7 +854,7 @@ class APIUserCommand(UserCommand, _APIApplicationCommandMixin): Autoincrementing version identifier updated during substantial record changes. """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( *UserCommand.__repr_attributes__, *_APIApplicationCommandMixin.__repr_attributes__, ) @@ -916,7 +917,7 @@ class MessageCommand(ApplicationCommand): .. versionadded:: 2.10 """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = tuple( + __repr_attributes__: ClassVar[tuple[str, ...]] = tuple( n for n in ApplicationCommand.__repr_attributes__ if n != "type" ) @@ -982,7 +983,7 @@ class APIMessageCommand(MessageCommand, _APIApplicationCommandMixin): Autoincrementing version identifier updated during substantial record changes. """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( *MessageCommand.__repr_attributes__, *_APIApplicationCommandMixin.__repr_attributes__, ) @@ -1055,7 +1056,7 @@ class SlashCommand(ApplicationCommand): The list of options the slash command has. """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( *tuple(n for n in ApplicationCommand.__repr_attributes__ if n != "type"), "description", "options", @@ -1065,7 +1066,7 @@ def __init__( self, name: LocalizedRequired, description: LocalizedRequired, - options: Optional[List[Option]] = None, + options: Optional[list[Option]] = None, dm_permission: Optional[bool] = None, # deprecated default_member_permissions: Optional[Union[Permissions, int]] = None, nsfw: Optional[bool] = None, @@ -1087,7 +1088,7 @@ def __init__( self.description: str = desc_loc.string self.description_localizations: LocalizationValue = desc_loc.localizations - self.options: List[Option] = options or [] + self.options: list[Option] = options or [] def __eq__(self, other) -> bool: return ( @@ -1105,7 +1106,7 @@ def add_option( required: bool = False, choices: Optional[Choices] = None, options: Optional[list] = None, - channel_types: Optional[List[ChannelType]] = None, + channel_types: Optional[list[ChannelType]] = None, autocomplete: bool = False, min_value: Optional[float] = None, max_value: Optional[float] = None, @@ -1203,7 +1204,7 @@ class APISlashCommand(SlashCommand, _APIApplicationCommandMixin): Autoincrementing version identifier updated during substantial record changes. """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( *SlashCommand.__repr_attributes__, *_APIApplicationCommandMixin.__repr_attributes__, ) @@ -1319,7 +1320,7 @@ def __init__( self.application_id: int = int(data["application_id"]) self.guild_id: int = int(data["guild_id"]) - self.permissions: List[ApplicationCommandPermissions] = [ + self.permissions: list[ApplicationCommandPermissions] = [ ApplicationCommandPermissions(data=elem, guild_id=self.guild_id) for elem in data["permissions"] ] diff --git a/disnake/appinfo.py b/disnake/appinfo.py index c3cb60b3dc..bfd4bfac20 100644 --- a/disnake/appinfo.py +++ b/disnake/appinfo.py @@ -2,7 +2,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Dict, List, Optional, Sequence, cast +from collections.abc import Sequence +from typing import TYPE_CHECKING, Optional, cast from . import utils from .asset import Asset, AssetBytes @@ -60,7 +61,7 @@ class InstallParams: def __init__( self, *, - scopes: List[str], + scopes: list[str], permissions: Permissions = MISSING, ) -> None: self.scopes = scopes @@ -332,7 +333,7 @@ def __init__(self, state: ConnectionState, data: AppInfoPayload) -> None: self.name: str = data["name"] self.description: str = data["description"] self._icon: Optional[str] = data["icon"] - self.rpc_origins: List[str] = data.get("rpc_origins") or [] + self.rpc_origins: list[str] = data.get("rpc_origins") or [] self.bot_public: bool = data["bot_public"] self.bot_require_code_grant: bool = data["bot_require_code_grant"] self.owner: User = state.create_user(data["owner"]) @@ -355,14 +356,14 @@ def __init__(self, state: ConnectionState, data: AppInfoPayload) -> None: self.flags: Optional[ApplicationFlags] = ( ApplicationFlags._from_value(flags) if flags is not None else None ) - self.tags: Optional[List[str]] = data.get("tags") + self.tags: Optional[list[str]] = data.get("tags") self.install_params: Optional[InstallParams] = ( InstallParams._from_data(data["install_params"], parent=self) if "install_params" in data else None ) self.custom_install_url: Optional[str] = data.get("custom_install_url") - self.redirect_uris: Optional[List[str]] = data.get("redirect_uris") + self.redirect_uris: Optional[list[str]] = data.get("redirect_uris") self.interactions_endpoint_url: Optional[str] = data.get("interactions_endpoint_url") self.role_connections_verification_url: Optional[str] = data.get( "role_connections_verification_url" @@ -371,7 +372,7 @@ def __init__(self, state: ConnectionState, data: AppInfoPayload) -> None: self.event_webhooks_status: ApplicationEventWebhookStatus = try_enum( ApplicationEventWebhookStatus, data.get("event_webhooks_status", 1) ) - self.event_webhooks_types: Optional[List[str]] = data.get("event_webhooks_types") + self.event_webhooks_types: Optional[list[str]] = data.get("event_webhooks_types") self.approximate_guild_count: int = data.get("approximate_guild_count", 0) self.approximate_user_install_count: int = data.get("approximate_user_install_count", 0) self.approximate_user_authorization_count: int = data.get( @@ -379,7 +380,7 @@ def __init__(self, state: ConnectionState, data: AppInfoPayload) -> None: ) # this is a bit of a mess, but there's no better way to expose this data for now - self._install_types_config: Dict[ + self._install_types_config: dict[ ApplicationIntegrationTypeLiteral, InstallTypeConfiguration ] = {} for type_str, config in (data.get("integration_types_config") or {}).items(): @@ -595,7 +596,7 @@ async def edit( fields["install_params"] = install_params.to_dict() if install_params else None if guild_install_type_config is not MISSING or user_install_type_config is not MISSING: - integration_types_config: Dict[str, ApplicationIntegrationTypeConfigurationPayload] = {} + integration_types_config: dict[str, ApplicationIntegrationTypeConfigurationPayload] = {} if guild_install_type_config is MISSING: guild_install_type_config = self.guild_install_type_config @@ -685,7 +686,7 @@ def __init__(self, *, state: ConnectionState, data: PartialAppInfoPayload) -> No self.name: str = data["name"] self._icon: Optional[str] = data.get("icon") self.description: str = data["description"] - self.rpc_origins: Optional[List[str]] = data.get("rpc_origins") + self.rpc_origins: Optional[list[str]] = data.get("rpc_origins") self._summary: str = data.get("summary", "") self.verify_key: str = data["verify_key"] self.terms_of_service_url: Optional[str] = data.get("terms_of_service_url") diff --git a/disnake/asset.py b/disnake/asset.py index cd08550b1a..0ebd2e8885 100644 --- a/disnake/asset.py +++ b/disnake/asset.py @@ -4,7 +4,7 @@ import io import os -from typing import TYPE_CHECKING, Any, Literal, Optional, Tuple, Union +from typing import TYPE_CHECKING, Any, Literal, Optional, Union import yarl @@ -37,7 +37,7 @@ class AssetMixin: url: str _state: Optional[AnyState] - __slots__: Tuple[str, ...] = ("_state",) + __slots__: tuple[str, ...] = ("_state",) async def read(self) -> bytes: """|coro| @@ -191,7 +191,7 @@ class Asset(AssetMixin): Returns the hash of the asset. """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "_url", "_animated", "_key", diff --git a/disnake/audit_logs.py b/disnake/audit_logs.py index cd3384bbc9..02d9874370 100644 --- a/disnake/audit_logs.py +++ b/disnake/audit_logs.py @@ -2,18 +2,13 @@ from __future__ import annotations +from collections.abc import Generator, Mapping from typing import ( TYPE_CHECKING, Any, Callable, ClassVar, - Dict, - Generator, - List, - Mapping, Optional, - Tuple, - Type, TypeVar, Union, cast, @@ -117,9 +112,9 @@ def _transform_guild_id(entry: AuditLogEntry, data: Optional[Snowflake]) -> Opti def _transform_overwrites( - entry: AuditLogEntry, data: List[PermissionOverwritePayload] -) -> List[Tuple[Union[Object, Member, Role, User], PermissionOverwrite]]: - overwrites: List[Tuple[Union[Object, Member, Role, User], PermissionOverwrite]] = [] + entry: AuditLogEntry, data: list[PermissionOverwritePayload] +) -> list[tuple[Union[Object, Member, Role, User], PermissionOverwrite]]: + overwrites: list[tuple[Union[Object, Member, Role, User], PermissionOverwrite]] = [] for elem in data: allow = Permissions(int(elem["allow"])) deny = Permissions(int(elem["deny"])) @@ -199,7 +194,7 @@ def _transform_tag_id( FlagsT = TypeVar("FlagsT", bound=flags.BaseFlags) -def _enum_transformer(enum: Type[EnumT]) -> Callable[[AuditLogEntry, int], EnumT]: +def _enum_transformer(enum: type[EnumT]) -> Callable[[AuditLogEntry, int], EnumT]: def _transform(entry: AuditLogEntry, data: int) -> EnumT: return enums.try_enum(enum, data) @@ -207,7 +202,7 @@ def _transform(entry: AuditLogEntry, data: int) -> EnumT: def _flags_transformer( - flags_type: Type[FlagsT], + flags_type: type[FlagsT], ) -> Callable[[AuditLogEntry, Optional[int]], Optional[FlagsT]]: def _transform(entry: AuditLogEntry, data: Optional[int]) -> Optional[FlagsT]: return flags_type._from_value(data) if data is not None else None @@ -217,8 +212,8 @@ def _transform(entry: AuditLogEntry, data: Optional[int]) -> Optional[FlagsT]: def _list_transformer( func: Callable[[AuditLogEntry, Any], T], -) -> Callable[[AuditLogEntry, Any], List[T]]: - def _transform(entry: AuditLogEntry, data: Any) -> List[T]: +) -> Callable[[AuditLogEntry, Any], list[T]]: + def _transform(entry: AuditLogEntry, data: Any) -> list[T]: if not data: return [] return [func(entry, value) for value in data if value is not None] @@ -294,7 +289,7 @@ class AuditLogDiff: def __len__(self) -> int: return len(self.__dict__) - def __iter__(self) -> Generator[Tuple[str, Any], None, None]: + def __iter__(self) -> Generator[tuple[str, Any], None, None]: yield from self.__dict__.items() def __repr__(self) -> str: @@ -313,7 +308,7 @@ def __setattr__(self, key: str, value: Any) -> Any: ... class AuditLogChanges: # fmt: off - TRANSFORMERS: ClassVar[Dict[str, Tuple[Optional[str], Optional[Transformer]]]] = { + TRANSFORMERS: ClassVar[dict[str, tuple[Optional[str], Optional[Transformer]]]] = { "verification_level": (None, _enum_transformer(enums.VerificationLevel)), "explicit_content_filter": (None, _enum_transformer(enums.ContentFilter)), "allow": (None, _transform_permissions), @@ -367,7 +362,7 @@ class AuditLogChanges: } # fmt: on - def __init__(self, entry: AuditLogEntry, data: List[AuditLogChangePayload]) -> None: + def __init__(self, entry: AuditLogEntry, data: list[AuditLogChangePayload]) -> None: self.before = AuditLogDiff() self.after = AuditLogDiff() @@ -440,7 +435,7 @@ def _handle_role( first: AuditLogDiff, second: AuditLogDiff, entry: AuditLogEntry, - elem: List[RolePayload], + elem: list[RolePayload], ) -> None: if not hasattr(first, "roles"): first.roles = [] diff --git a/disnake/automod.py b/disnake/automod.py index 3d6b5b2f66..9d627e95c1 100644 --- a/disnake/automod.py +++ b/disnake/automod.py @@ -3,15 +3,10 @@ from __future__ import annotations import datetime +from collections.abc import Iterable, Sequence from typing import ( TYPE_CHECKING, - Dict, - FrozenSet, - Iterable, - List, Optional, - Sequence, - Type, Union, overload, ) @@ -471,18 +466,18 @@ def __init__(self, *, data: AutoModRulePayload, guild: Guild) -> None: self.creator_id: int = int(data["creator_id"]) self.event_type: AutoModEventType = try_enum(AutoModEventType, data["event_type"]) self.trigger_type: AutoModTriggerType = try_enum(AutoModTriggerType, data["trigger_type"]) - self._actions: List[AutoModAction] = [ + self._actions: list[AutoModAction] = [ _automod_action_factory(action) for action in data["actions"] ] self.trigger_metadata: AutoModTriggerMetadata = AutoModTriggerMetadata._from_dict( data.get("trigger_metadata", {}) ) - self.exempt_role_ids: FrozenSet[int] = ( + self.exempt_role_ids: frozenset[int] = ( frozenset(map(int, exempt_roles)) if (exempt_roles := data.get("exempt_roles")) else frozenset() ) - self.exempt_channel_ids: FrozenSet[int] = ( + self.exempt_channel_ids: frozenset[int] = ( frozenset(map(int, exempt_channels)) if (exempt_channels := data.get("exempt_channels")) else frozenset() @@ -497,7 +492,7 @@ def created_at(self) -> datetime.datetime: return snowflake_time(self.id) @property - def actions(self) -> List[AutoModAction]: + def actions(self) -> list[AutoModAction]: """:class:`list`\\[:class:`AutoModBlockMessageAction` | :class:`AutoModSendAlertAction` | :class:`AutoModTimeoutAction` | :class:`AutoModAction`]: The list of actions that will execute if a matching event triggered this rule. """ @@ -511,12 +506,12 @@ def creator(self) -> Optional[Member]: return self.guild.get_member(self.creator_id) @property - def exempt_roles(self) -> List[Role]: + def exempt_roles(self) -> list[Role]: """:class:`list`\\[:class:`Role`]: The list of roles that are exempt from this rule.""" return list(filter(None, map(self.guild.get_role, self.exempt_role_ids))) @property - def exempt_channels(self) -> List[GuildChannel]: + def exempt_channels(self) -> list[GuildChannel]: """:class:`list`\\[:class:`abc.GuildChannel`]: The list of channels that are exempt from this rule.""" return list(filter(None, map(self.guild.get_channel, self.exempt_channel_ids))) @@ -791,7 +786,7 @@ def alert_message(self) -> Optional[Message]: return self.guild._state._get_message(self.alert_message_id) -_action_map: Dict[int, Type[AutoModAction]] = { +_action_map: dict[int, type[AutoModAction]] = { AutoModActionType.block_message.value: AutoModBlockMessageAction, AutoModActionType.send_alert_message.value: AutoModSendAlertAction, AutoModActionType.timeout.value: AutoModTimeoutAction, diff --git a/disnake/bans.py b/disnake/bans.py index 3f05cfb76d..d8bfdba791 100644 --- a/disnake/bans.py +++ b/disnake/bans.py @@ -2,7 +2,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, NamedTuple, Optional, Sequence +from collections.abc import Sequence +from typing import TYPE_CHECKING, NamedTuple, Optional __all__ = ("BanEntry",) diff --git a/disnake/channel.py b/disnake/channel.py index 99c5ee3d89..98d75c9e5d 100644 --- a/disnake/channel.py +++ b/disnake/channel.py @@ -5,20 +5,14 @@ import asyncio import datetime import time +from collections.abc import Iterable, Mapping, Sequence from typing import ( TYPE_CHECKING, Any, Callable, - Dict, - Iterable, - List, Literal, - Mapping, NamedTuple, Optional, - Sequence, - Tuple, - Type, Union, cast, overload, @@ -340,14 +334,14 @@ def permissions_for( return base @property - def members(self) -> List[Member]: + def members(self) -> list[Member]: """:class:`list`\\[:class:`Member`]: Returns all members that can see this channel.""" if isinstance(self.guild, Object): return [] return [m for m in self.guild.members if self.permissions_for(m).view_channel] @property - def threads(self) -> List[Thread]: + def threads(self) -> list[Thread]: """:class:`list`\\[:class:`Thread`]: Returns all the threads that you can see. .. versionadded:: 2.0 @@ -717,7 +711,7 @@ async def purge( around: Optional[SnowflakeTime] = None, oldest_first: Optional[bool] = False, bulk: bool = True, - ) -> List[Message]: + ) -> list[Message]: """|coro| Purges a list of messages that meet the criteria given by the predicate @@ -778,7 +772,7 @@ def is_me(m): iterator = self.history( limit=limit, before=before, after=after, oldest_first=oldest_first, around=around ) - ret: List[Message] = [] + ret: list[Message] = [] count = 0 minimum_time = int((time.time() - 14 * 24 * 60 * 60) * 1000.0 - 1420070400000) << 22 @@ -819,7 +813,7 @@ def is_me(m): return ret - async def webhooks(self) -> List[Webhook]: + async def webhooks(self) -> list[Webhook]: """|coro| Retrieves the list of webhooks this channel has. @@ -1198,10 +1192,10 @@ def __init__( self.id: int = int(data["id"]) self._update(guild, data) - def _get_voice_client_key(self) -> Tuple[int, str]: + def _get_voice_client_key(self) -> tuple[int, str]: return self.guild.id, "guild_id" - def _get_voice_state_pair(self) -> Tuple[int, int]: + def _get_voice_state_pair(self) -> tuple[int, int]: return self.guild.id, self.id def _update(self, guild: Guild, data: Union[VoiceChannelPayload, StageChannelPayload]) -> None: @@ -1226,12 +1220,12 @@ def _sorting_bucket(self) -> int: return ChannelType.voice.value @property - def members(self) -> List[Member]: + def members(self) -> list[Member]: """:class:`list`\\[:class:`Member`]: Returns all members that are currently inside this voice channel.""" if isinstance(self.guild, Object): return [] - ret: List[Member] = [] + ret: list[Member] = [] for user_id, state in self.guild._voice_states.items(): if state.channel and state.channel.id == self.id: member = self.guild.get_member(user_id) @@ -1240,7 +1234,7 @@ def members(self) -> List[Member]: return ret @property - def voice_states(self) -> Dict[int, VoiceState]: + def voice_states(self) -> dict[int, VoiceState]: """Returns a mapping of member IDs who have voice states in this channel. .. versionadded:: 1.3 @@ -1774,7 +1768,7 @@ async def purge( around: Optional[SnowflakeTime] = None, oldest_first: Optional[bool] = False, bulk: bool = True, - ) -> List[Message]: + ) -> list[Message]: """|coro| Purges a list of messages that meet the criteria given by the predicate @@ -1831,7 +1825,7 @@ async def purge( iterator = self.history( limit=limit, before=before, after=after, oldest_first=oldest_first, around=around ) - ret: List[Message] = [] + ret: list[Message] = [] count = 0 minimum_time = int((time.time() - 14 * 24 * 60 * 60) * 1000.0 - 1420070400000) << 22 @@ -1872,7 +1866,7 @@ async def purge( return ret - async def webhooks(self) -> List[Webhook]: + async def webhooks(self) -> list[Webhook]: """|coro| Retrieves the list of webhooks this channel has. @@ -2088,7 +2082,7 @@ async def _get_channel(self) -> Self: return self @property - def requesting_to_speak(self) -> List[Member]: + def requesting_to_speak(self) -> list[Member]: """:class:`list`\\[:class:`Member`]: A list of members who are requesting to speak in the stage channel.""" return [ member @@ -2097,7 +2091,7 @@ def requesting_to_speak(self) -> List[Member]: ] @property - def speakers(self) -> List[Member]: + def speakers(self) -> list[Member]: """:class:`list`\\[:class:`Member`]: A list of members who have been permitted to speak in the stage channel. .. versionadded:: 2.0 @@ -2111,7 +2105,7 @@ def speakers(self) -> List[Member]: ] @property - def listeners(self) -> List[Member]: + def listeners(self) -> list[Member]: """:class:`list`\\[:class:`Member`]: A list of members who are listening in the stage channel. .. versionadded:: 2.0 @@ -2119,7 +2113,7 @@ def listeners(self) -> List[Member]: return [member for member in self.members if member.voice and member.voice.suppress] @property - def moderators(self) -> List[Member]: + def moderators(self) -> list[Member]: """:class:`list`\\[:class:`Member`]: A list of members who are moderating the stage channel. .. versionadded:: 2.0 @@ -2356,7 +2350,7 @@ async def create_instance( :class:`StageInstance` The newly created stage instance. """ - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "channel_id": self.id, "topic": topic, "send_start_notification": notify_everyone, @@ -2631,7 +2625,7 @@ async def purge( around: Optional[SnowflakeTime] = None, oldest_first: Optional[bool] = False, bulk: bool = True, - ) -> List[Message]: + ) -> list[Message]: """|coro| Purges a list of messages that meet the criteria given by the predicate @@ -2688,7 +2682,7 @@ async def purge( iterator = self.history( limit=limit, before=before, after=after, oldest_first=oldest_first, around=around ) - ret: List[Message] = [] + ret: list[Message] = [] count = 0 minimum_time = int((time.time() - 14 * 24 * 60 * 60) * 1000.0 - 1420070400000) << 22 @@ -2729,7 +2723,7 @@ async def purge( return ret - async def webhooks(self) -> List[Webhook]: + async def webhooks(self) -> list[Webhook]: """|coro| Retrieves the list of webhooks this channel has. @@ -3107,7 +3101,7 @@ async def move(self, **kwargs: Any) -> None: return await super().move(**kwargs) @property - def channels(self) -> List[GuildChannelType]: + def channels(self) -> list[GuildChannelType]: """:class:`list`\\[:class:`abc.GuildChannel`]: Returns the channels that are under this category. These are sorted by the official Discord UI, which places voice channels below the text channels. @@ -3115,7 +3109,7 @@ def channels(self) -> List[GuildChannelType]: if isinstance(self.guild, Object): return [] - def comparator(channel: GuildChannelType) -> Tuple[bool, int]: + def comparator(channel: GuildChannelType) -> tuple[bool, int]: return ( not isinstance(channel, (TextChannel, ThreadOnlyGuildChannel)), channel.position, @@ -3126,7 +3120,7 @@ def comparator(channel: GuildChannelType) -> Tuple[bool, int]: return ret @property - def text_channels(self) -> List[TextChannel]: + def text_channels(self) -> list[TextChannel]: """:class:`list`\\[:class:`TextChannel`]: Returns the text channels that are under this category.""" if isinstance(self.guild, Object): return [] @@ -3140,7 +3134,7 @@ def text_channels(self) -> List[TextChannel]: return ret @property - def voice_channels(self) -> List[VoiceChannel]: + def voice_channels(self) -> list[VoiceChannel]: """:class:`list`\\[:class:`VoiceChannel`]: Returns the voice channels that are under this category.""" if isinstance(self.guild, Object): return [] @@ -3154,7 +3148,7 @@ def voice_channels(self) -> List[VoiceChannel]: return ret @property - def stage_channels(self) -> List[StageChannel]: + def stage_channels(self) -> list[StageChannel]: """:class:`list`\\[:class:`StageChannel`]: Returns the stage channels that are under this category. .. versionadded:: 1.7 @@ -3171,7 +3165,7 @@ def stage_channels(self) -> List[StageChannel]: return ret @property - def forum_channels(self) -> List[ForumChannel]: + def forum_channels(self) -> list[ForumChannel]: """:class:`list`\\[:class:`ForumChannel`]: Returns the forum channels that are under this category. .. versionadded:: 2.5 @@ -3188,7 +3182,7 @@ def forum_channels(self) -> List[ForumChannel]: return ret @property - def media_channels(self) -> List[MediaChannel]: + def media_channels(self) -> list[MediaChannel]: """:class:`list`\\[:class:`MediaChannel`]: Returns the media channels that are under this category. .. versionadded:: 2.10 @@ -3369,7 +3363,7 @@ def _update(self, guild: Guild, data: Union[ForumChannelPayload, MediaChannelPay ForumTag._from_data(data=tag, state=self._state) for tag in data.get("available_tags", []) ] - self._available_tags: Dict[int, ForumTag] = {tag.id: tag for tag in tags} + self._available_tags: dict[int, ForumTag] = {tag.id: tag for tag in tags} default_reaction_emoji = data.get("default_reaction_emoji") or {} # emoji_id may be `0`, use `None` instead @@ -3410,14 +3404,14 @@ def permissions_for( return base @property - def members(self) -> List[Member]: + def members(self) -> list[Member]: """:class:`list`\\[:class:`Member`]: Returns all members that can see this channel.""" if isinstance(self.guild, Object): return [] return [m for m in self.guild.members if self.permissions_for(m).view_channel] @property - def threads(self) -> List[Thread]: + def threads(self) -> list[Thread]: """:class:`list`\\[:class:`Thread`]: Returns all the threads that you can see.""" if isinstance(self.guild, Object): return [] @@ -3477,7 +3471,7 @@ def last_thread(self) -> Optional[Thread]: return self._state.get_channel(self.last_thread_id) if self.last_thread_id else None # type: ignore @property - def available_tags(self) -> List[ForumTag]: + def available_tags(self) -> list[ForumTag]: """:class:`list`\\[:class:`ForumTag`]: The available tags for threads in this channel. To create/edit/delete tags, use :func:`edit`. @@ -3548,7 +3542,7 @@ async def create_thread( applied_tags: Sequence[Snowflake] = ..., content: str = ..., embed: Embed = ..., - files: List[File] = ..., + files: list[File] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., stickers: Sequence[Union[GuildSticker, StandardSticker, StickerItem]] = ..., @@ -3567,7 +3561,7 @@ async def create_thread( slowmode_delay: Optional[int] = ..., applied_tags: Sequence[Snowflake] = ..., content: str = ..., - embeds: List[Embed] = ..., + embeds: list[Embed] = ..., file: File = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., @@ -3587,8 +3581,8 @@ async def create_thread( slowmode_delay: Optional[int] = ..., applied_tags: Sequence[Snowflake] = ..., content: str = ..., - embeds: List[Embed] = ..., - files: List[File] = ..., + embeds: list[Embed] = ..., + files: list[File] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., stickers: Sequence[Union[GuildSticker, StandardSticker, StickerItem]] = ..., @@ -3607,9 +3601,9 @@ async def create_thread( applied_tags: Sequence[Snowflake] = MISSING, content: str = MISSING, embed: Embed = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, file: File = MISSING, - files: List[File] = MISSING, + files: list[File] = MISSING, suppress_embeds: bool = MISSING, flags: MessageFlags = MISSING, stickers: Sequence[Union[GuildSticker, StandardSticker, StickerItem]] = MISSING, @@ -3819,7 +3813,7 @@ def archived_threads( self.id, self.guild, limit=limit, joined=False, private=False, before=before ) - async def webhooks(self) -> List[Webhook]: + async def webhooks(self) -> list[Webhook]: """|coro| Retrieves the list of webhooks this channel has. @@ -4966,7 +4960,7 @@ def _update_group(self, data: GroupChannelPayload) -> None: self.owner_id: Optional[int] = utils._get_as_snowflake(data, "owner_id") self._icon: Optional[str] = data.get("icon") self.name: Optional[str] = data.get("name") - self.recipients: List[User] = [ + self.recipients: list[User] = [ self._state.store_user(u) for u in data.get("recipients", []) ] @@ -5149,7 +5143,7 @@ def get_partial_message(self, message_id: int, /) -> PartialMessage: def _guild_channel_factory( channel_type: int, -) -> Tuple[Optional[Type[GuildChannelType]], ChannelType]: +) -> tuple[Optional[type[GuildChannelType]], ChannelType]: value = try_enum(ChannelType, channel_type) if value is ChannelType.text: return TextChannel, value @@ -5171,8 +5165,8 @@ def _guild_channel_factory( def _channel_factory( channel_type: int, -) -> Tuple[ - Optional[Union[Type[GuildChannelType], Type[DMChannel], Type[GroupChannel]]], ChannelType +) -> tuple[ + Optional[Union[type[GuildChannelType], type[DMChannel], type[GroupChannel]]], ChannelType ]: cls, value = _guild_channel_factory(channel_type) if value is ChannelType.private: @@ -5185,8 +5179,8 @@ def _channel_factory( def _threaded_channel_factory( channel_type: int, -) -> Tuple[ - Optional[Union[Type[GuildChannelType], Type[DMChannel], Type[GroupChannel], Type[Thread]]], +) -> tuple[ + Optional[Union[type[GuildChannelType], type[DMChannel], type[GroupChannel], type[Thread]]], ChannelType, ]: cls, value = _channel_factory(channel_type) @@ -5197,7 +5191,7 @@ def _threaded_channel_factory( def _threaded_guild_channel_factory( channel_type: int, -) -> Tuple[Optional[Union[Type[GuildChannelType], Type[Thread]]], ChannelType]: +) -> tuple[Optional[Union[type[GuildChannelType], type[Thread]]], ChannelType]: cls, value = _guild_channel_factory(channel_type) if value in (ChannelType.private_thread, ChannelType.public_thread, ChannelType.news_thread): return Thread, value @@ -5205,8 +5199,8 @@ def _threaded_guild_channel_factory( def _channel_type_factory( - cls: Union[Type[disnake.abc.GuildChannel], Type[Thread]], -) -> List[ChannelType]: + cls: Union[type[disnake.abc.GuildChannel], type[Thread]], +) -> list[ChannelType]: return { # FIXME: this includes private channels; improve this once there's a common base type for all channels disnake.abc.GuildChannel: list(ChannelType.__members__.values()), diff --git a/disnake/client.py b/disnake/client.py index 653d2c0bbb..957cd89f47 100644 --- a/disnake/client.py +++ b/disnake/client.py @@ -8,22 +8,16 @@ import sys import traceback import types +from collections.abc import Coroutine, Generator, Mapping, Sequence from datetime import datetime, timedelta from errno import ECONNRESET from typing import ( TYPE_CHECKING, Any, Callable, - Coroutine, - Dict, - Generator, - List, Literal, - Mapping, NamedTuple, Optional, - Sequence, - Tuple, TypedDict, TypeVar, Union, @@ -170,7 +164,7 @@ class SessionStartLimit: The approximate time at which which the :attr:`.remaining` limit resets. """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "total", "remaining", "reset_after", @@ -411,7 +405,7 @@ def __init__( self.loop: asyncio.AbstractEventLoop = loop self.loop.set_debug(asyncio_debug) - self._listeners: Dict[str, List[Tuple[asyncio.Future, Callable[..., bool]]]] = {} + self._listeners: dict[str, list[tuple[asyncio.Future, Callable[..., bool]]]] = {} self.session_start_limit: Optional[SessionStartLimit] = None self.http: HTTPClient = HTTPClient( @@ -422,12 +416,12 @@ def __init__( loop=self.loop, ) - self._handlers: Dict[str, Callable[..., Any]] = { + self._handlers: dict[str, Callable[..., Any]] = { "ready": self._handle_ready, "connect_internal": self._handle_first_connect, } - self._hooks: Dict[str, Callable[..., Any]] = { + self._hooks: dict[str, Callable[..., Any]] = { "before_identify": self._call_before_identify_hook } @@ -478,7 +472,7 @@ def __init__( msg = "Gateway encodings other than `json` are currently not supported." raise ValueError(msg) - self.extra_events: Dict[str, List[CoroFunc]] = {} + self.extra_events: dict[str, list[CoroFunc]] = {} # internals @@ -556,17 +550,17 @@ def user(self) -> ClientUser: return self._connection.user @property - def guilds(self) -> List[Guild]: + def guilds(self) -> list[Guild]: """:class:`list`\\[:class:`.Guild`]: The guilds that the connected client is a member of.""" return self._connection.guilds @property - def emojis(self) -> List[Emoji]: + def emojis(self) -> list[Emoji]: """:class:`list`\\[:class:`.Emoji`]: The emojis that the connected client has.""" return self._connection.emojis @property - def stickers(self) -> List[GuildSticker]: + def stickers(self) -> list[GuildSticker]: """:class:`list`\\[:class:`.GuildSticker`]: The stickers that the connected client has. .. versionadded:: 2.0 @@ -574,7 +568,7 @@ def stickers(self) -> List[GuildSticker]: return self._connection.stickers @property - def soundboard_sounds(self) -> List[GuildSoundboardSound]: + def soundboard_sounds(self) -> list[GuildSoundboardSound]: """:class:`list`\\[:class:`.GuildSoundboardSound`]: The soundboard sounds that the connected client has. .. versionadded:: 2.10 @@ -590,7 +584,7 @@ def cached_messages(self) -> Sequence[Message]: return utils.SequenceProxy(self._connection._messages or []) @property - def private_channels(self) -> List[PrivateChannel]: + def private_channels(self) -> list[PrivateChannel]: """:class:`list`\\[:class:`.abc.PrivateChannel`]: The private channels that the connected client is participating on. .. note:: @@ -601,7 +595,7 @@ def private_channels(self) -> List[PrivateChannel]: return self._connection.private_channels @property - def voice_clients(self) -> List[VoiceProtocol]: + def voice_clients(self) -> list[VoiceProtocol]: """:class:`list`\\[:class:`.VoiceProtocol`]: Represents a list of voice connections. These are usually :class:`.VoiceClient` instances. @@ -629,12 +623,12 @@ def application_flags(self) -> ApplicationFlags: return self._connection.application_flags @property - def global_application_commands(self) -> List[APIApplicationCommand]: + def global_application_commands(self) -> list[APIApplicationCommand]: """:class:`list`\\[:class:`.APIUserCommand` | :class:`.APIMessageCommand` | :class:`.APISlashCommand`]: The client's global application commands.""" return list(self._connection._global_application_commands.values()) @property - def global_slash_commands(self) -> List[APISlashCommand]: + def global_slash_commands(self) -> list[APISlashCommand]: """:class:`list`\\[:class:`.APISlashCommand`]: The client's global slash commands.""" return [ cmd @@ -643,7 +637,7 @@ def global_slash_commands(self) -> List[APISlashCommand]: ] @property - def global_user_commands(self) -> List[APIUserCommand]: + def global_user_commands(self) -> list[APIUserCommand]: """:class:`list`\\[:class:`.APIUserCommand`]: The client's global user commands.""" return [ cmd @@ -652,7 +646,7 @@ def global_user_commands(self) -> List[APIUserCommand]: ] @property - def global_message_commands(self) -> List[APIMessageCommand]: + def global_message_commands(self) -> list[APIMessageCommand]: """:class:`list`\\[:class:`.APIMessageCommand`]: The client's global message commands.""" return [ cmd @@ -932,7 +926,7 @@ def decorator(func: CoroT) -> CoroT: return decorator - def get_listeners(self) -> Mapping[str, List[CoroFunc]]: + def get_listeners(self) -> Mapping[str, list[CoroFunc]]: """:class:`~collections.abc.Mapping`\\[:class:`str`, :class:`list`\\[:class:`~collections.abc.Callable`]]: A read-only mapping of event names to listeners. .. note:: @@ -1394,7 +1388,7 @@ def intents(self) -> Intents: # helpers/getters @property - def users(self) -> List[User]: + def users(self) -> list[User]: """:class:`list`\\[:class:`~disnake.User`]: Returns a list of all the users the bot can see.""" return list(self._connection._users.values()) @@ -1577,7 +1571,7 @@ def get_all_members(self) -> Generator[Member, None, None]: for guild in self.guilds: yield from guild.members - def get_guild_application_commands(self, guild_id: int) -> List[APIApplicationCommand]: + def get_guild_application_commands(self, guild_id: int) -> list[APIApplicationCommand]: """Returns a list of all application commands in the guild with the given ID. Parameters @@ -1593,7 +1587,7 @@ def get_guild_application_commands(self, guild_id: int) -> List[APIApplicationCo data = self._connection._guild_application_commands.get(guild_id, {}) return list(data.values()) - def get_guild_slash_commands(self, guild_id: int) -> List[APISlashCommand]: + def get_guild_slash_commands(self, guild_id: int) -> list[APISlashCommand]: """Returns a list of all slash commands in the guild with the given ID. Parameters @@ -1609,7 +1603,7 @@ def get_guild_slash_commands(self, guild_id: int) -> List[APISlashCommand]: data = self._connection._guild_application_commands.get(guild_id, {}) return [cmd for cmd in data.values() if isinstance(cmd, APISlashCommand)] - def get_guild_user_commands(self, guild_id: int) -> List[APIUserCommand]: + def get_guild_user_commands(self, guild_id: int) -> list[APIUserCommand]: """Returns a list of all user commands in the guild with the given ID. Parameters @@ -1625,7 +1619,7 @@ def get_guild_user_commands(self, guild_id: int) -> List[APIUserCommand]: data = self._connection._guild_application_commands.get(guild_id, {}) return [cmd for cmd in data.values() if isinstance(cmd, APIUserCommand)] - def get_guild_message_commands(self, guild_id: int) -> List[APIMessageCommand]: + def get_guild_message_commands(self, guild_id: int) -> list[APIMessageCommand]: """Returns a list of all message commands in the guild with the given ID. Parameters @@ -2332,7 +2326,7 @@ async def delete_invite(self, invite: Union[Invite, str]) -> None: # Voice region stuff - async def fetch_voice_regions(self, guild_id: Optional[int] = None) -> List[VoiceRegion]: + async def fetch_voice_regions(self, guild_id: Optional[int] = None) -> list[VoiceRegion]: """Retrieves a list of :class:`.VoiceRegion`\\s. Retrieves voice regions for the user, or a guild if provided. @@ -2388,7 +2382,7 @@ async def fetch_widget(self, guild_id: int, /) -> Widget: data = await self.http.get_widget(guild_id) return Widget(state=self._connection, data=data) - async def fetch_default_soundboard_sounds(self) -> List[SoundboardSound]: + async def fetch_default_soundboard_sounds(self) -> list[SoundboardSound]: """|coro| Retrieves the list of default :class:`.SoundboardSound`\\s provided by Discord. @@ -2488,7 +2482,7 @@ async def create_application_emoji(self, *, name: str, image: AssetBytes) -> Emo data = await self.http.create_app_emoji(self.application_id, name=name, image=img) return Emoji(guild=None, state=self._connection, data=data) - async def fetch_application_emojis(self) -> List[Emoji]: + async def fetch_application_emojis(self) -> list[Emoji]: """|coro| Retrieves all the :class:`.Emoji` of the application. @@ -2678,7 +2672,7 @@ async def fetch_sticker_pack(self, pack_id: int, /) -> StickerPack: data = await self.http.get_sticker_pack(pack_id) return StickerPack(state=self._connection, data=data) - async def fetch_sticker_packs(self) -> List[StickerPack]: + async def fetch_sticker_packs(self) -> list[StickerPack]: """|coro| Retrieves all available sticker packs. @@ -2702,7 +2696,7 @@ async def fetch_sticker_packs(self) -> List[StickerPack]: return [StickerPack(state=self._connection, data=pack) for pack in data["sticker_packs"]] @deprecated("fetch_sticker_packs") - async def fetch_premium_sticker_packs(self) -> List[StickerPack]: + async def fetch_premium_sticker_packs(self) -> list[StickerPack]: """An alias of :meth:`fetch_sticker_packs`. .. deprecated:: 2.10 @@ -2786,7 +2780,7 @@ async def fetch_global_commands( self, *, with_localizations: bool = True, - ) -> List[APIApplicationCommand]: + ) -> list[APIApplicationCommand]: """|coro| Retrieves a list of global application commands. @@ -2923,8 +2917,8 @@ async def delete_global_command(self, command_id: int) -> None: await self._connection.delete_global_command(command_id) async def bulk_overwrite_global_commands( - self, application_commands: List[ApplicationCommand] - ) -> List[APIApplicationCommand]: + self, application_commands: list[ApplicationCommand] + ) -> list[APIApplicationCommand]: """|coro| Overwrites several global application commands in one API request. @@ -2952,7 +2946,7 @@ async def fetch_guild_commands( guild_id: int, *, with_localizations: bool = True, - ) -> List[APIApplicationCommand]: + ) -> list[APIApplicationCommand]: """|coro| Retrieves a list of guild application commands. @@ -3105,8 +3099,8 @@ async def delete_guild_command(self, guild_id: int, command_id: int) -> None: await self._connection.delete_guild_command(guild_id, command_id) async def bulk_overwrite_guild_commands( - self, guild_id: int, application_commands: List[ApplicationCommand] - ) -> List[APIApplicationCommand]: + self, guild_id: int, application_commands: list[ApplicationCommand] + ) -> list[APIApplicationCommand]: """|coro| Overwrites several guild application commands in one API request. @@ -3133,7 +3127,7 @@ async def bulk_overwrite_guild_commands( async def bulk_fetch_command_permissions( self, guild_id: int - ) -> List[GuildApplicationCommandPermissions]: + ) -> list[GuildApplicationCommandPermissions]: """|coro| Retrieves a list of :class:`.GuildApplicationCommandPermissions` configured for the guild with the given ID. @@ -3173,7 +3167,7 @@ async def fetch_command_permissions( """ return await self._connection.fetch_command_permissions(guild_id, command_id) - async def fetch_role_connection_metadata(self) -> List[ApplicationRoleConnectionMetadata]: + async def fetch_role_connection_metadata(self) -> list[ApplicationRoleConnectionMetadata]: """|coro| Retrieves the :class:`.ApplicationRoleConnectionMetadata` records for the application. @@ -3195,7 +3189,7 @@ async def fetch_role_connection_metadata(self) -> List[ApplicationRoleConnection async def edit_role_connection_metadata( self, records: Sequence[ApplicationRoleConnectionMetadata] - ) -> List[ApplicationRoleConnectionMetadata]: + ) -> list[ApplicationRoleConnectionMetadata]: """|coro| Edits the :class:`.ApplicationRoleConnectionMetadata` records for the application. @@ -3224,7 +3218,7 @@ async def edit_role_connection_metadata( :class:`list`\\[:class:`.ApplicationRoleConnectionMetadata`] The list of newly edited metadata records. """ - payload: List[ApplicationRoleConnectionMetadataPayload] = [] + payload: list[ApplicationRoleConnectionMetadataPayload] = [] for record in records: record._localize(self.i18n) payload.append(record.to_dict()) @@ -3234,7 +3228,7 @@ async def edit_role_connection_metadata( ) return [ApplicationRoleConnectionMetadata._from_data(record) for record in data] - async def skus(self) -> List[SKU]: + async def skus(self) -> list[SKU]: """|coro| Retrieves the :class:`.SKU`\\s for the application. diff --git a/disnake/colour.py b/disnake/colour.py index e6f83367c5..07c80b942b 100644 --- a/disnake/colour.py +++ b/disnake/colour.py @@ -4,7 +4,7 @@ import colorsys import random -from typing import TYPE_CHECKING, Any, Optional, Tuple, Union +from typing import TYPE_CHECKING, Any, Optional, Union if TYPE_CHECKING: from typing_extensions import Self @@ -95,7 +95,7 @@ def b(self) -> int: """:class:`int`: Returns the blue component of the colour.""" return self._get_byte(0) - def to_rgb(self) -> Tuple[int, int, int]: + def to_rgb(self) -> tuple[int, int, int]: """:class:`tuple`\\[:class:`int`, :class:`int`, :class:`int`]: Returns an (r, g, b) tuple representing the colour.""" return (self.r, self.g, self.b) @@ -321,7 +321,7 @@ def dark_embed(cls) -> Self: return cls(0x2B2D31) @classmethod - def holographic_style(cls) -> Tuple[Self, Self, Self]: + def holographic_style(cls) -> tuple[Self, Self, Self]: """A factory method that returns a tuple of :class:`Colour` with values of ``0xA9C9FF``, ``0xFFBBEC``, ``0xFFC3A0``. This matches the holographic colour style for roles. diff --git a/disnake/components.py b/disnake/components.py index a78ae94525..47069f6252 100644 --- a/disnake/components.py +++ b/disnake/components.py @@ -2,19 +2,15 @@ from __future__ import annotations +from collections.abc import Mapping from typing import ( TYPE_CHECKING, Any, ClassVar, - Dict, Final, Generic, - List, Literal, - Mapping, Optional, - Tuple, - Type, TypeVar, Union, cast, @@ -214,9 +210,9 @@ class Component: .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ("type", "id") + __slots__: tuple[str, ...] = ("type", "id") - __repr_attributes__: ClassVar[Tuple[str, ...]] + __repr_attributes__: ClassVar[tuple[str, ...]] # subclasses are expected to overwrite this if they're only usable with `MessageFlags.is_components_v2` is_v2: ClassVar[bool] = False @@ -240,7 +236,7 @@ def _raw_construct(cls, **kwargs) -> Self: setattr(self, slot, value) return self - def to_dict(self) -> Dict[str, Any]: + def to_dict(self) -> dict[str, Any]: raise NotImplementedError @@ -265,16 +261,16 @@ class ActionRow(Component, Generic[ActionRowChildComponentT]): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ("children",) + __slots__: tuple[str, ...] = ("children",) - __repr_attributes__: ClassVar[Tuple[str, ...]] = __slots__ + __repr_attributes__: ClassVar[tuple[str, ...]] = __slots__ def __init__(self, data: ActionRowPayload) -> None: self.type: Literal[ComponentType.action_row] = ComponentType.action_row self.id = data.get("id", 0) children = [_component_factory(d) for d in data.get("components", [])] - self.children: List[ActionRowChildComponentT] = children # type: ignore + self.children: list[ActionRowChildComponentT] = children # type: ignore def to_dict(self) -> ActionRowPayload: return { @@ -324,7 +320,7 @@ class Button(Component): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "style", "custom_id", "url", @@ -334,7 +330,7 @@ class Button(Component): "sku_id", ) - __repr_attributes__: ClassVar[Tuple[str, ...]] = __slots__ + __repr_attributes__: ClassVar[tuple[str, ...]] = __slots__ def __init__(self, data: ButtonComponentPayload) -> None: self.type: Literal[ComponentType.button] = ComponentType.button @@ -428,7 +424,7 @@ class BaseSelectMenu(Component): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "custom_id", "placeholder", "min_values", @@ -439,7 +435,7 @@ class BaseSelectMenu(Component): ) # FIXME: this isn't pretty; we should decouple __repr__ from slots - __repr_attributes__: ClassVar[Tuple[str, ...]] = tuple( + __repr_attributes__: ClassVar[tuple[str, ...]] = tuple( s for s in __slots__ if s != "default_values" ) @@ -456,7 +452,7 @@ def __init__(self, data: AnySelectMenuPayload) -> None: self.min_values: int = data.get("min_values", 1) self.max_values: int = data.get("max_values", 1) self.disabled: bool = data.get("disabled", False) - self.default_values: List[SelectDefaultValue] = [ + self.default_values: list[SelectDefaultValue] = [ SelectDefaultValue._from_dict(d) for d in (data.get("default_values") or []) ] self.required: bool = data.get("required", True) @@ -522,9 +518,9 @@ class StringSelectMenu(BaseSelectMenu): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ("options",) + __slots__: tuple[str, ...] = ("options",) - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( *BaseSelectMenu.__repr_attributes__, *__slots__, ) @@ -532,7 +528,7 @@ class StringSelectMenu(BaseSelectMenu): def __init__(self, data: StringSelectMenuPayload) -> None: super().__init__(data) - self.options: List[SelectOption] = [ + self.options: list[SelectOption] = [ SelectOption.from_dict(option) for option in data.get("options", []) ] @@ -586,7 +582,7 @@ class UserSelectMenu(BaseSelectMenu): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = () + __slots__: tuple[str, ...] = () type: Literal[ComponentType.user_select] @@ -637,7 +633,7 @@ class RoleSelectMenu(BaseSelectMenu): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = () + __slots__: tuple[str, ...] = () type: Literal[ComponentType.role_select] @@ -688,7 +684,7 @@ class MentionableSelectMenu(BaseSelectMenu): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = () + __slots__: tuple[str, ...] = () type: Literal[ComponentType.mentionable_select] @@ -742,9 +738,9 @@ class ChannelSelectMenu(BaseSelectMenu): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ("channel_types",) + __slots__: tuple[str, ...] = ("channel_types",) - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( *BaseSelectMenu.__repr_attributes__, *__slots__, ) @@ -754,7 +750,7 @@ def __init__(self, data: ChannelSelectMenuPayload) -> None: super().__init__(data) # on the API side, an empty list is (currently) equivalent to no value channel_types = data.get("channel_types") - self.channel_types: Optional[List[ChannelType]] = ( + self.channel_types: Optional[list[ChannelType]] = ( [try_enum(ChannelType, t) for t in channel_types] if channel_types else None ) @@ -790,7 +786,7 @@ class SelectOption: Whether this option is selected by default. """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "label", "value", "description", @@ -885,7 +881,7 @@ class SelectDefaultValue: The type of the target object. """ - __slots__: Tuple[str, ...] = ("id", "type") + __slots__: tuple[str, ...] = ("id", "type") def __init__(self, id: int, type: SelectDefaultValueType) -> None: self.id: int = id @@ -945,7 +941,7 @@ class TextInput(Component): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "style", "custom_id", "label", @@ -956,7 +952,7 @@ class TextInput(Component): "min_length", ) - __repr_attributes__: ClassVar[Tuple[str, ...]] = __slots__ + __repr_attributes__: ClassVar[tuple[str, ...]] = __slots__ def __init__(self, data: TextInputPayload) -> None: self.type: Literal[ComponentType.text_input] = ComponentType.text_input @@ -1023,9 +1019,9 @@ class Section(Component): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ("children", "accessory") + __slots__: tuple[str, ...] = ("children", "accessory") - __repr_attributes__: ClassVar[Tuple[str, ...]] = __slots__ + __repr_attributes__: ClassVar[tuple[str, ...]] = __slots__ is_v2 = True @@ -1033,7 +1029,7 @@ def __init__(self, data: SectionComponentPayload) -> None: self.type: Literal[ComponentType.section] = ComponentType.section self.id = data.get("id", 0) - self.children: List[SectionChildComponent] = [ + self.children: list[SectionChildComponent] = [ _component_factory(d, type=SectionChildComponent) for d in data.get("components", []) ] @@ -1070,9 +1066,9 @@ class TextDisplay(Component): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ("content",) + __slots__: tuple[str, ...] = ("content",) - __repr_attributes__: ClassVar[Tuple[str, ...]] = __slots__ + __repr_attributes__: ClassVar[tuple[str, ...]] = __slots__ is_v2 = True @@ -1113,7 +1109,7 @@ class UnfurledMediaItem: uploaded as an attachment. """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "url", "proxy_url", "height", @@ -1178,13 +1174,13 @@ class Thumbnail(Component): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "media", "description", "spoiler", ) - __repr_attributes__: ClassVar[Tuple[str, ...]] = __slots__ + __repr_attributes__: ClassVar[tuple[str, ...]] = __slots__ is_v2 = True @@ -1233,9 +1229,9 @@ class MediaGallery(Component): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ("items",) + __slots__: tuple[str, ...] = ("items",) - __repr_attributes__: ClassVar[Tuple[str, ...]] = __slots__ + __repr_attributes__: ClassVar[tuple[str, ...]] = __slots__ is_v2 = True @@ -1243,7 +1239,7 @@ def __init__(self, data: MediaGalleryComponentPayload) -> None: self.type: Literal[ComponentType.media_gallery] = ComponentType.media_gallery self.id = data.get("id", 0) - self.items: List[MediaGalleryItem] = [MediaGalleryItem.from_dict(i) for i in data["items"]] + self.items: list[MediaGalleryItem] = [MediaGalleryItem.from_dict(i) for i in data["items"]] def to_dict(self) -> MediaGalleryComponentPayload: return { @@ -1269,7 +1265,7 @@ class MediaGalleryItem: Whether the item is marked as a spoiler. Defaults to ``False``. """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "media", "description", "spoiler", @@ -1341,9 +1337,9 @@ class FileComponent(Component): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ("file", "spoiler", "name", "size") + __slots__: tuple[str, ...] = ("file", "spoiler", "name", "size") - __repr_attributes__: ClassVar[Tuple[str, ...]] = __slots__ + __repr_attributes__: ClassVar[tuple[str, ...]] = __slots__ is_v2 = True @@ -1392,9 +1388,9 @@ class Separator(Component): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ("divider", "spacing") + __slots__: tuple[str, ...] = ("divider", "spacing") - __repr_attributes__: ClassVar[Tuple[str, ...]] = __slots__ + __repr_attributes__: ClassVar[tuple[str, ...]] = __slots__ is_v2 = True @@ -1441,13 +1437,13 @@ class Container(Component): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "children", "accent_colour", "spoiler", ) - __repr_attributes__: ClassVar[Tuple[str, ...]] = __slots__ + __repr_attributes__: ClassVar[tuple[str, ...]] = __slots__ is_v2 = True @@ -1456,7 +1452,7 @@ def __init__(self, data: ContainerComponentPayload) -> None: self.id = data.get("id", 0) components = [_component_factory(d) for d in data.get("components", [])] - self.children: List[ContainerChildComponent] = components # type: ignore + self.children: list[ContainerChildComponent] = components # type: ignore self.accent_colour: Optional[Colour] = ( Colour(accent_color) if (accent_color := data.get("accent_color")) is not None else None @@ -1511,13 +1507,13 @@ class Label(Component): and unique within a message. """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "text", "description", "component", ) - __repr_info__: ClassVar[Tuple[str, ...]] = __slots__ + __repr_info__: ClassVar[tuple[str, ...]] = __slots__ def __init__(self, data: LabelComponentPayload) -> None: self.type: Literal[ComponentType.label] = ComponentType.label @@ -1575,7 +1571,7 @@ def handle_media_item_input(value: MediaItemInput) -> UnfurledMediaItem: C = TypeVar("C", bound="Component") -COMPONENT_LOOKUP: Mapping[ComponentTypeLiteral, Type[Component]] = { +COMPONENT_LOOKUP: Mapping[ComponentTypeLiteral, type[Component]] = { ComponentType.action_row.value: ActionRow, ComponentType.button.value: Button, ComponentType.string_select.value: StringSelectMenu, @@ -1597,7 +1593,7 @@ def handle_media_item_input(value: MediaItemInput) -> UnfurledMediaItem: # NOTE: The type param is purely for type-checking, it has no implications on runtime behavior. # FIXME: could be improved with https://peps.python.org/pep-0747/ -def _component_factory(data: ComponentPayload, *, type: Type[C] = Component) -> C: +def _component_factory(data: ComponentPayload, *, type: type[C] = Component) -> C: component_type = data["type"] try: diff --git a/disnake/context_managers.py b/disnake/context_managers.py index 120c75ffa9..a26890e819 100644 --- a/disnake/context_managers.py +++ b/disnake/context_managers.py @@ -3,7 +3,7 @@ from __future__ import annotations import asyncio -from typing import TYPE_CHECKING, Optional, Type, Union +from typing import TYPE_CHECKING, Optional, Union if TYPE_CHECKING: from types import TracebackType @@ -48,7 +48,7 @@ def __enter__(self) -> Self: def __exit__( self, - exc_type: Optional[Type[BaseException]], + exc_type: Optional[type[BaseException]], exc_value: Optional[BaseException], traceback: Optional[TracebackType], ) -> None: @@ -61,7 +61,7 @@ async def __aenter__(self) -> Self: async def __aexit__( self, - exc_type: Optional[Type[BaseException]], + exc_type: Optional[type[BaseException]], exc_value: Optional[BaseException], traceback: Optional[TracebackType], ) -> None: diff --git a/disnake/embeds.py b/disnake/embeds.py index eb91c25bfb..5bea0d1ae6 100644 --- a/disnake/embeds.py +++ b/disnake/embeds.py @@ -3,17 +3,14 @@ from __future__ import annotations import datetime +from collections.abc import Mapping, Sized from typing import ( TYPE_CHECKING, Any, ClassVar, - Dict, - List, Literal, - Mapping, Optional, Protocol, - Sized, Union, cast, overload, @@ -220,9 +217,9 @@ def __init__( self._author: Optional[EmbedAuthorPayload] = None self._image: Optional[EmbedImagePayload] = None self._footer: Optional[EmbedFooterPayload] = None - self._fields: Optional[List[EmbedFieldPayload]] = None + self._fields: Optional[list[EmbedFieldPayload]] = None - self._files: Dict[_FileKey, File] = {} + self._files: dict[_FileKey, File] = {} # see `EmptyEmbed` above if not TYPE_CHECKING: @@ -654,14 +651,14 @@ def remove_author(self) -> Self: return self @property - def fields(self) -> List[_EmbedFieldProxy]: + def fields(self) -> list[_EmbedFieldProxy]: """:class:`list`\\[``EmbedProxy``]: Returns a :class:`list` of ``EmbedProxy`` denoting the field contents. See :meth:`add_field` for possible values you can access. If an attribute is not set, it will be :data:`None`. """ - return cast("List[_EmbedFieldProxy]", [EmbedProxy(d) for d in (self._fields or [])]) + return cast("list[_EmbedFieldProxy]", [EmbedProxy(d) for d in (self._fields or [])]) def add_field(self, name: Any, value: Any, *, inline: bool = True) -> Self: """Adds a field to the embed object. diff --git a/disnake/emoji.py b/disnake/emoji.py index 57c6c113d7..76c897b8fd 100644 --- a/disnake/emoji.py +++ b/disnake/emoji.py @@ -2,7 +2,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Iterator, List, Optional, Tuple, Union +from collections.abc import Iterator +from typing import TYPE_CHECKING, Any, Optional, Union from .asset import Asset, AssetMixin from .errors import InvalidData @@ -82,7 +83,7 @@ class Emoji(_EmojiTag, AssetMixin): or the bot user if created using :meth:`Client.create_application_emoji`. """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "require_colons", "animated", "managed", @@ -119,7 +120,7 @@ def _from_data(self, emoji: EmojiPayload) -> None: def _to_partial(self) -> PartialEmoji: return PartialEmoji(name=self.name, animated=self.animated, id=self.id) - def __iter__(self) -> Iterator[Tuple[str, Any]]: + def __iter__(self) -> Iterator[tuple[str, Any]]: for attr in self.__slots__: if attr[0] != "_": value = getattr(self, attr, None) @@ -160,7 +161,7 @@ def url(self) -> str: return f"{Asset.BASE}/emojis/{self.id}.{fmt}" @property - def roles(self) -> List[Role]: + def roles(self) -> list[Role]: """:class:`list`\\[:class:`Role`]: A :class:`list` of roles that are allowed to use this emoji. If roles is empty, the emoji is unrestricted. @@ -267,7 +268,7 @@ async def delete(self, *, reason: Optional[str] = None) -> None: await self._state.http.delete_custom_emoji(self.guild_id, self.id, reason=reason) async def edit( - self, *, name: str = MISSING, roles: List[Snowflake] = MISSING, reason: Optional[str] = None + self, *, name: str = MISSING, roles: list[Snowflake] = MISSING, reason: Optional[str] = None ) -> Emoji: """|coro| diff --git a/disnake/enums.py b/disnake/enums.py index fb6dd6cbe4..c17a86067f 100644 --- a/disnake/enums.py +++ b/disnake/enums.py @@ -2,18 +2,15 @@ from __future__ import annotations import types +from collections.abc import Iterator from functools import total_ordering from typing import ( TYPE_CHECKING, Any, ClassVar, - Dict, - Iterator, - List, NamedTuple, NoReturn, Optional, - Type, TypeVar, ) @@ -82,7 +79,7 @@ "NameplatePalette", ) -EnumMetaT = TypeVar("EnumMetaT", bound="Type[EnumMeta]") +EnumMetaT = TypeVar("EnumMetaT", bound="type[EnumMeta]") class _EnumValueBase(NamedTuple): @@ -108,7 +105,7 @@ def __lt__(self, other: object) -> bool: return isinstance(other, self.__class__) and self.value < other.value -def _create_value_cls(name: str, comparable: bool) -> Type[_EnumValueBase]: +def _create_value_cls(name: str, comparable: bool) -> type[_EnumValueBase]: parent = _EnumValueComparable if comparable else _EnumValueBase return type(f"{parent.__name__}_{name}", (parent,), {"_cls_name": name}) # type: ignore @@ -120,10 +117,10 @@ def _is_descriptor(obj) -> bool: class EnumMeta(type): if TYPE_CHECKING: __name__: ClassVar[str] - _enum_member_names_: ClassVar[List[str]] - _enum_member_map_: ClassVar[Dict[str, Any]] - _enum_value_map_: ClassVar[Dict[Any, Any]] - _enum_value_cls_: ClassVar[Type[_EnumValueBase]] + _enum_member_names_: ClassVar[list[str]] + _enum_member_map_: ClassVar[dict[str, Any]] + _enum_value_map_: ClassVar[dict[Any, Any]] + _enum_value_cls_: ClassVar[type[_EnumValueBase]] def __new__(cls: EnumMetaT, name: str, bases, attrs, *, comparable: bool = False) -> EnumMetaT: value_mapping = {} @@ -777,7 +774,7 @@ class AuditLogAction(Enum): @property def category(self) -> Optional[AuditLogActionCategory]: # fmt: off - lookup: Dict[AuditLogAction, Optional[AuditLogActionCategory]] = { + lookup: dict[AuditLogAction, Optional[AuditLogActionCategory]] = { AuditLogAction.guild_update: AuditLogActionCategory.update, AuditLogAction.channel_create: AuditLogActionCategory.create, AuditLogAction.channel_update: AuditLogActionCategory.update, @@ -1076,7 +1073,7 @@ def file_extension(self) -> str: return STICKER_FORMAT_LOOKUP[self] -STICKER_FORMAT_LOOKUP: Dict[StickerFormatType, str] = { +STICKER_FORMAT_LOOKUP: dict[StickerFormatType, str] = { StickerFormatType.png: "png", StickerFormatType.apng: "png", StickerFormatType.lottie: "json", @@ -2452,13 +2449,13 @@ class NameplatePalette(Enum): T = TypeVar("T") -def create_unknown_value(cls: Type[T], val: Any) -> T: +def create_unknown_value(cls: type[T], val: Any) -> T: value_cls = cls._enum_value_cls_ # type: ignore name = f"unknown_{val}" return value_cls(name=name, value=val) -def try_enum(cls: Type[T], val: Any) -> T: +def try_enum(cls: type[T], val: Any) -> T: """A function that tries to turn the value into enum ``cls``. If it fails it returns a proxy invalid value instead. @@ -2469,7 +2466,7 @@ def try_enum(cls: Type[T], val: Any) -> T: return create_unknown_value(cls, val) -def enum_if_int(cls: Type[T], val: Any) -> T: +def enum_if_int(cls: type[T], val: Any) -> T: """A function that tries to turn the value into enum ``cls``. If it fails it returns a proxy invalid value instead. diff --git a/disnake/errors.py b/disnake/errors.py index 1d04d0b3e3..00a51bc50f 100644 --- a/disnake/errors.py +++ b/disnake/errors.py @@ -2,7 +2,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, Mapping, Optional, Tuple, Union +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, ClassVar, Optional, Union if TYPE_CHECKING: from aiohttp import ClientResponse, ClientWebSocketResponse @@ -70,14 +71,14 @@ def __init__(self) -> None: super().__init__(message) -def _flatten_error_dict(d: Dict[str, Any], key: str = "") -> Dict[str, str]: - items: List[Tuple[str, str]] = [] +def _flatten_error_dict(d: dict[str, Any], key: str = "") -> dict[str, str]: + items: list[tuple[str, str]] = [] for k, v in d.items(): new_key = f"{key}.{k}" if key else k if isinstance(v, dict): try: - _errors: List[Dict[str, Any]] = v["_errors"] + _errors: list[dict[str, Any]] = v["_errors"] except KeyError: items.extend(_flatten_error_dict(v, new_key).items()) else: @@ -107,7 +108,7 @@ class HTTPException(DiscordException): """ def __init__( - self, response: _ResponseType, message: Optional[Union[str, Dict[str, Any]]] + self, response: _ResponseType, message: Optional[Union[str, dict[str, Any]]] ) -> None: self.response: _ResponseType = response self.status: int = response.status # type: ignore diff --git a/disnake/ext/commands/_types.py b/disnake/ext/commands/_types.py index 6f23a6e11c..c337f75674 100644 --- a/disnake/ext/commands/_types.py +++ b/disnake/ext/commands/_types.py @@ -1,6 +1,7 @@ # SPDX-License-Identifier: MIT -from typing import TYPE_CHECKING, Any, Callable, Coroutine, TypeVar, Union +from collections.abc import Coroutine +from typing import TYPE_CHECKING, Any, Callable, TypeVar, Union if TYPE_CHECKING: from disnake import ApplicationCommandInteraction diff --git a/disnake/ext/commands/base_core.py b/disnake/ext/commands/base_core.py index fdd543df51..2510e7e3c6 100644 --- a/disnake/ext/commands/base_core.py +++ b/disnake/ext/commands/base_core.py @@ -10,10 +10,7 @@ TYPE_CHECKING, Any, Callable, - Dict, - List, Optional, - Tuple, TypeVar, Union, cast, @@ -134,7 +131,7 @@ class InvokableApplicationCommand(ABC): .. versionadded:: 2.5 """ - __original_kwargs__: Dict[str, Any] + __original_kwargs__: dict[str, Any] body: ApplicationCommand def __new__(cls, *args: Any, **kwargs: Any) -> Self: @@ -151,7 +148,7 @@ def __init__(self, func: CommandCallback, *, name: Optional[str] = None, **kwarg # Annotation parser needs this attribute because body doesn't exist at this moment. # We will use this attribute later in order to set the allowed contexts. self._guild_only: bool = kwargs.get("guild_only", False) - self.extras: Dict[str, Any] = kwargs.get("extras") or {} + self.extras: dict[str, Any] = kwargs.get("extras") or {} if not isinstance(self.name, str): msg = "Name of a command must be a string." @@ -178,7 +175,7 @@ def __init__(self, func: CommandCallback, *, name: Optional[str] = None, **kwarg except AttributeError: checks = kwargs.get("checks", []) - self.checks: List[AppCheck] = checks + self.checks: list[AppCheck] = checks try: cooldown = func.__commands_cooldown__ @@ -202,7 +199,7 @@ def __init__(self, func: CommandCallback, *, name: Optional[str] = None, **kwarg self._max_concurrency: Optional[MaxConcurrency] = max_concurrency self.cog: Optional[Cog] = None - self.guild_ids: Optional[Tuple[int, ...]] = None + self.guild_ids: Optional[tuple[int, ...]] = None self.auto_sync: bool = True self._before_invoke: Optional[Hook] = None @@ -261,7 +258,7 @@ def copy(self: AppCommandT) -> AppCommandT: copy = type(self)(self.callback, **self.__original_kwargs__) return self._ensure_assignment_on_copy(copy) - def _update_copy(self: AppCommandT, kwargs: Dict[str, Any]) -> AppCommandT: + def _update_copy(self: AppCommandT, kwargs: dict[str, Any]) -> AppCommandT: if kwargs: kw = kwargs.copy() kw.update(self.__original_kwargs__) diff --git a/disnake/ext/commands/bot.py b/disnake/ext/commands/bot.py index 9d1ec9ea65..a14286ef7a 100644 --- a/disnake/ext/commands/bot.py +++ b/disnake/ext/commands/bot.py @@ -2,7 +2,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Callable, List, Optional, Sequence, Set, Union +from collections.abc import Sequence +from typing import TYPE_CHECKING, Any, Callable, Optional, Union import disnake @@ -256,7 +257,7 @@ def __init__( *, strip_after_prefix: bool = False, owner_id: Optional[int] = None, - owner_ids: Optional[Set[int]] = None, + owner_ids: Optional[set[int]] = None, reload: bool = False, case_insensitive: bool = False, command_sync_flags: CommandSyncFlags = ..., @@ -309,7 +310,7 @@ def __init__( *, strip_after_prefix: bool = False, owner_id: Optional[int] = None, - owner_ids: Optional[Set[int]] = None, + owner_ids: Optional[set[int]] = None, reload: bool = False, case_insensitive: bool = False, command_sync_flags: CommandSyncFlags = ..., @@ -321,7 +322,7 @@ def __init__( default_contexts: Optional[InteractionContextTypes] = None, asyncio_debug: bool = False, loop: Optional[asyncio.AbstractEventLoop] = None, - shard_ids: Optional[List[int]] = None, # instead of shard_id + shard_ids: Optional[list[int]] = None, # instead of shard_id shard_count: Optional[int] = None, enable_debug_events: bool = False, enable_gateway_error_handler: bool = True, @@ -482,7 +483,7 @@ def __init__( self, *, owner_id: Optional[int] = None, - owner_ids: Optional[Set[int]] = None, + owner_ids: Optional[set[int]] = None, reload: bool = False, command_sync_flags: CommandSyncFlags = ..., sync_commands: bool = ..., @@ -528,7 +529,7 @@ def __init__( self, *, owner_id: Optional[int] = None, - owner_ids: Optional[Set[int]] = None, + owner_ids: Optional[set[int]] = None, reload: bool = False, command_sync_flags: CommandSyncFlags = ..., sync_commands: bool = ..., @@ -539,7 +540,7 @@ def __init__( default_contexts: Optional[InteractionContextTypes] = None, asyncio_debug: bool = False, loop: Optional[asyncio.AbstractEventLoop] = None, - shard_ids: Optional[List[int]] = None, # instead of shard_id + shard_ids: Optional[list[int]] = None, # instead of shard_id shard_count: Optional[int] = None, enable_debug_events: bool = False, enable_gateway_error_handler: bool = True, diff --git a/disnake/ext/commands/bot_base.py b/disnake/ext/commands/bot_base.py index ea78e35710..64d173b425 100644 --- a/disnake/ext/commands/bot_base.py +++ b/disnake/ext/commands/bot_base.py @@ -9,7 +9,8 @@ import sys import traceback import warnings -from typing import TYPE_CHECKING, Any, Callable, Iterable, List, Optional, Type, TypeVar, Union +from collections.abc import Iterable +from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union import disnake from disnake.utils import iscoroutinefunction @@ -46,7 +47,7 @@ _log = logging.getLogger(__name__) -def when_mentioned(bot: BotBase, msg: Message) -> List[str]: +def when_mentioned(bot: BotBase, msg: Message) -> list[str]: """A callable that implements a command prefix equivalent to being mentioned. These are meant to be passed into the :attr:`.Bot.command_prefix` attribute. @@ -55,7 +56,7 @@ def when_mentioned(bot: BotBase, msg: Message) -> List[str]: return [f"<@{bot.user.id}> ", f"<@!{bot.user.id}> "] # type: ignore -def when_mentioned_or(*prefixes: str) -> Callable[[BotBase, Message], List[str]]: +def when_mentioned_or(*prefixes: str) -> Callable[[BotBase, Message], list[str]]: """A callable that implements when mentioned or other prefixes provided. These are meant to be passed into the :attr:`.Bot.command_prefix` attribute. @@ -84,7 +85,7 @@ async def get_prefix(bot, message): :func:`.when_mentioned` """ - def inner(bot: BotBase, msg: Message) -> List[str]: + def inner(bot: BotBase, msg: Message) -> list[str]: r = list(prefixes) r = when_mentioned(bot, msg) + r return r @@ -151,8 +152,8 @@ def __init__( self.command_prefix = command_prefix - self._checks: List[Check] = [] - self._check_once: List[Check] = [] + self._checks: list[Check] = [] + self._check_once: list[Check] = [] self._before_invoke: Optional[CoroFunc] = None self._after_invoke: Optional[CoroFunc] = None @@ -432,7 +433,7 @@ def help_command(self, value: Optional[HelpCommand]) -> None: # command processing - async def get_prefix(self, message: Message) -> Optional[Union[List[str], str]]: + async def get_prefix(self, message: Message) -> Optional[Union[list[str], str]]: """|coro| Retrieves the prefix the bot is listening to @@ -477,7 +478,7 @@ async def get_prefix(self, message: Message) -> Optional[Union[List[str], str]]: return ret - async def get_context(self, message: Message, *, cls: Type[CXT] = Context) -> CXT: + async def get_context(self, message: Message, *, cls: type[CXT] = Context) -> CXT: """|coro| Returns the invocation context from the message. diff --git a/disnake/ext/commands/cog.py b/disnake/ext/commands/cog.py index bbf37a527c..2435893158 100644 --- a/disnake/ext/commands/cog.py +++ b/disnake/ext/commands/cog.py @@ -4,17 +4,13 @@ import inspect import logging +from collections.abc import Generator from typing import ( TYPE_CHECKING, Any, Callable, ClassVar, - Dict, - Generator, - List, Optional, - Tuple, - Type, Union, ) @@ -138,15 +134,15 @@ async def bar(self, ctx): """ __cog_name__: str - __cog_settings__: Dict[str, Any] - __cog_slash_settings__: Dict[str, Any] - __cog_user_settings__: Dict[str, Any] - __cog_message_settings__: Dict[str, Any] - __cog_commands__: List[Command[Any, ..., Any]] - __cog_app_commands__: List[InvokableApplicationCommand] - __cog_listeners__: List[Tuple[str, str]] - - def __new__(cls: Type[CogMeta], *args: Any, **kwargs: Any) -> CogMeta: + __cog_settings__: dict[str, Any] + __cog_slash_settings__: dict[str, Any] + __cog_user_settings__: dict[str, Any] + __cog_message_settings__: dict[str, Any] + __cog_commands__: list[Command[Any, ..., Any]] + __cog_app_commands__: list[InvokableApplicationCommand] + __cog_listeners__: list[tuple[str, str]] + + def __new__(cls: type[CogMeta], *args: Any, **kwargs: Any) -> CogMeta: name, bases, attrs = args attrs["__cog_name__"] = kwargs.pop("name", name) attrs["__cog_settings__"] = kwargs.pop("command_attrs", {}) @@ -229,10 +225,10 @@ class Cog(metaclass=CogMeta): """ __cog_name__: ClassVar[str] - __cog_settings__: ClassVar[Dict[str, Any]] - __cog_commands__: ClassVar[List[Command[Self, ..., Any]]] - __cog_app_commands__: ClassVar[List[InvokableApplicationCommand]] - __cog_listeners__: ClassVar[List[Tuple[str, str]]] + __cog_settings__: ClassVar[dict[str, Any]] + __cog_commands__: ClassVar[list[Command[Self, ..., Any]]] + __cog_app_commands__: ClassVar[list[InvokableApplicationCommand]] + __cog_listeners__: ClassVar[list[tuple[str, str]]] def __new__(cls, *args: Any, **kwargs: Any) -> Self: # For issue 426, we need to store a copy of the command objects @@ -245,7 +241,7 @@ def __new__(cls, *args: Any, **kwargs: Any) -> Self: message_cmd_attrs = cls.__cog_message_settings__ # Either update the command with the cog provided defaults or copy it. - cog_app_commands: List[InvokableApplicationCommand] = [] + cog_app_commands: list[InvokableApplicationCommand] = [] for c in cls.__cog_app_commands__: if isinstance(c, InvokableSlashCommand): c = c._update_copy(slash_cmd_attrs) @@ -277,7 +273,7 @@ def __new__(cls, *args: Any, **kwargs: Any) -> Self: return self - def get_commands(self) -> List[Command[Self, ..., Any]]: + def get_commands(self) -> list[Command[Self, ..., Any]]: """Returns a list of commands the cog has. Returns @@ -292,7 +288,7 @@ def get_commands(self) -> List[Command[Self, ..., Any]]: """ return [c for c in self.__cog_commands__ if c.parent is None] - def get_application_commands(self) -> List[InvokableApplicationCommand]: + def get_application_commands(self) -> list[InvokableApplicationCommand]: """Returns a list of application commands the cog has. Returns @@ -307,7 +303,7 @@ def get_application_commands(self) -> List[InvokableApplicationCommand]: """ return list(self.__cog_app_commands__) - def get_slash_commands(self) -> List[InvokableSlashCommand]: + def get_slash_commands(self) -> list[InvokableSlashCommand]: """Returns a list of slash commands the cog has. Returns @@ -322,7 +318,7 @@ def get_slash_commands(self) -> List[InvokableSlashCommand]: """ return [c for c in self.__cog_app_commands__ if isinstance(c, InvokableSlashCommand)] - def get_user_commands(self) -> List[InvokableUserCommand]: + def get_user_commands(self) -> list[InvokableUserCommand]: """Returns a list of user commands the cog has. Returns @@ -333,7 +329,7 @@ def get_user_commands(self) -> List[InvokableUserCommand]: """ return [c for c in self.__cog_app_commands__ if isinstance(c, InvokableUserCommand)] - def get_message_commands(self) -> List[InvokableMessageCommand]: + def get_message_commands(self) -> list[InvokableMessageCommand]: """Returns a list of message commands the cog has. Returns @@ -374,7 +370,7 @@ def walk_commands(self) -> Generator[Command[Self, ..., Any], None, None]: if isinstance(command, GroupMixin): yield from command.walk_commands() - def get_listeners(self) -> List[Tuple[str, Callable[..., Any]]]: + def get_listeners(self) -> list[tuple[str, Callable[..., Any]]]: """Returns a :class:`list` of (name, function) listener pairs the cog has. Returns diff --git a/disnake/ext/commands/common_bot_base.py b/disnake/ext/commands/common_bot_base.py index ea4f06e6f6..17303413d6 100644 --- a/disnake/ext/commands/common_bot_base.py +++ b/disnake/ext/commands/common_bot_base.py @@ -11,7 +11,8 @@ import sys import time import types -from typing import TYPE_CHECKING, Any, Dict, Generic, List, Mapping, Optional, Set, TypeVar, Union +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Generic, Optional, TypeVar, Union import disnake import disnake.utils @@ -38,24 +39,24 @@ def _is_submodule(parent: str, child: str) -> bool: class CommonBotBase(Generic[CogT]): if TYPE_CHECKING: - extra_events: Dict[str, List[CoroFunc]] + extra_events: dict[str, list[CoroFunc]] def __init__( self, *args: Any, owner_id: Optional[int] = None, - owner_ids: Optional[Set[int]] = None, + owner_ids: Optional[set[int]] = None, reload: bool = False, **kwargs: Any, ) -> None: - self.__cogs: Dict[str, Cog] = {} - self.__extensions: Dict[str, types.ModuleType] = {} + self.__cogs: dict[str, Cog] = {} + self.__extensions: dict[str, types.ModuleType] = {} self._is_closed: bool = False self.owner_id: Optional[int] = owner_id - self.owner_ids: Set[int] = owner_ids or set() + self.owner_ids: set[int] = owner_ids or set() self.owner: Optional[disnake.User] = None - self.owners: Set[disnake.TeamMember] = set() + self.owners: set[disnake.TeamMember] = set() if self.owner_id and self.owner_ids: msg = "Both owner_id and owner_ids are set." diff --git a/disnake/ext/commands/context.py b/disnake/ext/commands/context.py index 86112b6781..4038704937 100644 --- a/disnake/ext/commands/context.py +++ b/disnake/ext/commands/context.py @@ -4,7 +4,7 @@ import inspect import re -from typing import TYPE_CHECKING, Any, Dict, Generic, List, Optional, TypeVar, Union +from typing import TYPE_CHECKING, Any, Generic, Optional, TypeVar, Union import disnake.abc import disnake.utils @@ -103,12 +103,12 @@ def __init__( message: Message, bot: BotT, view: StringView, - args: List[Any] = MISSING, - kwargs: Dict[str, Any] = MISSING, + args: list[Any] = MISSING, + kwargs: dict[str, Any] = MISSING, prefix: Optional[str] = None, command: Optional[Command[Any, ..., Any]] = None, invoked_with: Optional[str] = None, - invoked_parents: List[str] = MISSING, + invoked_parents: list[str] = MISSING, invoked_subcommand: Optional[Command[Any, ..., Any]] = None, subcommand_passed: Optional[str] = None, command_failed: bool = False, @@ -116,13 +116,13 @@ def __init__( ) -> None: self.message: Message = message self.bot: BotT = bot - self.args: List[Any] = args or [] - self.kwargs: Dict[str, Any] = kwargs or {} + self.args: list[Any] = args or [] + self.kwargs: dict[str, Any] = kwargs or {} self.prefix: Optional[str] = prefix self.command: Optional[Command[Any, ..., Any]] = command self.view: StringView = view self.invoked_with: Optional[str] = invoked_with - self.invoked_parents: List[str] = invoked_parents or [] + self.invoked_parents: list[str] = invoked_parents or [] self.invoked_subcommand: Optional[Command[Any, ..., Any]] = invoked_subcommand self.subcommand_passed: Optional[str] = subcommand_passed self.command_failed: bool = command_failed diff --git a/disnake/ext/commands/converter.py b/disnake/ext/commands/converter.py index e26c526a15..10f714b02c 100644 --- a/disnake/ext/commands/converter.py +++ b/disnake/ext/commands/converter.py @@ -5,19 +5,15 @@ import functools import inspect import re +from collections.abc import Iterable from typing import ( TYPE_CHECKING, Any, Callable, - Dict, Generic, - Iterable, - List, Literal, Optional, Protocol, - Tuple, - Type, TypeVar, Union, runtime_checkable, @@ -383,7 +379,7 @@ class PartialMessageConverter(Converter[disnake.PartialMessage]): """ @staticmethod - def _get_id_matches(ctx: AnyContext, argument: str) -> Tuple[Optional[int], int, int]: + def _get_id_matches(ctx: AnyContext, argument: str) -> tuple[Optional[int], int, int]: id_regex = re.compile(r"(?:(?P[0-9]{17,19})-)?(?P[0-9]{17,19})$") link_regex = re.compile( r"https?://(?:(ptb|canary|www)\.)?discord(?:app)?\.com/channels/" @@ -477,7 +473,7 @@ async def convert(self, ctx: AnyContext, argument: str) -> disnake.abc.GuildChan return self._resolve_channel(ctx, argument, "channels", disnake.abc.GuildChannel) @staticmethod - def _resolve_channel(ctx: AnyContext, argument: str, attribute: str, type: Type[CT]) -> CT: + def _resolve_channel(ctx: AnyContext, argument: str, attribute: str, type: type[CT]) -> CT: bot: disnake.Client = ctx.bot match = IDConverter._get_id_match(argument) or re.match(r"<#([0-9]{17,19})>$", argument) @@ -506,7 +502,7 @@ def _resolve_channel(ctx: AnyContext, argument: str, attribute: str, type: Type[ return result @staticmethod - def _resolve_thread(ctx: AnyContext, argument: str, attribute: str, type: Type[TT]) -> TT: + def _resolve_thread(ctx: AnyContext, argument: str, attribute: str, type: type[TT]) -> TT: match = IDConverter._get_id_match(argument) or re.match(r"<#([0-9]{17,19})>$", argument) result: Optional[disnake.Thread] = None guild = ctx.guild @@ -1004,7 +1000,7 @@ async def convert(self, ctx: AnyContext, argument: str) -> disnake.Permissions: argument = argument.replace("server", "guild") # try multiple attributes, then a single one - perms: List[disnake.Permissions] = [] + perms: list[disnake.Permissions] = [] for name in argument.split(): attr = getattr(disnake.Permissions, name, None) if attr is None: @@ -1129,7 +1125,7 @@ def resolve_channel(id: int) -> str: return f"<#{id}>" - transforms: Dict[str, Callable[[int], str]] = { + transforms: dict[str, Callable[[int], str]] = { "@": resolve_user, "@!": resolve_user, "#": resolve_channel, @@ -1151,7 +1147,7 @@ def repl(match: re.Match) -> str: return disnake.utils.escape_mentions(result) -class Greedy(List[T]): +class Greedy(list[T]): """A special converter that greedily consumes arguments until it can't. As a consequence of this behaviour, most input errors are silently discarded, since it is used as an indicator of when to stop parsing. @@ -1182,7 +1178,7 @@ def __repr__(self) -> str: converter = getattr(self.converter, "__name__", repr(self.converter)) return f"Greedy[{converter}]" - def __class_getitem__(cls, params: Union[Tuple[T], T]) -> Greedy[T]: + def __class_getitem__(cls, params: Union[tuple[T], T]) -> Greedy[T]: if not isinstance(params, tuple): params = (params,) if len(params) != 1: @@ -1228,14 +1224,14 @@ def get_converter(param: inspect.Parameter) -> Any: return converter -_GenericAlias = type(List[Any]) +_GenericAlias = type(list[Any]) -def is_generic_type(tp: Any, *, _GenericAlias: Type = _GenericAlias) -> bool: +def is_generic_type(tp: Any, *, _GenericAlias: type = _GenericAlias) -> bool: return (isinstance(tp, type) and issubclass(tp, Generic)) or isinstance(tp, _GenericAlias) -CONVERTER_MAPPING: Dict[Type[Any], Type[Converter]] = { +CONVERTER_MAPPING: dict[type[Any], type[Converter]] = { disnake.Object: ObjectConverter, disnake.Member: MemberConverter, disnake.User: UserConverter, @@ -1265,7 +1261,7 @@ def is_generic_type(tp: Any, *, _GenericAlias: Type = _GenericAlias) -> bool: async def _actual_conversion( ctx: Context, - converter: Union[Type[T], Type[Converter[T]], Converter[T], Callable[[str], T]], + converter: Union[type[T], type[Converter[T]], Converter[T], Callable[[str], T]], argument: str, param: inspect.Parameter, ) -> T: @@ -1342,7 +1338,7 @@ async def run_converters( origin = getattr(converter, "__origin__", None) if origin is Union: - errors: List[CommandError] = [] + errors: list[CommandError] = [] _NoneType = type(None) union_args = converter.__args__ for conv in union_args: @@ -1364,7 +1360,7 @@ async def run_converters( raise BadUnionArgument(param, union_args, errors) if origin is Literal: - errors: List[CommandError] = [] + errors: list[CommandError] = [] conversions = {} literal_args = converter.__args__ for literal in literal_args: diff --git a/disnake/ext/commands/cooldowns.py b/disnake/ext/commands/cooldowns.py index 8b28182d48..747915c498 100644 --- a/disnake/ext/commands/cooldowns.py +++ b/disnake/ext/commands/cooldowns.py @@ -5,7 +5,7 @@ import asyncio import time from collections import deque -from typing import TYPE_CHECKING, Any, Callable, Deque, Dict, Optional +from typing import TYPE_CHECKING, Any, Callable, Optional from disnake.enums import Enum from disnake.member import Member @@ -193,7 +193,7 @@ def __init__( msg = "Cooldown type must be a BucketType or callable" raise TypeError(msg) - self._cache: Dict[Any, Cooldown] = {} + self._cache: dict[Any, Cooldown] = {} self._cooldown: Optional[Cooldown] = original self._type: Callable[[Message], Any] = type @@ -297,7 +297,7 @@ class _Semaphore: def __init__(self, number: int) -> None: self.value: int = number self.loop: asyncio.AbstractEventLoop = asyncio.get_running_loop() - self._waiters: Deque[asyncio.Future] = deque() + self._waiters: deque[asyncio.Future] = deque() def __repr__(self) -> str: return f"<_Semaphore value={self.value} waiters={len(self._waiters)}>" @@ -343,7 +343,7 @@ class MaxConcurrency: __slots__ = ("number", "per", "wait", "_mapping") def __init__(self, number: int, *, per: BucketType, wait: bool) -> None: - self._mapping: Dict[Any, _Semaphore] = {} + self._mapping: dict[Any, _Semaphore] = {} self.per: BucketType = per self.number: int = number self.wait: bool = wait diff --git a/disnake/ext/commands/core.py b/disnake/ext/commands/core.py index e2defd9197..86eb5ab8f8 100644 --- a/disnake/ext/commands/core.py +++ b/disnake/ext/commands/core.py @@ -6,20 +6,15 @@ import datetime import functools import inspect +from collections.abc import Generator from typing import ( TYPE_CHECKING, Any, Callable, - Dict, - Generator, Generic, - List, Literal, Optional, Protocol, - Set, - Tuple, - Type, TypeVar, Union, cast, @@ -167,7 +162,7 @@ async def wrapped(*args: Any, **kwargs: Any) -> Optional[T]: return wrapped -class _CaseInsensitiveDict(Dict[str, VT]): +class _CaseInsensitiveDict(dict[str, VT]): def __contains__(self, k: str) -> bool: return super().__contains__(k.casefold()) @@ -261,7 +256,7 @@ class Command(_BaseCommand, Generic[CogT, P, T]): .. versionadded:: 2.0 """ - __original_kwargs__: Dict[str, Any] + __original_kwargs__: dict[str, Any] def __new__(cls, *args: Any, **kwargs: Any) -> Self: # if you're wondering why this is done, it's because we need to ensure @@ -310,8 +305,8 @@ def __init__( self.brief: Optional[str] = kwargs.get("brief") self.usage: Optional[str] = kwargs.get("usage") self.rest_is_raw: bool = kwargs.get("rest_is_raw", False) - self.aliases: Union[List[str], Tuple[str]] = kwargs.get("aliases", []) - self.extras: Dict[str, Any] = kwargs.get("extras", {}) + self.aliases: Union[list[str], tuple[str]] = kwargs.get("aliases", []) + self.extras: dict[str, Any] = kwargs.get("extras", {}) if not isinstance(self.aliases, (list, tuple)): msg = "Aliases of a command must be a list or a tuple of strings." @@ -326,7 +321,7 @@ def __init__( except AttributeError: checks = kwargs.get("checks", []) - self.checks: List[Check] = checks + self.checks: list[Check] = checks try: cooldown = func.__commands_cooldown__ @@ -485,7 +480,7 @@ def copy(self: CommandT) -> CommandT: ret = self.__class__(self.callback, **self.__original_kwargs__) return self._ensure_assignment_on_copy(ret) - def _update_copy(self: CommandT, kwargs: Dict[str, Any]) -> CommandT: + def _update_copy(self: CommandT, kwargs: dict[str, Any]) -> CommandT: if kwargs: kw = kwargs.copy() kw.update(self.__original_kwargs__) @@ -611,7 +606,7 @@ async def _transform_greedy_var_pos( return value @property - def clean_params(self) -> Dict[str, inspect.Parameter]: + def clean_params(self) -> dict[str, inspect.Parameter]: """:class:`dict`\\[:class:`str`, :class:`inspect.Parameter`]: Retrieves the parameter dictionary without the context or self parameters. @@ -636,7 +631,7 @@ def full_parent_name(self) -> str: return " ".join(reversed(entries)) @property - def parents(self) -> List[Group[CogT, ..., Any]]: + def parents(self) -> list[Group[CogT, ..., Any]]: """:class:`list`\\[:class:`Group`]: Retrieves the parents of this command. If the command has no parents then it returns an empty :class:`list`. @@ -1004,7 +999,7 @@ def signature(self) -> str: if not params: return "" - result: List[str] = [] + result: list[str] = [] for name, param in params.items(): greedy = isinstance(param.annotation, Greedy) optional = False # postpone evaluation of if it's an optional argument @@ -1125,14 +1120,14 @@ class GroupMixin(Generic[CogT]): """ def __init__(self, *args: Any, case_insensitive: bool = False, **kwargs: Any) -> None: - self.all_commands: Dict[str, Command[CogT, Any, Any]] = ( + self.all_commands: dict[str, Command[CogT, Any, Any]] = ( _CaseInsensitiveDict() if case_insensitive else {} ) self.case_insensitive: bool = case_insensitive super().__init__(*args, **kwargs) @property - def commands(self) -> Set[Command[CogT, Any, Any]]: + def commands(self) -> set[Command[CogT, Any, Any]]: """:class:`set`\\[:class:`.Command`]: A unique set of commands without aliases that are registered.""" return set(self.all_commands.values()) @@ -1278,7 +1273,7 @@ def get_command(self, name: str) -> Optional[Command[CogT, Any, Any]]: def command( self, name: str, - cls: Type[CommandT], + cls: type[CommandT], *args: Any, **kwargs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], CommandT]: ... @@ -1288,7 +1283,7 @@ def command( self, name: str = ..., *args: Any, - cls: Type[CommandT], + cls: type[CommandT], **kwargs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], CommandT]: ... @@ -1303,7 +1298,7 @@ def command( def command( self, name: str = MISSING, - cls: Type[Command[Any, Any, Any]] = Command, + cls: type[Command[Any, Any, Any]] = Command, *args: Any, **kwargs: Any, ) -> Any: @@ -1328,7 +1323,7 @@ def decorator(func: CommandCallback[CogT, ContextT, P, T]) -> Command[Any, Any, def group( self, name: str, - cls: Type[GroupT], + cls: type[GroupT], *args: Any, **kwargs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], GroupT]: ... @@ -1338,7 +1333,7 @@ def group( self, name: str = ..., *args: Any, - cls: Type[GroupT], + cls: type[GroupT], **kwargs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], GroupT]: ... @@ -1353,7 +1348,7 @@ def group( def group( self, name: str = MISSING, - cls: Type[Group[Any, Any, Any]] = MISSING, + cls: type[Group[Any, Any, Any]] = MISSING, *args: Any, **kwargs: Any, ) -> Any: @@ -1526,7 +1521,7 @@ def __call__( @overload def command( name: str, - cls: Type[CommandT], + cls: type[CommandT], **attrs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], CommandT]: ... @@ -1535,7 +1530,7 @@ def command( def command( name: str = ..., *, - cls: Type[CommandT], + cls: type[CommandT], **attrs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], CommandT]: ... @@ -1549,7 +1544,7 @@ def command( def command( name: str = MISSING, - cls: Type[Command[Any, Any, Any]] = MISSING, + cls: type[Command[Any, Any, Any]] = MISSING, **attrs: Any, ) -> Any: """A decorator that transforms a function into a :class:`.Command` @@ -1596,7 +1591,7 @@ def decorator(func: CommandCallback[CogT, ContextT, P, T]) -> Command[Any, Any, @overload def group( name: str, - cls: Type[GroupT], + cls: type[GroupT], **attrs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], GroupT]: ... @@ -1605,7 +1600,7 @@ def group( def group( name: str = ..., *, - cls: Type[GroupT], + cls: type[GroupT], **attrs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], GroupT]: ... @@ -1619,7 +1614,7 @@ def group( def group( name: str = MISSING, - cls: Type[Group[Any, Any, Any]] = MISSING, + cls: type[Group[Any, Any, Any]] = MISSING, **attrs: Any, ) -> Any: """A decorator that transforms a function into a :class:`.Group`. diff --git a/disnake/ext/commands/ctx_menus_core.py b/disnake/ext/commands/ctx_menus_core.py index 03e3be1262..1a1e3aa59d 100644 --- a/disnake/ext/commands/ctx_menus_core.py +++ b/disnake/ext/commands/ctx_menus_core.py @@ -2,7 +2,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Sequence, Tuple, Union +from collections.abc import Sequence +from typing import TYPE_CHECKING, Any, Callable, Optional, Union from disnake.app_commands import MessageCommand, UserCommand from disnake.flags import ApplicationInstallTypes, InteractionContextTypes @@ -85,7 +86,7 @@ def __init__( ) -> None: name_loc = Localized._cast(name, False) super().__init__(func, name=name_loc.string, **kwargs) - self.guild_ids: Optional[Tuple[int, ...]] = None if guild_ids is None else tuple(guild_ids) + self.guild_ids: Optional[tuple[int, ...]] = None if guild_ids is None else tuple(guild_ids) self.auto_sync: bool = True if auto_sync is None else auto_sync try: @@ -196,7 +197,7 @@ def __init__( ) -> None: name_loc = Localized._cast(name, False) super().__init__(func, name=name_loc.string, **kwargs) - self.guild_ids: Optional[Tuple[int, ...]] = None if guild_ids is None else tuple(guild_ids) + self.guild_ids: Optional[tuple[int, ...]] = None if guild_ids is None else tuple(guild_ids) self.auto_sync: bool = True if auto_sync is None else auto_sync try: @@ -263,7 +264,7 @@ def user_command( contexts: Optional[InteractionContextTypes] = None, guild_ids: Optional[Sequence[int]] = None, auto_sync: Optional[bool] = None, - extras: Optional[Dict[str, Any]] = None, + extras: Optional[dict[str, Any]] = None, **kwargs: Any, ) -> Callable[[InteractionCommandCallback[CogT, UserCommandInteraction, P]], InvokableUserCommand]: """A shortcut decorator that builds a user command. @@ -371,7 +372,7 @@ def message_command( contexts: Optional[InteractionContextTypes] = None, guild_ids: Optional[Sequence[int]] = None, auto_sync: Optional[bool] = None, - extras: Optional[Dict[str, Any]] = None, + extras: Optional[dict[str, Any]] = None, **kwargs: Any, ) -> Callable[ [InteractionCommandCallback[CogT, MessageCommandInteraction, P]], diff --git a/disnake/ext/commands/errors.py b/disnake/ext/commands/errors.py index 0d96702bb4..a4d9ca876e 100644 --- a/disnake/ext/commands/errors.py +++ b/disnake/ext/commands/errors.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Callable, List, Optional, Tuple, Union +from typing import TYPE_CHECKING, Any, Callable, Optional, Union from disnake.errors import ClientException, DiscordException from disnake.utils import humanize_list @@ -207,10 +207,10 @@ class CheckAnyFailure(CheckFailure): """ def __init__( - self, checks: List[CheckFailure], errors: List[Callable[[AnyContext], bool]] + self, checks: list[CheckFailure], errors: list[Callable[[AnyContext], bool]] ) -> None: - self.checks: List[CheckFailure] = checks - self.errors: List[Callable[[AnyContext], bool]] = errors + self.checks: list[CheckFailure] = checks + self.errors: list[Callable[[AnyContext], bool]] = errors super().__init__("You do not have permission to run this command.") @@ -766,8 +766,8 @@ class MissingPermissions(CheckFailure): The required permissions that are missing. """ - def __init__(self, missing_permissions: List[str], *args: Any) -> None: - self.missing_permissions: List[str] = missing_permissions + def __init__(self, missing_permissions: list[str], *args: Any) -> None: + self.missing_permissions: list[str] = missing_permissions missing = [ perm.replace("_", " ").replace("guild", "server").title() @@ -791,8 +791,8 @@ class BotMissingPermissions(CheckFailure): The required permissions that are missing. """ - def __init__(self, missing_permissions: List[str], *args: Any) -> None: - self.missing_permissions: List[str] = missing_permissions + def __init__(self, missing_permissions: list[str], *args: Any) -> None: + self.missing_permissions: list[str] = missing_permissions missing = [ perm.replace("_", " ").replace("guild", "server").title() @@ -821,11 +821,11 @@ class BadUnionArgument(UserInputError): """ def __init__( - self, param: Parameter, converters: Tuple[type, ...], errors: List[CommandError] + self, param: Parameter, converters: tuple[type, ...], errors: list[CommandError] ) -> None: self.param: Parameter = param - self.converters: Tuple[type, ...] = converters - self.errors: List[CommandError] = errors + self.converters: tuple[type, ...] = converters + self.errors: list[CommandError] = errors def _get_name(x): try: @@ -860,11 +860,11 @@ class BadLiteralArgument(UserInputError): """ def __init__( - self, param: Parameter, literals: Tuple[Any, ...], errors: List[CommandError] + self, param: Parameter, literals: tuple[Any, ...], errors: list[CommandError] ) -> None: self.param: Parameter = param - self.literals: Tuple[Any, ...] = literals - self.errors: List[CommandError] = errors + self.literals: tuple[Any, ...] = literals + self.errors: list[CommandError] = errors to_string = [repr(literal) for literal in literals] fmt = humanize_list(to_string, "or") @@ -1070,9 +1070,9 @@ class TooManyFlags(FlagError): The values that were passed. """ - def __init__(self, flag: Flag, values: List[str]) -> None: + def __init__(self, flag: Flag, values: list[str]) -> None: self.flag: Flag = flag - self.values: List[str] = values + self.values: list[str] = values super().__init__( f"Too many flag values, expected {flag.max_args} but received {len(values)}." ) diff --git a/disnake/ext/commands/flag_converter.py b/disnake/ext/commands/flag_converter.py index 6121b2b3d3..45597d1b29 100644 --- a/disnake/ext/commands/flag_converter.py +++ b/disnake/ext/commands/flag_converter.py @@ -5,19 +5,14 @@ import inspect import re import sys +from collections.abc import Iterator from dataclasses import dataclass, field +from re import Pattern from typing import ( TYPE_CHECKING, Any, - Dict, - Iterator, - List, Literal, Optional, - Pattern, - Set, - Tuple, - Type, TypeVar, Union, get_args, @@ -48,7 +43,7 @@ from .context import Context -FlagsMetaT = TypeVar("FlagsMetaT", bound="Type[FlagsMeta]") +FlagsMetaT = TypeVar("FlagsMetaT", bound="type[FlagsMeta]") @dataclass @@ -79,7 +74,7 @@ class Flag: """ name: str = MISSING - aliases: List[str] = field(default_factory=list) + aliases: list[str] = field(default_factory=list) attribute: str = MISSING annotation: Any = MISSING default: Any = MISSING @@ -99,7 +94,7 @@ def required(self) -> bool: def flag( *, name: str = MISSING, - aliases: List[str] = MISSING, + aliases: list[str] = MISSING, default: Any = MISSING, max_args: int = MISSING, override: bool = MISSING, @@ -128,7 +123,7 @@ class attributes. return Flag(name=name, aliases=aliases, default=default, max_args=max_args, override=override) -def validate_flag_name(name: str, forbidden: Set[str]) -> None: +def validate_flag_name(name: str, forbidden: set[str]) -> None: if not name: msg = "flag names should not be empty" raise ValueError(msg) @@ -146,13 +141,13 @@ def validate_flag_name(name: str, forbidden: Set[str]) -> None: def get_flags( - namespace: Dict[str, Any], globals: Dict[str, Any], locals: Dict[str, Any] -) -> Dict[str, Flag]: + namespace: dict[str, Any], globals: dict[str, Any], locals: dict[str, Any] +) -> dict[str, Flag]: annotations = namespace.get("__annotations__", {}) case_insensitive = namespace["__commands_flag_case_insensitive__"] - flags: Dict[str, Flag] = {} - cache: Dict[str, Any] = {} - names: Set[str] = set() + flags: dict[str, Flag] = {} + cache: dict[str, Any] = {} + names: set[str] = set() for name, annotation in annotations.items(): flag = namespace.pop(name, MISSING) if isinstance(flag, Flag): @@ -199,19 +194,17 @@ def get_flags( # typing.Optional flag.default = None elif origin is tuple: - # typing.Tuple # tuple parsing is e.g. `flag: peter 20` # for Tuple[str, int] would give you flag: ('peter', 20) if flag.max_args is MISSING: flag.max_args = 1 elif origin is list: - # typing.List if flag.max_args is MISSING: flag.max_args = -1 elif origin is dict: - # typing.Dict[K, V] + # dict[K, V] # Equivalent to: - # typing.List[typing.Tuple[K, V]] + # list[tuple[K, V]] flag.cast_to_dict = True if flag.max_args is MISSING: flag.max_args = -1 @@ -252,8 +245,8 @@ def get_flags( class FlagsMeta(type): if TYPE_CHECKING: __commands_is_flag__: bool - __commands_flags__: Dict[str, Flag] - __commands_flag_aliases__: Dict[str, str] + __commands_flags__: dict[str, Flag] + __commands_flag_aliases__: dict[str, str] __commands_flag_regex__: Pattern[str] __commands_flag_case_insensitive__: bool __commands_flag_delimiter__: str @@ -262,8 +255,8 @@ class FlagsMeta(type): def __new__( cls: FlagsMetaT, name: str, - bases: Tuple[type, ...], - attrs: Dict[str, Any], + bases: tuple[type, ...], + attrs: dict[str, Any], *, case_insensitive: bool = MISSING, delimiter: str = MISSING, @@ -288,8 +281,8 @@ def __new__( finally: del frame - flags: Dict[str, Flag] = {} - aliases: Dict[str, str] = {} + flags: dict[str, Flag] = {} + aliases: dict[str, str] = {} for base in reversed(bases): if base.__dict__.get("__commands_is_flag__", False): flags.update(base.__dict__["__commands_flags__"]) @@ -349,7 +342,7 @@ def __new__( async def tuple_convert_all( ctx: Context, argument: str, flag: Flag, converter: Any -) -> Tuple[Any, ...]: +) -> tuple[Any, ...]: view = StringView(argument) results = [] param: inspect.Parameter = ctx.current_parameter # type: ignore @@ -376,7 +369,7 @@ async def tuple_convert_all( async def tuple_convert_flag( ctx: Context, argument: str, flag: Flag, converters: Any -) -> Tuple[Any, ...]: +) -> tuple[Any, ...]: view = StringView(argument) results = [] param: inspect.Parameter = ctx.current_parameter # type: ignore @@ -415,7 +408,7 @@ async def convert_flag(ctx: Context, argument: str, flag: Flag, annotation: Any else: return await tuple_convert_flag(ctx, argument, flag, args) elif origin is list: - # typing.List[x] + # list[x] annotation = args[0] return await convert_flag(ctx, argument, flag, annotation) elif origin is Union and args[-1] is type(None): @@ -423,7 +416,7 @@ async def convert_flag(ctx: Context, argument: str, flag: Flag, annotation: Any annotation = Union[args[:-1]] return await run_converters(ctx, annotation, argument, param) elif origin is dict: - # typing.Dict[K, V] -> typing.Tuple[K, V] + # dict[K, V] -> tuple[K, V] return await tuple_convert_flag(ctx, argument, flag, args) try: @@ -467,7 +460,7 @@ class FlagConverter(metaclass=FlagsMeta): """ @classmethod - def get_flags(cls) -> Dict[str, Flag]: + def get_flags(cls) -> dict[str, Flag]: """:class:`dict`\\[:class:`str`, :class:`Flag`]: A mapping of flag name to flag object this converter has.""" return cls.__commands_flags__.copy() @@ -475,7 +468,7 @@ def get_flags(cls) -> Dict[str, Flag]: def _can_be_constructible(cls) -> bool: return all(not flag.required for flag in cls.__commands_flags__.values()) - def __iter__(self) -> Iterator[Tuple[str, Any]]: + def __iter__(self) -> Iterator[tuple[str, Any]]: for flag in self.__class__.__commands_flags__.values(): yield (flag.name, getattr(self, flag.attribute)) @@ -501,8 +494,8 @@ def __repr__(self) -> str: return f"<{self.__class__.__name__} {pairs}>" @classmethod - def parse_flags(cls, argument: str) -> Dict[str, List[str]]: - result: Dict[str, List[str]] = {} + def parse_flags(cls, argument: str) -> dict[str, list[str]]: + result: dict[str, list[str]] = {} flags = cls.__commands_flags__ aliases = cls.__commands_flag_aliases__ last_position = 0 diff --git a/disnake/ext/commands/help.py b/disnake/ext/commands/help.py index 876c7478da..459d2bd33b 100644 --- a/disnake/ext/commands/help.py +++ b/disnake/ext/commands/help.py @@ -6,19 +6,14 @@ import functools import itertools import re +from collections.abc import Generator, Iterable, Mapping, Sequence +from re import Match from typing import ( TYPE_CHECKING, Any, Callable, ClassVar, - Dict, - Generator, - Iterable, - List, - Mapping, - Match, Optional, - Sequence, TypeVar, Union, ) @@ -112,12 +107,12 @@ def __init__( def clear(self) -> None: """Clears the paginator to have no pages.""" if self.prefix is not None: - self._current_page: List[str] = [self.prefix] + self._current_page: list[str] = [self.prefix] self._count: int = len(self.prefix) + self._linesep_len # prefix + newline else: self._current_page = [] self._count = 0 - self._pages: List[str] = [] + self._pages: list[str] = [] @property def _prefix_len(self) -> int: @@ -182,7 +177,7 @@ def __len__(self) -> int: return total + self._count @property - def pages(self) -> List[str]: + def pages(self) -> list[str]: """:class:`list`\\[:class:`str`]: Returns the rendered list of pages.""" # we have more than just the prefix in our current page if len(self._current_page) > (0 if self.prefix is None else 1): @@ -244,7 +239,7 @@ def _inject_into_cog(self, cog: CogT) -> None: original_get_commands = cog.get_commands original_walk_commands = cog.walk_commands - def wrapped_get_commands() -> List[Command[Any, ..., Any]]: + def wrapped_get_commands() -> list[Command[Any, ..., Any]]: ret = original_get_commands() ret.append(self) # pyright: ignore[reportArgumentType] return ret @@ -337,7 +332,7 @@ def __init__(self, **options: Any) -> None: attrs = options.pop("command_attrs", {}) attrs.setdefault("name", "help") attrs.setdefault("help", "Shows this message") - self.command_attrs: Dict[str, Any] = attrs + self.command_attrs: dict[str, Any] = attrs self.context: Context[AnyBot] = disnake.utils.MISSING self._command_impl: _HelpCommandImpl = _HelpCommandImpl(self, **self.command_attrs) @@ -383,10 +378,10 @@ def remove_check(self, func: Check) -> None: """ self._command_impl.remove_check(func) - def get_bot_mapping(self) -> Dict[Optional[Cog], List[Command[Any, ..., Any]]]: + def get_bot_mapping(self) -> dict[Optional[Cog], list[Command[Any, ..., Any]]]: """Retrieves the bot mapping passed to :meth:`send_bot_help`.""" bot = self.context.bot - mapping: Dict[Optional[Cog], List[Command[Any, ..., Any]]] = { + mapping: dict[Optional[Cog], list[Command[Any, ..., Any]]] = { cog: cog.get_commands() for cog in bot.cogs.values() } mapping[None] = [c for c in bot.commands if c.cog is None] @@ -552,7 +547,7 @@ async def filter_commands( *, sort: bool = False, key: Optional[Callable[[Command[Any, ..., Any]], Any]] = None, - ) -> List[Command[Any, ..., Any]]: + ) -> list[Command[Any, ..., Any]]: """|coro| Returns a filtered list of commands and optionally sorts them. @@ -600,7 +595,7 @@ async def predicate(cmd: Command[Any, ..., Any]) -> bool: except CommandError: return False - ret: List[Command[Any, ..., Any]] = [] + ret: list[Command[Any, ..., Any]] = [] for cmd in iterator: valid = await predicate(cmd) if valid: @@ -686,7 +681,7 @@ async def on_help_command_error(self, ctx: Context[BotT], error: CommandError) - pass async def send_bot_help( - self, mapping: Mapping[Optional[Cog], List[Command[Any, ..., Any]]] + self, mapping: Mapping[Optional[Cog], list[Command[Any, ..., Any]]] ) -> None: """|coro| @@ -1048,7 +1043,7 @@ async def prepare_help_command(self, ctx: Context[BotT], command: Optional[str]) await super().prepare_help_command(ctx, command) async def send_bot_help( - self, mapping: Mapping[Optional[Cog], List[Command[Any, ..., Any]]] + self, mapping: Mapping[Optional[Cog], list[Command[Any, ..., Any]]] ) -> None: ctx = self.context bot = ctx.bot @@ -1296,7 +1291,7 @@ async def prepare_help_command(self, ctx: Context[BotT], command: Optional[str]) await super().prepare_help_command(ctx, command) async def send_bot_help( - self, mapping: Mapping[Optional[Cog], List[Command[Any, ..., Any]]] + self, mapping: Mapping[Optional[Cog], list[Command[Any, ..., Any]]] ) -> None: ctx = self.context bot = ctx.bot diff --git a/disnake/ext/commands/interaction_bot_base.py b/disnake/ext/commands/interaction_bot_base.py index 6d9f57cbbf..bfa8d29d3f 100644 --- a/disnake/ext/commands/interaction_bot_base.py +++ b/disnake/ext/commands/interaction_bot_base.py @@ -7,18 +7,13 @@ import sys import traceback import warnings +from collections.abc import Iterable, Sequence from itertools import chain from typing import ( TYPE_CHECKING, Any, Callable, - Dict, - Iterable, - List, Optional, - Sequence, - Set, - Tuple, TypedDict, TypeVar, Union, @@ -73,14 +68,14 @@ class _Diff(TypedDict): - no_changes: List[ApplicationCommand] - upsert: List[ApplicationCommand] - edit: List[ApplicationCommand] - delete: List[ApplicationCommand] - delete_ignored: NotRequired[List[ApplicationCommand]] + no_changes: list[ApplicationCommand] + upsert: list[ApplicationCommand] + edit: list[ApplicationCommand] + delete: list[ApplicationCommand] + delete_ignored: NotRequired[list[ApplicationCommand]] -def _get_to_send_from_diff(diff: _Diff) -> List[ApplicationCommand]: +def _get_to_send_from_diff(diff: _Diff) -> list[ApplicationCommand]: return diff["no_changes"] + diff["upsert"] + diff["edit"] + diff.get("delete_ignored", []) @@ -127,7 +122,7 @@ def _app_commands_diff( def _format_diff(diff: _Diff) -> str: - lines: List[str] = [] + lines: list[str] = [] for key, label in _diff_map.items(): if key not in diff: continue @@ -160,7 +155,7 @@ def __init__( super().__init__(**options) test_guilds = None if test_guilds is None else tuple(test_guilds) - self._test_guilds: Optional[Tuple[int, ...]] = test_guilds + self._test_guilds: Optional[tuple[int, ...]] = test_guilds if command_sync_flags is not None and ( sync_commands is not MISSING @@ -219,9 +214,9 @@ def __init__( self._before_message_command_invoke = None self._after_message_command_invoke = None - self.all_slash_commands: Dict[str, InvokableSlashCommand] = {} - self.all_user_commands: Dict[str, InvokableUserCommand] = {} - self.all_message_commands: Dict[str, InvokableMessageCommand] = {} + self.all_slash_commands: dict[str, InvokableSlashCommand] = {} + self.all_user_commands: dict[str, InvokableUserCommand] = {} + self.all_message_commands: dict[str, InvokableMessageCommand] = {} @disnake.utils.copy_doc(disnake.Client.login) async def login(self, token: str) -> None: @@ -245,22 +240,22 @@ def application_commands_iterator(self) -> Iterable[InvokableApplicationCommand] ) @property - def application_commands(self) -> Set[InvokableApplicationCommand]: + def application_commands(self) -> set[InvokableApplicationCommand]: """:class:`set`\\[:class:`InvokableApplicationCommand`]: A set of all application commands the bot has.""" return set(self.application_commands_iterator()) @property - def slash_commands(self) -> Set[InvokableSlashCommand]: + def slash_commands(self) -> set[InvokableSlashCommand]: """:class:`set`\\[:class:`InvokableSlashCommand`]: A set of all slash commands the bot has.""" return set(self.all_slash_commands.values()) @property - def user_commands(self) -> Set[InvokableUserCommand]: + def user_commands(self) -> set[InvokableUserCommand]: """:class:`set`\\[:class:`InvokableUserCommand`]: A set of all user commands the bot has.""" return set(self.all_user_commands.values()) @property - def message_commands(self) -> Set[InvokableMessageCommand]: + def message_commands(self) -> set[InvokableMessageCommand]: """:class:`set`\\[:class:`InvokableMessageCommand`]: A set of all message commands the bot has.""" return set(self.all_message_commands.values()) @@ -505,11 +500,11 @@ def slash_command( nsfw: Optional[bool] = None, install_types: Optional[ApplicationInstallTypes] = None, contexts: Optional[InteractionContextTypes] = None, - options: Optional[List[Option]] = None, + options: Optional[list[Option]] = None, guild_ids: Optional[Sequence[int]] = None, - connectors: Optional[Dict[str, str]] = None, + connectors: Optional[dict[str, str]] = None, auto_sync: Optional[bool] = None, - extras: Optional[Dict[str, Any]] = None, + extras: Optional[dict[str, Any]] = None, **kwargs: Any, ) -> Callable[[CommandCallback], InvokableSlashCommand]: """A shortcut decorator that invokes :func:`~disnake.ext.commands.slash_command` and adds it to @@ -626,7 +621,7 @@ def user_command( contexts: Optional[InteractionContextTypes] = None, guild_ids: Optional[Sequence[int]] = None, auto_sync: Optional[bool] = None, - extras: Optional[Dict[str, Any]] = None, + extras: Optional[dict[str, Any]] = None, **kwargs: Any, ) -> Callable[ [InteractionCommandCallback[CogT, UserCommandInteraction, P]], InvokableUserCommand @@ -729,7 +724,7 @@ def message_command( contexts: Optional[InteractionContextTypes] = None, guild_ids: Optional[Sequence[int]] = None, auto_sync: Optional[bool] = None, - extras: Optional[Dict[str, Any]] = None, + extras: Optional[dict[str, Any]] = None, **kwargs: Any, ) -> Callable[ [InteractionCommandCallback[CogT, MessageCommandInteraction, P]], InvokableMessageCommand @@ -825,9 +820,9 @@ def decorator( def _ordered_unsynced_commands( self, test_guilds: Optional[Sequence[int]] = None - ) -> Tuple[List[ApplicationCommand], Dict[int, List[ApplicationCommand]]]: - global_cmds: List[ApplicationCommand] = [] - guilds: Dict[int, List[ApplicationCommand]] = {} + ) -> tuple[list[ApplicationCommand], dict[int, list[ApplicationCommand]]]: + global_cmds: list[ApplicationCommand] = [] + guilds: dict[int, list[ApplicationCommand]] = {} for cmd in self.application_commands_iterator(): if not cmd.auto_sync: diff --git a/disnake/ext/commands/params.py b/disnake/ext/commands/params.py index 51d9a31f64..c13b453d64 100644 --- a/disnake/ext/commands/params.py +++ b/disnake/ext/commands/params.py @@ -13,6 +13,7 @@ import sys import types from abc import ABC, abstractmethod +from collections.abc import Sequence from dataclasses import dataclass from enum import Enum, EnumMeta from typing import ( @@ -20,17 +21,11 @@ Any, Callable, ClassVar, - Dict, Final, - FrozenSet, Generic, - List, Literal, NoReturn, Optional, - Sequence, - Tuple, - Type, TypeVar, Union, cast, @@ -98,7 +93,7 @@ EllipsisType = type(Ellipsis) T = TypeVar("T", bound=Any) -TypeT = TypeVar("TypeT", bound=Type[Any]) +TypeT = TypeVar("TypeT", bound=type[Any]) BotT = TypeVar("BotT", bound="disnake.Client", covariant=True) __all__ = ( @@ -117,7 +112,7 @@ ) -def issubclass_(obj: Any, tp: Union[TypeT, Tuple[TypeT, ...]]) -> TypeGuard[TypeT]: +def issubclass_(obj: Any, tp: Union[TypeT, tuple[TypeT, ...]]) -> TypeGuard[TypeT]: """Similar to the builtin `issubclass`, but more lenient. Can also handle unions (`issubclass(int | str, int)`) and generic types (`issubclass(X[T], X)`) in the first argument. @@ -188,23 +183,23 @@ class Injection(Generic[P, T_]): .. versionadded:: 2.6 """ - _registered: ClassVar[Dict[Any, Injection]] = {} + _registered: ClassVar[dict[Any, Injection]] = {} def __init__( self, function: InjectionCallback[CogT, P, T_], *, - autocompleters: Optional[Dict[str, Callable]] = None, + autocompleters: Optional[dict[str, Callable]] = None, ) -> None: if autocompleters is not None: for autocomp in autocompleters.values(): classify_autocompleter(autocomp) self.function: InjectionCallback[Any, P, T_] = function - self.autocompleters: Dict[str, Callable] = autocompleters or {} + self.autocompleters: dict[str, Callable] = autocompleters or {} self._injected: Optional[Cog] = None - def __get__(self, obj: Optional[Any], _: Type[Any]) -> Self: + def __get__(self, obj: Optional[Any], _: type[Any]) -> Self: if obj is None: return self @@ -230,7 +225,7 @@ def register( function: InjectionCallback[CogT, P, T_], annotation: Any, *, - autocompleters: Optional[Dict[str, Callable]] = None, + autocompleters: Optional[dict[str, Callable]] = None, ) -> Injection[P, T_]: self = cls(function, autocompleters=autocompleters) cls._registered[annotation] = self @@ -273,13 +268,13 @@ def decorator(func: FuncT) -> FuncT: class _BaseRange(ABC): """Internal base type for supporting ``Range[...]`` and ``String[...]``.""" - _allowed_types: ClassVar[Tuple[Type[Any], ...]] + _allowed_types: ClassVar[tuple[type[Any], ...]] - underlying_type: Type[Any] + underlying_type: type[Any] min_value: Optional[Union[int, float]] max_value: Optional[Union[int, float]] - def __class_getitem__(cls, params: Tuple[Any, ...]) -> Self: + def __class_getitem__(cls, params: tuple[Any, ...]) -> Self: # deconstruct type arguments if not isinstance(params, tuple): params = (params,) @@ -353,7 +348,7 @@ def __repr__(self) -> str: @classmethod @abstractmethod - def _infer_type(cls, params: Tuple[Any, ...]) -> Type[Any]: + def _infer_type(cls, params: tuple[Any, ...]) -> type[Any]: raise NotImplementedError # hack to get `typing._type_check` to pass, e.g. when using `Range` as a generic parameter @@ -369,7 +364,7 @@ def __or__(self, other): if TYPE_CHECKING: # aliased import since mypy doesn't understand `Range = Annotated` - from typing_extensions import Annotated as Range, Annotated as String + from typing import Annotated as Range, Annotated as String else: @dataclass(frozen=True, repr=False) @@ -397,7 +392,7 @@ def __post_init__(self) -> None: raise TypeError(msg) @classmethod - def _infer_type(cls, params: Tuple[Any, ...]) -> Type[Any]: + def _infer_type(cls, params: tuple[Any, ...]) -> type[Any]: if any(isinstance(p, float) for p in params): return float return int @@ -430,7 +425,7 @@ def __post_init__(self) -> None: raise ValueError(msg) @classmethod - def _infer_type(cls, params: Tuple[Any, ...]) -> Type[Any]: + def _infer_type(cls, params: tuple[Any, ...]) -> type[Any]: return str @@ -439,7 +434,7 @@ class LargeInt(int): # option types that require additional handling in verify_type -_VERIFY_TYPES: Final[FrozenSet[OptionType]] = frozenset((OptionType.user, OptionType.mentionable)) +_VERIFY_TYPES: Final[frozenset[OptionType]] = frozenset((OptionType.user, OptionType.mentionable)) class ParamInfo: @@ -490,7 +485,7 @@ class ParamInfo: .. versionadded:: 2.6 """ - TYPES: ClassVar[Dict[Union[type, UnionType], int]] = { + TYPES: ClassVar[dict[Union[type, UnionType], int]] = { str: OptionType.string.value, int: OptionType.integer.value, bool: OptionType.boolean.value, @@ -508,7 +503,7 @@ class ParamInfo: float: OptionType.number.value, disnake.Attachment: OptionType.attachment.value, } # fmt: skip - _registered_converters: ClassVar[Dict[type, Callable[..., Any]]] = {} + _registered_converters: ClassVar[dict[type, Callable[..., Any]]] = {} def __init__( self, @@ -521,7 +516,7 @@ def __init__( autocomplete: Optional[AnyAutocompleter] = None, choices: Optional[Choices] = None, type: Optional[type] = None, - channel_types: Optional[List[ChannelType]] = None, + channel_types: Optional[list[ChannelType]] = None, lt: Optional[float] = None, le: Optional[float] = None, gt: Optional[float] = None, @@ -604,8 +599,8 @@ def discord_type(self, discord_type: OptionType) -> None: def from_param( cls, param: inspect.Parameter, - type_hints: Dict[str, Any], - parsed_docstring: Optional[Dict[str, disnake.utils._DocstringParam]] = None, + type_hints: dict[str, Any], + parsed_docstring: Optional[dict[str, disnake.utils._DocstringParam]] = None, ) -> Self: # hopefully repeated parsing won't cause any problems parsed_docstring = parsed_docstring or {} @@ -701,7 +696,7 @@ def _parse_enum(self, annotation: Any) -> None: self.type = type(self.choices[0].value) def _parse_guild_channel( - self, *channels: Union[Type[disnake.abc.GuildChannel], Type[disnake.Thread]] + self, *channels: Union[type[disnake.abc.GuildChannel], type[disnake.Thread]] ) -> None: # this variable continues to be GuildChannel because the type is still # determined from the TYPE mapping in the class definition @@ -877,8 +872,8 @@ def safe_call(function: Callable[..., T], /, *possible_args: Any, **possible_kwa raise TypeError(msg) parsed_pos = False - args: List[Any] = [] - kwargs: Dict[str, Any] = {} + args: list[Any] = [] + kwargs: dict[str, Any] = {} for index, parameter, posarg in itertools.zip_longest( itertools.count(), @@ -912,8 +907,8 @@ def safe_call(function: Callable[..., T], /, *possible_args: Any, **possible_kwa def isolate_self( function: Callable[..., Any], - parameters: Optional[Dict[str, inspect.Parameter]] = None, -) -> Tuple[Tuple[Optional[inspect.Parameter], ...], Dict[str, inspect.Parameter]]: + parameters: Optional[dict[str, inspect.Parameter]] = None, +) -> tuple[tuple[Optional[inspect.Parameter], ...], dict[str, inspect.Parameter]]: """Create parameters without self and the first interaction. Optionally accepts a `{str: inspect.Parameter}` dict as an optimization, @@ -978,8 +973,8 @@ def classify_autocompleter(autocompleter: AnyAutocompleter) -> None: def collect_params( function: Callable[..., Any], - parameters: Optional[Dict[str, inspect.Parameter]] = None, -) -> Tuple[Optional[str], Optional[str], List[ParamInfo], Dict[str, Injection]]: + parameters: Optional[dict[str, inspect.Parameter]] = None, +) -> tuple[Optional[str], Optional[str], list[ParamInfo], dict[str, Injection]]: """Collect all parameters in a function. Optionally accepts a `{str: inspect.Parameter}` dict as an optimization. @@ -990,8 +985,8 @@ def collect_params( doc = disnake.utils.parse_docstring(function)["params"] - paraminfos: List[ParamInfo] = [] - injections: Dict[str, Injection] = {} + paraminfos: list[ParamInfo] = [] + injections: dict[str, Injection] = {} for parameter in parameters.values(): if parameter.kind in [parameter.VAR_POSITIONAL, parameter.VAR_KEYWORD]: @@ -1029,7 +1024,7 @@ def collect_params( ) -def collect_nested_params(function: Callable[..., Any]) -> List[ParamInfo]: +def collect_nested_params(function: Callable[..., Any]) -> list[ParamInfo]: """Collect all options from a function""" # TODO: Have these be actually sorted properly and not have injections always at the end _, _, paraminfos, injections = collect_params(function) @@ -1047,7 +1042,7 @@ def format_kwargs( /, *args: Any, **kwargs: Any, -) -> Dict[str, Any]: +) -> dict[str, Any]: """Create kwargs from appropriate information""" first = args[0] if args else None @@ -1069,15 +1064,15 @@ def format_kwargs( async def run_injections( - injections: Dict[str, Injection], + injections: dict[str, Injection], interaction: ApplicationCommandInteraction, /, *args: Any, **kwargs: Any, -) -> Dict[str, Any]: +) -> dict[str, Any]: """Run and resolve a list of injections""" - async def _helper(name: str, injection: Injection) -> Tuple[str, Any]: + async def _helper(name: str, injection: Injection) -> tuple[str, Any]: return name, await call_param_func(injection.function, interaction, *args, **kwargs) resolved = await asyncio.gather(*(_helper(name, i) for name, i in injections.items())) @@ -1108,7 +1103,7 @@ async def call_param_func( return await maybe_coroutine(safe_call, function, **kwargs) -def expand_params(command: AnySlashCommand) -> List[Option]: +def expand_params(command: AnySlashCommand) -> list[Option]: """Update an option with its params *in-place* Returns the created options @@ -1158,7 +1153,7 @@ def Param( converter: Optional[Callable[[ApplicationCommandInteraction[BotT], Any], Any]] = None, convert_defaults: bool = False, autocomplete: Optional[AnyAutocompleter] = None, - channel_types: Optional[List[ChannelType]] = None, + channel_types: Optional[list[ChannelType]] = None, lt: Optional[float] = None, le: Optional[float] = None, gt: Optional[float] = None, @@ -1284,7 +1279,7 @@ def Param( def inject( function: Callable[..., Any], *, - autocompleters: Optional[Dict[str, Callable]] = None, + autocompleters: Optional[dict[str, Callable]] = None, ) -> Any: """A special function to use the provided function for injections. This should be assigned to a parameter of a function representing your slash command. @@ -1321,7 +1316,7 @@ def inject( def injection( *, - autocompleters: Optional[Dict[str, Callable]] = None, + autocompleters: Optional[dict[str, Callable]] = None, ) -> Callable[[Callable[..., Any]], Any]: """Decorator interface for :func:`inject`. You can then assign this value to your slash commands' parameters. @@ -1354,8 +1349,8 @@ def decorator(function: Callable[..., Any]) -> Injection: def option_enum( - choices: Union[Dict[str, TChoice], List[TChoice]], **kwargs: TChoice -) -> Type[TChoice]: + choices: Union[dict[str, TChoice], list[TChoice]], **kwargs: TChoice +) -> type[TChoice]: """A utility function to create an enum type. Returns a new :class:`~enum.Enum` based on the provided parameters. @@ -1403,7 +1398,7 @@ def converter_method(function: Any) -> ConverterMethod: def register_injection( function: InjectionCallback[CogT, P, T_], *, - autocompleters: Optional[Dict[str, Callable]] = None, + autocompleters: Optional[dict[str, Callable]] = None, ) -> Injection[P, T_]: """A decorator to register a global injection. diff --git a/disnake/ext/commands/slash_core.py b/disnake/ext/commands/slash_core.py index 8a39a8b476..091cd7a862 100644 --- a/disnake/ext/commands/slash_core.py +++ b/disnake/ext/commands/slash_core.py @@ -4,15 +4,12 @@ import asyncio import inspect +from collections.abc import Sequence from typing import ( TYPE_CHECKING, Any, Callable, - Dict, - List, Optional, - Sequence, - Tuple, TypeVar, Union, ) @@ -106,7 +103,7 @@ async def _call_autocompleter( # this is just a helpful message for users trying to set specific # top-level-only fields on subcommands or groups -def _check_invalid_sub_kwargs(func: CommandCallback, kwargs: Dict[str, Any]) -> None: +def _check_invalid_sub_kwargs(func: CommandCallback, kwargs: dict[str, Any]) -> None: invalid_keys = kwargs.keys() & _INVALID_SUB_KWARGS for decorator_key in [ @@ -172,7 +169,7 @@ def __init__( name_loc = Localized._cast(name, False) super().__init__(func, name=name_loc.string, **kwargs) self.parent: InvokableSlashCommand = parent - self.children: Dict[str, SubCommand] = {} + self.children: dict[str, SubCommand] = {} # while subcommand groups don't have a description, parse the docstring regardless to # retrieve the localization key, if any @@ -198,7 +195,7 @@ def root_parent(self) -> InvokableSlashCommand: return self.parent @property - def parents(self) -> Tuple[InvokableSlashCommand]: + def parents(self) -> tuple[InvokableSlashCommand]: """:class:`tuple`\\[:class:`InvokableSlashCommand`]: Returns all parents of this group. .. versionadded:: 2.6 @@ -213,9 +210,9 @@ def sub_command( self, name: LocalizedOptional = None, description: LocalizedOptional = None, - options: Optional[List[Option]] = None, - connectors: Optional[Dict[str, str]] = None, - extras: Optional[Dict[str, Any]] = None, + options: Optional[list[Option]] = None, + connectors: Optional[dict[str, str]] = None, + extras: Optional[dict[str, Any]] = None, **kwargs: Any, ) -> Callable[[CommandCallback], SubCommand]: """A decorator that creates a subcommand in the subcommand group. @@ -293,15 +290,15 @@ def __init__( *, name: LocalizedOptional = None, description: LocalizedOptional = None, - options: Optional[List[Option]] = None, - connectors: Optional[Dict[str, str]] = None, + options: Optional[list[Option]] = None, + connectors: Optional[dict[str, str]] = None, **kwargs: Any, ) -> None: name_loc = Localized._cast(name, False) super().__init__(func, name=name_loc.string, **kwargs) self.parent: Union[InvokableSlashCommand, SubCommandGroup] = parent - self.connectors: Dict[str, str] = connectors or {} - self.autocompleters: Dict[str, Union[Choices, Callable[..., Optional[Choices]]]] = ( + self.connectors: dict[str, str] = connectors or {} + self.autocompleters: dict[str, Union[Choices, Callable[..., Optional[Choices]]]] = ( kwargs.get("autocompleters", {}) ) @@ -335,7 +332,7 @@ def root_parent(self) -> InvokableSlashCommand: @property def parents( self, - ) -> Union[Tuple[InvokableSlashCommand], Tuple[SubCommandGroup, InvokableSlashCommand]]: + ) -> Union[tuple[InvokableSlashCommand], tuple[SubCommandGroup, InvokableSlashCommand]]: """:class:`tuple`\\[:class:`InvokableSlashCommand`] | :class:`tuple`\\[:class:`SubCommandGroup`, :class:`InvokableSlashCommand`]: Returns all parents of this subcommand. @@ -450,25 +447,25 @@ def __init__( *, name: LocalizedOptional = None, description: LocalizedOptional = None, - options: Optional[List[Option]] = None, + options: Optional[list[Option]] = None, dm_permission: Optional[bool] = None, # deprecated default_member_permissions: Optional[Union[Permissions, int]] = None, nsfw: Optional[bool] = None, install_types: Optional[ApplicationInstallTypes] = None, contexts: Optional[InteractionContextTypes] = None, guild_ids: Optional[Sequence[int]] = None, - connectors: Optional[Dict[str, str]] = None, + connectors: Optional[dict[str, str]] = None, auto_sync: Optional[bool] = None, **kwargs: Any, ) -> None: name_loc = Localized._cast(name, False) super().__init__(func, name=name_loc.string, **kwargs) self.parent = None - self.connectors: Dict[str, str] = connectors or {} - self.children: Dict[str, Union[SubCommand, SubCommandGroup]] = {} + self.connectors: dict[str, str] = connectors or {} + self.children: dict[str, Union[SubCommand, SubCommandGroup]] = {} self.auto_sync: bool = True if auto_sync is None else auto_sync - self.guild_ids: Optional[Tuple[int, ...]] = None if guild_ids is None else tuple(guild_ids) - self.autocompleters: Dict[str, Union[Choices, Callable[..., Optional[Choices]]]] = ( + self.guild_ids: Optional[tuple[int, ...]] = None if guild_ids is None else tuple(guild_ids) + self.autocompleters: dict[str, Union[Choices, Callable[..., Optional[Choices]]]] = ( kwargs.get("autocompleters", {}) ) @@ -515,7 +512,7 @@ def root_parent(self) -> None: return None @property - def parents(self) -> Tuple[()]: + def parents(self) -> tuple[()]: """:class:`tuple`\\[()]: This is mainly for consistency with :class:`SubCommand`, and is equivalent to an empty tuple. .. versionadded:: 2.6 @@ -546,7 +543,7 @@ def description(self) -> str: return self.body.description @property - def options(self) -> List[Option]: + def options(self) -> list[Option]: """:class:`list`\\[:class:`.Option`]: The list of options the slash command has. Shorthand for :attr:`self.body.options <.SlashCommand.options>`.""" return self.body.options @@ -554,9 +551,9 @@ def sub_command( self, name: LocalizedOptional = None, description: LocalizedOptional = None, - options: Optional[List[Option]] = None, - connectors: Optional[Dict[str, str]] = None, - extras: Optional[Dict[str, Any]] = None, + options: Optional[list[Option]] = None, + connectors: Optional[dict[str, str]] = None, + extras: Optional[dict[str, Any]] = None, **kwargs: Any, ) -> Callable[[CommandCallback], SubCommand]: """A decorator that creates a subcommand under the base command. @@ -618,7 +615,7 @@ def decorator(func: CommandCallback) -> SubCommand: def sub_command_group( self, name: LocalizedOptional = None, - extras: Optional[Dict[str, Any]] = None, + extras: Optional[dict[str, Any]] = None, **kwargs: Any, ) -> Callable[[CommandCallback], SubCommandGroup]: """A decorator that creates a subcommand group under the base command. @@ -790,11 +787,11 @@ def slash_command( nsfw: Optional[bool] = None, install_types: Optional[ApplicationInstallTypes] = None, contexts: Optional[InteractionContextTypes] = None, - options: Optional[List[Option]] = None, + options: Optional[list[Option]] = None, guild_ids: Optional[Sequence[int]] = None, - connectors: Optional[Dict[str, str]] = None, + connectors: Optional[dict[str, str]] = None, auto_sync: Optional[bool] = None, - extras: Optional[Dict[str, Any]] = None, + extras: Optional[dict[str, Any]] = None, **kwargs: Any, ) -> Callable[[CommandCallback], InvokableSlashCommand]: """A decorator that builds a slash command. diff --git a/disnake/ext/mypy_plugin/__init__.py b/disnake/ext/mypy_plugin/__init__.py index 97b23df5da..6c6367cde3 100644 --- a/disnake/ext/mypy_plugin/__init__.py +++ b/disnake/ext/mypy_plugin/__init__.py @@ -1,6 +1,5 @@ # SPDX-License-Identifier: MIT -import typing as t from mypy.plugin import Plugin @@ -10,5 +9,5 @@ class DisnakePlugin(Plugin): """Custom mypy plugin; no-op as of version 2.9.""" -def plugin(version: str) -> t.Type[Plugin]: +def plugin(version: str) -> type[Plugin]: return DisnakePlugin diff --git a/disnake/ext/tasks/__init__.py b/disnake/ext/tasks/__init__.py index 085a889c6e..da7337ca09 100644 --- a/disnake/ext/tasks/__init__.py +++ b/disnake/ext/tasks/__init__.py @@ -7,17 +7,14 @@ import inspect import sys import traceback -from collections.abc import Sequence +from collections.abc import Coroutine, Sequence from typing import ( TYPE_CHECKING, Any, Callable, - Coroutine, Generic, - List, Optional, Protocol, - Type, TypeVar, Union, cast, @@ -198,7 +195,7 @@ async def _loop(self, *args: Any, **kwargs: Any) -> None: self._stop_next_iteration = False self._has_failed = False - def __get__(self, obj: T, objtype: Type[T]) -> Self: + def __get__(self, obj: T, objtype: type[T]) -> Self: if obj is None: return self clone = self.clone() @@ -254,7 +251,7 @@ def hours(self) -> Optional[float]: return self._hours @property - def time(self) -> Optional[List[datetime.time]]: + def time(self) -> Optional[list[datetime.time]]: """:class:`list`\\[:class:`datetime.time`] | :data:`None`: Read-only list for the exact times this loop runs at. :data:`None` if relative times were passed instead. @@ -383,7 +380,7 @@ def restart_when_over(fut: Any, *, args: Any = args, kwargs: Any = kwargs) -> No self._task.add_done_callback(restart_when_over) self._task.cancel() - def add_exception_type(self, *exceptions: Type[BaseException]) -> None: + def add_exception_type(self, *exceptions: type[BaseException]) -> None: """Adds exception types to be handled during the reconnect logic. By default the exception types handled are those handled by @@ -422,7 +419,7 @@ def clear_exception_types(self) -> None: """ self._valid_exception = () - def remove_exception_type(self, *exceptions: Type[BaseException]) -> bool: + def remove_exception_type(self, *exceptions: type[BaseException]) -> bool: """Removes exception types from being handled during the reconnect logic. Parameters @@ -610,9 +607,9 @@ def _get_time_parameter( self, time: Union[datetime.time, Sequence[datetime.time]], *, - dt: Type[datetime.time] = datetime.time, + dt: type[datetime.time] = datetime.time, utc: datetime.timezone = datetime.timezone.utc, - ) -> List[datetime.time]: + ) -> list[datetime.time]: if isinstance(time, dt): inner = time if time.tzinfo is not None else time.replace(tzinfo=utc) return [inner] @@ -623,7 +620,7 @@ def _get_time_parameter( msg = "time parameter must not be an empty sequence." raise ValueError(msg) - ret: List[datetime.time] = [] + ret: list[datetime.time] = [] for index, t in enumerate(time): if not isinstance(t, dt): msg = f"Expected a sequence of {dt!r} for ``time``, received {type(t).__name__!r} at index {index} instead." @@ -685,7 +682,7 @@ def change_interval( self._seconds = float(seconds) self._hours = float(hours) self._minutes = float(minutes) - self._time: List[datetime.time] = MISSING + self._time: list[datetime.time] = MISSING else: if any((seconds, minutes, hours)): msg = "Cannot mix explicit time with relative time" @@ -731,12 +728,12 @@ def loop( @overload def loop( - cls: Type[Object[L_co, Concatenate[LF, P]]], *_: P.args, **kwargs: P.kwargs + cls: type[Object[L_co, Concatenate[LF, P]]], *_: P.args, **kwargs: P.kwargs ) -> Callable[[LF], L_co]: ... def loop( - cls: Type[Object[L_co, Concatenate[LF, P]]] = Loop[Any], + cls: type[Object[L_co, Concatenate[LF, P]]] = Loop[Any], **kwargs: Any, ) -> Callable[[LF], L_co]: """A decorator that schedules a task in the background for you with @@ -803,6 +800,6 @@ def decorator(func: LF) -> L_co: msg = "The decorated function must be a coroutine function." raise TypeError(msg) - return cast("Type[L_co]", cls)(func, **kwargs) + return cast("type[L_co]", cls)(func, **kwargs) return decorator diff --git a/disnake/flags.py b/disnake/flags.py index d7db1aa3bc..ad36b05a90 100644 --- a/disnake/flags.py +++ b/disnake/flags.py @@ -4,20 +4,15 @@ import functools import operator +from collections.abc import Iterator, Sequence from typing import ( TYPE_CHECKING, Any, Callable, ClassVar, - Dict, Generic, - Iterator, - List, NoReturn, Optional, - Sequence, - Tuple, - Type, TypeVar, Union, overload, @@ -55,7 +50,7 @@ class flag_value(Generic[T]): def __init__(self, func: Callable[[Any], int]) -> None: self.flag = func(None) self.__doc__ = func.__doc__ - self._parent: Type[T] = MISSING + self._parent: type[T] = MISSING def __eq__(self, other: Any) -> bool: if isinstance(other, flag_value): @@ -85,12 +80,12 @@ def __invert__(self: flag_value[T]) -> T: return ~self._parent._from_value(self.flag) @overload - def __get__(self, instance: None, owner: Type[BF]) -> flag_value[BF]: ... + def __get__(self, instance: None, owner: type[BF]) -> flag_value[BF]: ... @overload - def __get__(self, instance: BF, owner: Type[BF]) -> bool: ... + def __get__(self, instance: BF, owner: type[BF]) -> bool: ... - def __get__(self, instance: Optional[BF], owner: Type[BF]) -> Any: + def __get__(self, instance: Optional[BF], owner: type[BF]) -> Any: if instance is None: return self return instance._has_flag(self.flag) @@ -106,12 +101,12 @@ class alias_flag_value(flag_value[T]): pass -def all_flags_value(flags: Dict[str, int]) -> int: +def all_flags_value(flags: dict[str, int]) -> int: return functools.reduce(operator.or_, flags.values()) class BaseFlags: - VALID_FLAGS: ClassVar[Dict[str, int]] + VALID_FLAGS: ClassVar[dict[str, int]] DEFAULT_VALUE: ClassVar[int] value: int @@ -127,7 +122,7 @@ def __init__(self, **kwargs: bool) -> None: setattr(self, key, value) @classmethod - def __init_subclass__(cls, inverted: bool = False, no_fill_flags: bool = False) -> Type[Self]: + def __init_subclass__(cls, inverted: bool = False, no_fill_flags: bool = False) -> type[Self]: # add a way to bypass filling flags, eg for ListBaseFlags. if no_fill_flags: return cls @@ -262,7 +257,7 @@ def __hash__(self) -> int: def __repr__(self) -> str: return f"<{self.__class__.__name__} value={self.value}>" - def __iter__(self) -> Iterator[Tuple[str, bool]]: + def __iter__(self) -> Iterator[tuple[str, bool]]: for name, value in self.__class__.__dict__.items(): if isinstance(value, alias_flag_value): continue @@ -306,7 +301,7 @@ def _from_values(cls, values: Sequence[int]) -> Self: return self @property - def values(self) -> List[int]: + def values(self) -> list[int]: # This essentially converts an int like `0b100110` into `[1, 2, 5]`, # i.e. the exponents of set bits in `self.value`. # This may look weird but interestingly it's by far the @@ -943,7 +938,7 @@ def active_developer(self) -> int: """ return UserFlags.active_developer.value - def all(self) -> List[UserFlags]: + def all(self) -> list[UserFlags]: """:class:`list`\\[:class:`UserFlags`]: Returns all public flags the user has.""" return [public_flag for public_flag in UserFlags if self._has_flag(public_flag.value)] diff --git a/disnake/gateway.py b/disnake/gateway.py index daeaf1e23c..b96ac46728 100644 --- a/disnake/gateway.py +++ b/disnake/gateway.py @@ -16,10 +16,7 @@ TYPE_CHECKING, Any, Callable, - Deque, - Dict, Final, - List, Literal, NamedTuple, Optional, @@ -101,9 +98,9 @@ class WebSocketClosure(Exception): class EventListener(NamedTuple): - predicate: Callable[[Dict[str, Any]], bool] + predicate: Callable[[dict[str, Any]], bool] event: str - result: Optional[Callable[[Dict[str, Any]], Any]] + result: Optional[Callable[[dict[str, Any]], Any]] future: asyncio.Future[Any] @@ -254,7 +251,7 @@ def ack(self) -> None: class VoiceKeepAliveHandler(KeepAliveHandler): def __init__(self, *args: Any, ws: HeartbeatWebSocket, interval: float, **kwargs: Any) -> None: super().__init__(*args, ws=ws, interval=interval, **kwargs) - self.recent_ack_latencies: Deque[float] = deque(maxlen=20) + self.recent_ack_latencies: deque[float] = deque(maxlen=20) self.msg = "Keeping shard ID %s voice websocket alive with timestamp %s." self.block_msg = "Shard ID %s voice heartbeat blocked for more than %s seconds" self.behind_msg = "High socket latency, shard ID %s heartbeat is %.1fs behind" @@ -351,7 +348,7 @@ def __init__( self._dispatch: DispatchFunc = lambda event, *args: None self._dispatch_gateway_error: Optional[GatewayErrorFunc] = None # generic event listeners - self._dispatch_listeners: List[EventListener] = [] + self._dispatch_listeners: list[EventListener] = [] # the keep alive self._keep_alive: Optional[KeepAliveHandler] = None self.thread_id: int = threading.get_ident() @@ -369,7 +366,7 @@ def __init__( # set in `from_client` self.token: str self._connection: ConnectionState - self._discord_parsers: Dict[str, Callable[[Dict[str, Any]], Any]] + self._discord_parsers: dict[str, Callable[[dict[str, Any]], Any]] self.gateway: str self.call_hooks: CallHooksFunc self._initial_identify: bool @@ -459,8 +456,8 @@ async def from_client( def wait_for( self, event: str, - predicate: Callable[[Dict[str, Any]], bool], - result: Optional[Callable[[Dict[str, Any]], T]] = None, + predicate: Callable[[dict[str, Any]], bool], + result: Optional[Callable[[dict[str, Any]], T]] = None, ) -> asyncio.Future[T]: """Waits for a DISPATCH'd event that meets the predicate. @@ -653,7 +650,7 @@ async def received_message(self, raw_msg: Union[str, bytes], /) -> None: ) # remove the dispatched listeners - removed: List[int] = [] + removed: list[int] = [] for index, entry in enumerate(self._dispatch_listeners): if entry.event != event: continue @@ -808,7 +805,7 @@ async def request_chunks( query: Optional[str] = None, *, limit: int, - user_ids: Optional[List[int]] = None, + user_ids: Optional[list[int]] = None, presences: bool = False, nonce: Optional[str] = None, ) -> None: @@ -909,7 +906,7 @@ def __init__( self.loop: asyncio.AbstractEventLoop = loop self._keep_alive: Optional[VoiceKeepAliveHandler] = None self._close_code: Optional[int] = None - self.secret_key: Optional[List[int]] = None + self.secret_key: Optional[list[int]] = None self.thread_id: int = threading.get_ident() if hook: self._hook = hook @@ -1050,7 +1047,7 @@ async def initial_connection(self, data: VoiceReadyPayload) -> None: _log.debug("detected ip: %s port: %s", state.ip, state.port) # there *should* always be at least one supported mode - modes: List[SupportedModes] = [ + modes: list[SupportedModes] = [ mode for mode in data["modes"] if mode in self._connection.supported_modes ] _log.debug("received supported encryption modes: %s", ", ".join(modes)) diff --git a/disnake/guild.py b/disnake/guild.py index cabf40fe75..570bc05cd6 100644 --- a/disnake/guild.py +++ b/disnake/guild.py @@ -5,20 +5,15 @@ import copy import datetime import unicodedata +from collections.abc import Iterable, Sequence from typing import ( TYPE_CHECKING, Any, ClassVar, - Dict, - Iterable, - List, Literal, NamedTuple, NewType, Optional, - Sequence, - Set, - Tuple, Union, cast, overload, @@ -126,7 +121,7 @@ GuildChannel = Union[ VoiceChannel, StageChannel, TextChannel, CategoryChannel, ForumChannel, MediaChannel ] - ByCategoryItem = Tuple[Optional[CategoryChannel], List[GuildChannel]] + ByCategoryItem = tuple[Optional[CategoryChannel], list[GuildChannel]] class _GuildLimit(NamedTuple): @@ -472,7 +467,7 @@ class Guild(Hashable): "_safety_alerts_channel_id", ) - _PREMIUM_GUILD_LIMITS: ClassVar[Dict[Optional[int], _GuildLimit]] = { + _PREMIUM_GUILD_LIMITS: ClassVar[dict[Optional[int], _GuildLimit]] = { None: _GuildLimit(emoji=50, stickers=5, bitrate=96e3, filesize=10485760, sounds=8), 0: _GuildLimit(emoji=50, stickers=5, bitrate=96e3, filesize=10485760, sounds=8), 1: _GuildLimit(emoji=100, stickers=15, bitrate=128e3, filesize=10485760, sounds=24), @@ -481,12 +476,12 @@ class Guild(Hashable): } def __init__(self, *, data: GuildPayload, state: ConnectionState) -> None: - self._channels: Dict[int, GuildChannel] = {} - self._members: Dict[int, Member] = {} - self._voice_states: Dict[int, VoiceState] = {} - self._threads: Dict[int, Thread] = {} - self._stage_instances: Dict[int, StageInstance] = {} - self._scheduled_events: Dict[int, GuildScheduledEvent] = {} + self._channels: dict[int, GuildChannel] = {} + self._members: dict[int, Member] = {} + self._voice_states: dict[int, VoiceState] = {} + self._threads: dict[int, Thread] = {} + self._stage_instances: dict[int, StageInstance] = {} + self._scheduled_events: dict[int, GuildScheduledEvent] = {} self._state: ConnectionState = state self._from_data(data) @@ -524,8 +519,8 @@ def _remove_threads_by_channel(self, channel_id: int) -> None: for k in to_remove: del self._threads[k] - def _filter_threads(self, channel_ids: Set[int]) -> Dict[int, Thread]: - to_remove: Dict[int, Thread] = { + def _filter_threads(self, channel_ids: set[int]) -> dict[int, Thread]: + to_remove: dict[int, Thread] = { k: t for k, t in self._threads.items() if t.parent_id in channel_ids } for k in to_remove: @@ -548,7 +543,7 @@ def __repr__(self) -> str: def _update_voice_state( self, data: GuildVoiceState, channel_id: Optional[int] - ) -> Tuple[Optional[Member], VoiceState, VoiceState]: + ) -> tuple[Optional[Member], VoiceState, VoiceState]: user_id = int(data["user_id"]) channel: Optional[VocalGuildChannel] = self.get_channel(channel_id) # type: ignore try: @@ -648,23 +643,23 @@ def _from_data(self, guild: GuildPayload) -> None: self._banner: Optional[str] = guild.get("banner") self.unavailable: bool = guild.get("unavailable", False) self.id: int = int(guild["id"]) - self._roles: Dict[int, Role] = {} + self._roles: dict[int, Role] = {} state = self._state # speed up attribute access for r in guild.get("roles", []): role = Role(guild=self, data=r, state=state) self._roles[role.id] = role self.mfa_level: MFALevel = guild.get("mfa_level", 0) - self.emojis: Tuple[Emoji, ...] = tuple( + self.emojis: tuple[Emoji, ...] = tuple( state.store_emoji(self, d) for d in guild.get("emojis", []) ) - self.stickers: Tuple[GuildSticker, ...] = tuple( + self.stickers: tuple[GuildSticker, ...] = tuple( state.store_sticker(self, d) for d in guild.get("stickers", []) ) - self.soundboard_sounds: Tuple[GuildSoundboardSound, ...] = tuple( + self.soundboard_sounds: tuple[GuildSoundboardSound, ...] = tuple( state.store_soundboard_sound(self, d) for d in guild.get("soundboard_sounds", []) ) - self.features: List[GuildFeature] = guild.get("features", []) + self.features: list[GuildFeature] = guild.get("features", []) self._splash: Optional[str] = guild.get("splash") self._system_channel_id: Optional[int] = utils._get_as_snowflake(guild, "system_channel_id") self.description: Optional[str] = guild.get("description") @@ -757,12 +752,12 @@ def _sync(self, data: GuildPayload) -> None: self._add_thread(Thread(guild=self, state=self._state, data=thread)) @property - def channels(self) -> List[GuildChannel]: + def channels(self) -> list[GuildChannel]: """:class:`list`\\[:class:`abc.GuildChannel`]: A list of channels that belong to this guild.""" return list(self._channels.values()) @property - def threads(self) -> List[Thread]: + def threads(self) -> list[Thread]: """:class:`list`\\[:class:`Thread`]: A list of threads that you have permission to view. .. versionadded:: 2.0 @@ -784,7 +779,7 @@ def large(self) -> bool: return self._large @property - def voice_channels(self) -> List[VoiceChannel]: + def voice_channels(self) -> list[VoiceChannel]: """:class:`list`\\[:class:`VoiceChannel`]: A list of voice channels that belong to this guild. This is sorted by the position and are in UI order from top to bottom. @@ -794,7 +789,7 @@ def voice_channels(self) -> List[VoiceChannel]: return r @property - def stage_channels(self) -> List[StageChannel]: + def stage_channels(self) -> list[StageChannel]: """:class:`list`\\[:class:`StageChannel`]: A list of stage channels that belong to this guild. .. versionadded:: 1.7 @@ -806,7 +801,7 @@ def stage_channels(self) -> List[StageChannel]: return r @property - def forum_channels(self) -> List[ForumChannel]: + def forum_channels(self) -> list[ForumChannel]: """:class:`list`\\[:class:`ForumChannel`]: A list of forum channels that belong to this guild. This is sorted by the position and are in UI order from top to bottom. @@ -818,7 +813,7 @@ def forum_channels(self) -> List[ForumChannel]: return r @property - def media_channels(self) -> List[MediaChannel]: + def media_channels(self) -> list[MediaChannel]: """:class:`list`\\[:class:`MediaChannel`]: A list of media channels that belong to this guild. This is sorted by the position and are in UI order from top to bottom. @@ -844,7 +839,7 @@ def voice_client(self) -> Optional[VoiceProtocol]: return self._state._get_voice_client(self.id) @property - def text_channels(self) -> List[TextChannel]: + def text_channels(self) -> list[TextChannel]: """:class:`list`\\[:class:`TextChannel`]: A list of text channels that belong to this guild. This is sorted by the position and are in UI order from top to bottom. @@ -854,7 +849,7 @@ def text_channels(self) -> List[TextChannel]: return r @property - def categories(self) -> List[CategoryChannel]: + def categories(self) -> list[CategoryChannel]: """:class:`list`\\[:class:`CategoryChannel`]: A list of categories that belong to this guild. This is sorted by the position and are in UI order from top to bottom. @@ -863,7 +858,7 @@ def categories(self) -> List[CategoryChannel]: r.sort(key=lambda c: (c.position, c.id)) return r - def by_category(self) -> List[ByCategoryItem]: + def by_category(self) -> list[ByCategoryItem]: """Returns every :class:`CategoryChannel` and their associated channels. These channels and categories are sorted in the official Discord UI order. @@ -876,7 +871,7 @@ def by_category(self) -> List[ByCategoryItem]: :class:`list`\\[:class:`tuple`\\[:class:`CategoryChannel` | :data:`None`, :class:`list`\\[:class:`abc.GuildChannel`]]]: The categories and their associated channels. """ - grouped: Dict[Optional[int], List[GuildChannel]] = {} + grouped: dict[Optional[int], list[GuildChannel]] = {} for channel in self._channels.values(): if isinstance(channel, CategoryChannel): grouped.setdefault(channel.id, []) @@ -887,12 +882,12 @@ def by_category(self) -> List[ByCategoryItem]: except KeyError: grouped[channel.category_id] = [channel] - def key(t: ByCategoryItem) -> Tuple[Tuple[int, int], List[GuildChannel]]: + def key(t: ByCategoryItem) -> tuple[tuple[int, int], list[GuildChannel]]: k, v = t return ((k.position, k.id) if k else (-1, -1), v) _get = self._channels.get - as_list: List[ByCategoryItem] = [(_get(k), v) for k, v in grouped.items()] # type: ignore + as_list: list[ByCategoryItem] = [(_get(k), v) for k, v in grouped.items()] # type: ignore as_list.sort(key=key) for _, channels in as_list: channels.sort(key=lambda c: (c._sorting_bucket, c.position, c.id)) @@ -1051,7 +1046,7 @@ def soundboard_limit(self) -> int: return max(more_soundboard, self._PREMIUM_GUILD_LIMITS[self.premium_tier].sounds) @property - def members(self) -> List[Member]: + def members(self) -> list[Member]: """:class:`list`\\[:class:`Member`]: A list of members that belong to this guild.""" return list(self._members.values()) @@ -1071,12 +1066,12 @@ def get_member(self, user_id: int, /) -> Optional[Member]: return self._members.get(user_id) @property - def premium_subscribers(self) -> List[Member]: + def premium_subscribers(self) -> list[Member]: """:class:`list`\\[:class:`Member`]: A list of members who have "boosted" this guild.""" return [member for member in self.members if member.premium_since is not None] @property - def roles(self) -> List[Role]: + def roles(self) -> list[Role]: """:class:`list`\\[:class:`Role`]: Returns a :class:`list` of the guild's roles in hierarchy order. The first element of this list will be the lowest role in the @@ -1130,7 +1125,7 @@ def self_role(self) -> Optional[Role]: return None @property - def stage_instances(self) -> List[StageInstance]: + def stage_instances(self) -> list[StageInstance]: """:class:`list`\\[:class:`StageInstance`]: Returns a :class:`list` of the guild's stage instances that are currently running. @@ -1156,7 +1151,7 @@ def get_stage_instance(self, stage_instance_id: int, /) -> Optional[StageInstanc return self._stage_instances.get(stage_instance_id) @property - def scheduled_events(self) -> List[GuildScheduledEvent]: + def scheduled_events(self) -> list[GuildScheduledEvent]: """:class:`list`\\[:class:`GuildScheduledEvent`]: Returns a :class:`list` of existing guild scheduled events. .. versionadded:: 2.3 @@ -1321,7 +1316,7 @@ def _create_channel( self, name: str, channel_type: ChannelType, - overwrites: Dict[Union[Role, Member], PermissionOverwrite] = MISSING, + overwrites: dict[Union[Role, Member], PermissionOverwrite] = MISSING, category: Optional[Snowflake] = None, **options: Any, ) -> Any: @@ -1370,7 +1365,7 @@ async def create_text_channel( default_auto_archive_duration: AnyThreadArchiveDuration = MISSING, nsfw: bool = MISSING, news: bool = MISSING, - overwrites: Dict[Union[Role, Member], PermissionOverwrite] = MISSING, + overwrites: dict[Union[Role, Member], PermissionOverwrite] = MISSING, ) -> TextChannel: """|coro| @@ -1524,7 +1519,7 @@ async def create_voice_channel( video_quality_mode: VideoQualityMode = MISSING, nsfw: bool = MISSING, slowmode_delay: int = MISSING, - overwrites: Dict[Union[Role, Member], PermissionOverwrite] = MISSING, + overwrites: dict[Union[Role, Member], PermissionOverwrite] = MISSING, reason: Optional[str] = None, ) -> VoiceChannel: """|coro| @@ -1639,7 +1634,7 @@ async def create_stage_channel( user_limit: int = MISSING, rtc_region: Optional[Union[str, VoiceRegion]] = MISSING, video_quality_mode: VideoQualityMode = MISSING, - overwrites: Dict[Union[Role, Member], PermissionOverwrite] = MISSING, + overwrites: dict[Union[Role, Member], PermissionOverwrite] = MISSING, category: Optional[Snowflake] = None, nsfw: bool = MISSING, slowmode_delay: int = MISSING, @@ -1716,7 +1711,7 @@ async def create_stage_channel( :class:`StageChannel` The channel that was just created. """ - options: Dict[str, Any] = {} + options: dict[str, Any] = {} if topic is not MISSING: options["topic"] = topic @@ -1767,7 +1762,7 @@ async def create_forum_channel( default_thread_slowmode_delay: int = MISSING, default_auto_archive_duration: Optional[AnyThreadArchiveDuration] = None, nsfw: bool = MISSING, - overwrites: Dict[Union[Role, Member], PermissionOverwrite] = MISSING, + overwrites: dict[Union[Role, Member], PermissionOverwrite] = MISSING, available_tags: Optional[Sequence[ForumTag]] = None, default_reaction: Optional[Union[str, Emoji, PartialEmoji]] = None, default_sort_order: Optional[ThreadSortOrder] = None, @@ -1917,7 +1912,7 @@ async def create_media_channel( default_thread_slowmode_delay: int = MISSING, default_auto_archive_duration: Optional[AnyThreadArchiveDuration] = None, nsfw: bool = MISSING, - overwrites: Dict[Union[Role, Member], PermissionOverwrite] = MISSING, + overwrites: dict[Union[Role, Member], PermissionOverwrite] = MISSING, available_tags: Optional[Sequence[ForumTag]] = None, default_reaction: Optional[Union[str, Emoji, PartialEmoji]] = None, default_sort_order: Optional[ThreadSortOrder] = None, @@ -2036,7 +2031,7 @@ async def create_category( self, name: str, *, - overwrites: Dict[Union[Role, Member], PermissionOverwrite] = MISSING, + overwrites: dict[Union[Role, Member], PermissionOverwrite] = MISSING, reason: Optional[str] = None, position: int = MISSING, ) -> CategoryChannel: @@ -2079,7 +2074,7 @@ async def create_category( :class:`CategoryChannel` The channel that was just created. """ - options: Dict[str, Any] = {} + options: dict[str, Any] = {} if position is not MISSING: options["position"] = position @@ -2367,7 +2362,7 @@ async def edit( if payload: await http.edit_guild_incident_actions(self.id, payload) - fields: Dict[str, Any] = {} + fields: dict[str, Any] = {} if name is not MISSING: fields["name"] = name @@ -2558,7 +2553,7 @@ def convert(d: GuildChannelPayload) -> GuildChannel: return [convert(d) for d in data] - async def active_threads(self) -> List[Thread]: + async def active_threads(self) -> list[Thread]: """|coro| Returns a list of active :class:`Thread` that the client can access. @@ -2579,7 +2574,7 @@ async def active_threads(self) -> List[Thread]: """ data = await self._state.http.get_active_threads(self.id) threads = [Thread(guild=self, state=self._state, data=d) for d in data.get("threads", [])] - thread_lookup: Dict[int, Thread] = {thread.id: thread for thread in threads} + thread_lookup: dict[int, Thread] = {thread.id: thread for thread in threads} for member in data.get("members", []): thread = thread_lookup.get(int(member["id"])) if thread is not None: @@ -2589,7 +2584,7 @@ async def active_threads(self) -> List[Thread]: async def fetch_scheduled_events( self, *, with_user_count: bool = False - ) -> List[GuildScheduledEvent]: + ) -> list[GuildScheduledEvent]: """|coro| Retrieves a list of all :class:`GuildScheduledEvent` instances that the guild has. @@ -2822,7 +2817,7 @@ async def create_scheduled_event( msg = "privacy_level must be an instance of GuildScheduledEventPrivacyLevel" raise TypeError(msg) - fields: Dict[str, Any] = { + fields: dict[str, Any] = { "name": name, "privacy_level": privacy_level.value, "scheduled_start_time": utils.isoformat_utc(scheduled_start_time), @@ -2884,7 +2879,7 @@ async def edit_welcome_screen( self, *, enabled: bool = MISSING, - channels: Optional[List[WelcomeScreenChannel]] = MISSING, + channels: Optional[list[WelcomeScreenChannel]] = MISSING, description: Optional[str] = MISSING, reason: Optional[str] = None, ) -> WelcomeScreen: @@ -3178,7 +3173,7 @@ async def prune_members( *, days: int, compute_prune_count: bool = True, - roles: List[Snowflake] = MISSING, + roles: list[Snowflake] = MISSING, reason: Optional[str] = None, ) -> Optional[int]: """|coro| @@ -3246,7 +3241,7 @@ async def prune_members( ) return data["pruned"] - async def templates(self) -> List[Template]: + async def templates(self) -> list[Template]: """|coro| Gets the list of templates from this guild. @@ -3271,7 +3266,7 @@ async def templates(self) -> List[Template]: data = await self._state.http.guild_templates(self.id) return [Template(data=d, state=self._state) for d in data] - async def webhooks(self) -> List[Webhook]: + async def webhooks(self) -> list[Webhook]: """|coro| Gets the list of webhooks from this guild. @@ -3294,7 +3289,7 @@ async def webhooks(self) -> List[Webhook]: data = await self._state.http.guild_webhooks(self.id) return [Webhook.from_state(d, state=self._state) for d in data] - async def estimate_pruned_members(self, *, days: int, roles: List[Snowflake] = MISSING) -> int: + async def estimate_pruned_members(self, *, days: int, roles: list[Snowflake] = MISSING) -> int: """|coro| Similar to :meth:`prune_members` except instead of actually @@ -3340,7 +3335,7 @@ async def estimate_pruned_members(self, *, days: int, roles: List[Snowflake] = M data = await self._state.http.estimate_pruned_members(self.id, days, role_ids) return data["pruned"] - async def invites(self) -> List[Invite]: + async def invites(self) -> list[Invite]: """|coro| Returns a list of all active instant invites from the guild. @@ -3368,7 +3363,7 @@ async def invites(self) -> List[Invite]: The list of invites that are currently active. """ data = await self._state.http.invites_from(self.id) - result: List[Invite] = [] + result: list[Invite] = [] for invite in data: if channel_data := invite.get("channel"): channel = self.get_channel(int(channel_data["id"])) @@ -3441,7 +3436,7 @@ async def create_integration(self, *, type: IntegrationType, id: int) -> None: """ await self._state.http.create_integration(self.id, type, id) - async def integrations(self) -> List[Integration]: + async def integrations(self) -> list[Integration]: """|coro| Returns a list of all integrations attached to the guild. @@ -3471,7 +3466,7 @@ def convert(d: IntegrationPayload) -> Integration: return [convert(d) for d in data] - async def fetch_stickers(self) -> List[GuildSticker]: + async def fetch_stickers(self) -> list[GuildSticker]: """|coro| Retrieves a list of all :class:`Sticker`\\s that the guild has. @@ -3611,7 +3606,7 @@ async def delete_sticker(self, sticker: Snowflake, *, reason: Optional[str] = No """ await self._state.http.delete_guild_sticker(self.id, sticker.id, reason=reason) - async def fetch_emojis(self) -> List[Emoji]: + async def fetch_emojis(self) -> list[Emoji]: """|coro| Retrieves all custom :class:`Emoji`\\s that the guild has. @@ -3797,7 +3792,7 @@ async def fetch_role(self, role_id: int, /) -> Role: data = await self._state.http.get_role(self.id, role_id=role_id) return Role(guild=self, state=self._state, data=data) - async def fetch_roles(self) -> List[Role]: + async def fetch_roles(self) -> list[Role]: """|coro| Retrieves all :class:`Role` that the guild has. @@ -4045,8 +4040,8 @@ async def create_role( return role async def edit_role_positions( - self, positions: Dict[Snowflake, int], *, reason: Optional[str] = None - ) -> List[Role]: + self, positions: dict[Snowflake, int], *, reason: Optional[str] = None + ) -> list[Role]: """|coro| Bulk edits a list of :class:`Role` in the guild. @@ -4097,14 +4092,14 @@ async def edit_role_positions( msg = "positions parameter expects a dict." raise TypeError(msg) - role_positions: List[Any] = [] + role_positions: list[Any] = [] for role, position in positions.items(): payload = {"id": role.id, "position": position} role_positions.append(payload) data = await self._state.http.move_role_position(self.id, role_positions, reason=reason) - roles: List[Role] = [] + roles: list[Role] = [] for d in data: role = Role(guild=self, data=d, state=self._state) roles.append(role) @@ -4635,7 +4630,7 @@ async def edit_mfa_level(self, mfa_level: MFALevel, *, reason: Optional[str] = N # return value unused await self._state.http.edit_mfa_level(self.id, mfa_level, reason=reason) - async def chunk(self, *, cache: bool = True) -> Optional[List[Member]]: + async def chunk(self, *, cache: bool = True) -> Optional[list[Member]]: """|coro| Returns a :class:`list` of all guild members. @@ -4674,10 +4669,10 @@ async def query_members( query: Optional[str] = None, *, limit: int = 5, - user_ids: Optional[List[int]] = None, + user_ids: Optional[list[int]] = None, presences: bool = False, cache: bool = True, - ) -> List[Member]: + ) -> list[Member]: """|coro| Request members that belong to this guild whose name starts with @@ -4757,7 +4752,7 @@ async def search_members( *, limit: int = 1, cache: bool = True, - ) -> List[Member]: + ) -> list[Member]: """|coro| Retrieves members that belong to this guild whose name starts with @@ -4798,7 +4793,7 @@ async def search_members( raise ValueError(msg) limit = min(1000, limit) members = await self._state.http.search_guild_members(self.id, query=query, limit=limit) - resp: List[Member] = [] + resp: list[Member] = [] for member in members: member = Member(state=self._state, data=member, guild=self) if cache and member.id not in self._members: @@ -4808,11 +4803,11 @@ async def search_members( async def get_or_fetch_members( self, - user_ids: List[int], + user_ids: list[int], *, presences: bool = False, cache: bool = True, - ) -> List[Member]: + ) -> list[Member]: """|coro| Tries to get the guild members matching the provided IDs from cache. @@ -4852,8 +4847,8 @@ async def get_or_fetch_members( msg = "Intents.presences must be enabled to use this." raise ClientException(msg) - members: List[Member] = [] - unresolved_ids: List[int] = [] + members: list[Member] = [] + unresolved_ids: list[int] = [] for user_id in user_ids: member = self.get_member(user_id) @@ -4892,7 +4887,7 @@ async def get_or_fetch_members( getch_members = get_or_fetch_members - async def fetch_voice_regions(self) -> List[VoiceRegion]: + async def fetch_voice_regions(self) -> list[VoiceRegion]: """|coro| Retrieves a list of :class:`VoiceRegion` for this guild. @@ -4971,7 +4966,7 @@ async def change_voice_state( # Application command permissions - async def bulk_fetch_command_permissions(self) -> List[GuildApplicationCommandPermissions]: + async def bulk_fetch_command_permissions(self) -> list[GuildApplicationCommandPermissions]: """|coro| Requests a list of :class:`GuildApplicationCommandPermissions` configured for this guild. @@ -5073,7 +5068,7 @@ async def timeout( msg = "Exactly one of `duration` and `until` must be provided" raise ValueError(msg) - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} if duration is not MISSING: if duration is None: @@ -5116,7 +5111,7 @@ async def fetch_automod_rule(self, rule_id: int, /) -> AutoModRule: data = await self._state.http.get_auto_moderation_rule(self.id, rule_id) return AutoModRule(data=data, guild=self) - async def fetch_automod_rules(self) -> List[AutoModRule]: + async def fetch_automod_rules(self) -> list[AutoModRule]: """|coro| Retrieves the guild's auto moderation rules. @@ -5353,7 +5348,7 @@ async def fetch_soundboard_sound(self, sound_id: int, /) -> GuildSoundboardSound data = await self._state.http.get_guild_soundboard_sound(self.id, sound_id) return GuildSoundboardSound(data=data, state=self._state, guild_id=self.id) - async def fetch_soundboard_sounds(self) -> List[GuildSoundboardSound]: + async def fetch_soundboard_sounds(self) -> list[GuildSoundboardSound]: """|coro| Retrieves all :class:`GuildSoundboardSound`\\s that the guild has. @@ -5471,8 +5466,8 @@ def __init__(self, *, state: ConnectionState, name: str) -> None: self.name: str = name # note: the first role corresponds to @everyone - self._roles: List[CreateGuildPlaceholderRole] = [] - self._channels: List[CreateGuildPlaceholderChannel] = [] + self._roles: list[CreateGuildPlaceholderRole] = [] + self._channels: list[CreateGuildPlaceholderChannel] = [] self.icon: Optional[AssetBytes] = None self.verification_level: Optional[VerificationLevel] = None @@ -5496,12 +5491,12 @@ def _add_channel( *, type: ChannelType, name: str, - overwrites: Dict[PlaceholderID, PermissionOverwrite] = MISSING, + overwrites: dict[PlaceholderID, PermissionOverwrite] = MISSING, category: PlaceholderID = MISSING, topic: Optional[str] = MISSING, slowmode_delay: int = MISSING, nsfw: bool = MISSING, - ) -> Tuple[PlaceholderID, CreateGuildPlaceholderChannel]: + ) -> tuple[PlaceholderID, CreateGuildPlaceholderChannel]: _id = self._next_id() data: CreateGuildPlaceholderChannel = { "id": _id, @@ -5510,7 +5505,7 @@ def _add_channel( } if overwrites is not MISSING: - overwrites_data: List[PermissionOverwritePayload] = [] + overwrites_data: list[PermissionOverwritePayload] = [] for target, perm in overwrites.items(): allow, deny = perm.pair() overwrites_data.append( @@ -5682,7 +5677,7 @@ def add_category( self, name: str, *, - overwrites: Dict[PlaceholderID, PermissionOverwrite] = MISSING, + overwrites: dict[PlaceholderID, PermissionOverwrite] = MISSING, ) -> PlaceholderID: """Adds a category channel to the guild builder. @@ -5709,7 +5704,7 @@ def add_text_channel( self, name: str, *, - overwrites: Dict[PlaceholderID, PermissionOverwrite] = MISSING, + overwrites: dict[PlaceholderID, PermissionOverwrite] = MISSING, category: PlaceholderID = MISSING, topic: Optional[str] = MISSING, slowmode_delay: int = MISSING, @@ -5769,7 +5764,7 @@ def add_voice_channel( self, name: str, *, - overwrites: Dict[PlaceholderID, PermissionOverwrite] = MISSING, + overwrites: dict[PlaceholderID, PermissionOverwrite] = MISSING, category: PlaceholderID = MISSING, slowmode_delay: int = MISSING, nsfw: bool = MISSING, diff --git a/disnake/guild_preview.py b/disnake/guild_preview.py index 91ab0300b0..e55af6884e 100644 --- a/disnake/guild_preview.py +++ b/disnake/guild_preview.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional, Tuple +from typing import TYPE_CHECKING, Optional from .asset import Asset from .emoji import Emoji @@ -74,19 +74,19 @@ def __init__(self, *, data: GuildPreviewPayload, state: ConnectionState) -> None emojis = data.get("emojis") if emojis: - self.emojis: Tuple[Emoji, ...] = tuple( + self.emojis: tuple[Emoji, ...] = tuple( Emoji(guild=self, state=self._state, data=emoji) for emoji in emojis ) else: - self.emojis: Tuple[Emoji, ...] = () + self.emojis: tuple[Emoji, ...] = () stickers = data.get("stickers") if stickers: - self.stickers: Tuple[GuildSticker, ...] = tuple( + self.stickers: tuple[GuildSticker, ...] = tuple( GuildSticker(state=self._state, data=sticker) for sticker in stickers ) else: - self.stickers: Tuple[GuildSticker, ...] = () + self.stickers: tuple[GuildSticker, ...] = () def __repr__(self) -> str: return f"" diff --git a/disnake/guild_scheduled_event.py b/disnake/guild_scheduled_event.py index 66c3181546..9d36001995 100644 --- a/disnake/guild_scheduled_event.py +++ b/disnake/guild_scheduled_event.py @@ -3,7 +3,7 @@ from __future__ import annotations from datetime import datetime -from typing import TYPE_CHECKING, Any, Dict, Literal, Optional, overload +from typing import TYPE_CHECKING, Any, Literal, Optional, overload from .asset import Asset from .enums import ( @@ -451,7 +451,7 @@ async def edit( :class:`GuildScheduledEvent` The newly updated guild scheduled event instance. """ - fields: Dict[str, Any] = {} + fields: dict[str, Any] = {} if entity_type is MISSING: if channel is None: diff --git a/disnake/http.py b/disnake/http.py index c32cbc8842..c4c33d37a7 100644 --- a/disnake/http.py +++ b/disnake/http.py @@ -7,20 +7,14 @@ import re import sys import weakref +from collections.abc import Coroutine, Iterable, Sequence from errno import ECONNRESET from typing import ( TYPE_CHECKING, Any, ClassVar, - Coroutine, - Dict, - Iterable, - List, Literal, Optional, - Sequence, - Tuple, - Type, TypeVar, Union, cast, @@ -108,7 +102,7 @@ def _workaround_set_api_version(version: Literal[9, 10]) -> None: Route.BASE = f"https://discord.com/api/v{_API_VERSION}" -async def json_or_text(response: aiohttp.ClientResponse) -> Union[Dict[str, Any], str]: +async def json_or_text(response: aiohttp.ClientResponse) -> Union[dict[str, Any], str]: text = await response.text(encoding="utf-8") try: if response.headers["content-type"] == "application/json": @@ -120,7 +114,7 @@ async def json_or_text(response: aiohttp.ClientResponse) -> Union[Dict[str, Any] return text -def set_attachments(payload: Dict[str, Any], files: Sequence[File]) -> None: +def set_attachments(payload: dict[str, Any], files: Sequence[File]) -> None: """Updates the payload's attachments list based on the provided files note: this method modifies the provided ``payload`` and ``payload["attachments"]`` collections @@ -140,11 +134,11 @@ def set_attachments(payload: Dict[str, Any], files: Sequence[File]) -> None: payload["attachments"] = attachments -def to_multipart(payload: Dict[str, Any], files: Sequence[File]) -> List[Dict[str, Any]]: +def to_multipart(payload: dict[str, Any], files: Sequence[File]) -> list[dict[str, Any]]: """Converts the payload and list of files to a multipart payload, as specified by https://discord.com/developers/docs/reference#uploading-files """ - multipart: List[Dict[str, Any]] = [] + multipart: list[dict[str, Any]] = [] for index, file in enumerate(files): multipart.append( { @@ -160,8 +154,8 @@ def to_multipart(payload: Dict[str, Any], files: Sequence[File]) -> List[Dict[st def to_multipart_with_attachments( - payload: Dict[str, Any], files: Sequence[File] -) -> List[Dict[str, Any]]: + payload: dict[str, Any], files: Sequence[File] +) -> list[dict[str, Any]]: """Updates the payload's attachments and converts it to a multipart payload Shorthand for ``set_attachments`` + ``to_multipart`` @@ -212,7 +206,7 @@ def defer(self) -> None: def __exit__( self, - exc_type: Optional[Type[BaseException]], + exc_type: Optional[type[BaseException]], exc: Optional[BaseException], traceback: Optional[TracebackType], ) -> None: @@ -281,7 +275,7 @@ async def request( route: Route, *, files: Optional[Sequence[File]] = None, - form: Optional[Iterable[Dict[str, Any]]] = None, + form: Optional[Iterable[dict[str, Any]]] = None, **kwargs: Any, ) -> Any: bucket = route.bucket @@ -293,7 +287,7 @@ async def request( self._locks[bucket] = lock = asyncio.Lock() # header creation - headers: Dict[str, str] = { + headers: dict[str, str] = { "User-Agent": self.user_agent, } @@ -325,7 +319,7 @@ async def request( await self._global_over.wait() response: Optional[aiohttp.ClientResponse] = None - data: Optional[Union[Dict[str, Any], str]] = None + data: Optional[Union[dict[str, Any], str]] = None await lock.acquire() with MaybeUnlock(lock) as maybe_lock: for tries in range(5): @@ -508,7 +502,7 @@ def create_party( # Group functionality def start_group( - self, user_id: Snowflake, recipients: List[int] + self, user_id: Snowflake, recipients: list[int] ) -> Response[channel.GroupDMChannel]: payload = { "recipients": recipients, @@ -537,7 +531,7 @@ def send_message( *, tts: bool = False, embed: Optional[embed.Embed] = None, - embeds: Optional[List[embed.Embed]] = None, + embeds: Optional[list[embed.Embed]] = None, nonce: Optional[Union[str, int]] = None, allowed_mentions: Optional[message.AllowedMentions] = None, message_reference: Optional[message.MessageReference] = None, @@ -547,7 +541,7 @@ def send_message( flags: Optional[int] = None, ) -> Response[message.Message]: r = Route("POST", "/channels/{channel_id}/messages", channel_id=channel_id) - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} if content: payload["content"] = content @@ -593,7 +587,7 @@ def get_poll_answer_voters( after: Optional[Snowflake] = None, limit: Optional[int] = None, ) -> Response[poll.PollVoters]: - params: Dict[str, Any] = {} + params: dict[str, Any] = {} if after is not None: params["after"] = after @@ -634,7 +628,7 @@ def send_multipart_helper( content: Optional[str] = None, tts: bool = False, embed: Optional[embed.Embed] = None, - embeds: Optional[List[embed.Embed]] = None, + embeds: Optional[list[embed.Embed]] = None, nonce: Optional[Union[str, int]] = None, allowed_mentions: Optional[message.AllowedMentions] = None, message_reference: Optional[message.MessageReference] = None, @@ -643,7 +637,7 @@ def send_multipart_helper( poll: Optional[poll.PollCreatePayload] = None, flags: Optional[int] = None, ) -> Response[message.Message]: - payload: Dict[str, Any] = {"tts": tts} + payload: dict[str, Any] = {"tts": tts} if content: payload["content"] = content if embed: @@ -677,7 +671,7 @@ def send_files( content: Optional[str] = None, tts: bool = False, embed: Optional[embed.Embed] = None, - embeds: Optional[List[embed.Embed]] = None, + embeds: Optional[list[embed.Embed]] = None, nonce: Optional[Union[str, int]] = None, allowed_mentions: Optional[message.AllowedMentions] = None, message_reference: Optional[message.MessageReference] = None, @@ -729,7 +723,7 @@ def edit_message( channel_id: Snowflake, message_id: Snowflake, *, - files: Optional[List[File]] = None, + files: Optional[list[File]] = None, **fields: Any, ) -> Response[message.Message]: r = Route( @@ -787,7 +781,7 @@ def get_reaction_users( emoji: str, limit: int, after: Optional[Snowflake] = None, - ) -> Response[List[user.User]]: + ) -> Response[list[user.User]]: r = Route( "GET", "/channels/{channel_id}/messages/{message_id}/reactions/{emoji}", @@ -796,7 +790,7 @@ def get_reaction_users( emoji=emoji, ) - params: Dict[str, Any] = { + params: dict[str, Any] = { "limit": limit, } if after: @@ -847,8 +841,8 @@ def logs_from( before: Optional[Snowflake] = None, after: Optional[Snowflake] = None, around: Optional[Snowflake] = None, - ) -> Response[List[message.Message]]: - params: Dict[str, Any] = { + ) -> Response[list[message.Message]]: + params: dict[str, Any] = { "limit": limit, } @@ -908,7 +902,7 @@ def get_pins( "/channels/{channel_id}/messages/pins", channel_id=channel_id, ) - params: Dict[str, Any] = {"limit": limit} + params: dict[str, Any] = {"limit": limit} if before is not None: params["before"] = before @@ -919,7 +913,7 @@ def get_pins( def search_guild_members( self, guild_id: Snowflake, query: str, limit: int = 1 - ) -> Response[List[member.MemberWithUser]]: + ) -> Response[list[member.MemberWithUser]]: r = Route("GET", "/guilds/{guild_id}/members/search", guild_id=guild_id) return self.request(r, params={"query": query, "limit": limit}) @@ -956,7 +950,7 @@ def unban( def bulk_ban( self, - user_ids: List[Snowflake], + user_ids: list[Snowflake], guild_id: Snowflake, *, delete_message_seconds: int = 0, @@ -970,7 +964,7 @@ def bulk_ban( return self.request(r, json=payload, reason=reason) - def get_guild_voice_regions(self, guild_id: Snowflake) -> Response[List[voice.VoiceRegion]]: + def get_guild_voice_regions(self, guild_id: Snowflake) -> Response[list[voice.VoiceRegion]]: return self.request(Route("GET", "/guilds/{guild_id}/regions", guild_id=guild_id)) def guild_voice_state( @@ -994,7 +988,7 @@ def guild_voice_state( return self.request(r, json=payload, reason=reason) - def edit_profile(self, payload: Dict[str, Any]) -> Response[user.User]: + def edit_profile(self, payload: dict[str, Any]) -> Response[user.User]: return self.request(Route("PATCH", "/users/@me"), json=payload) def change_nickname( @@ -1024,12 +1018,12 @@ def get_voice_state( ) return self.request(r) - def edit_my_voice_state(self, guild_id: Snowflake, payload: Dict[str, Any]) -> Response[None]: + def edit_my_voice_state(self, guild_id: Snowflake, payload: dict[str, Any]) -> Response[None]: r = Route("PATCH", "/guilds/{guild_id}/voice-states/@me", guild_id=guild_id) return self.request(r, json=payload) def edit_voice_state( - self, guild_id: Snowflake, user_id: Snowflake, payload: Dict[str, Any] + self, guild_id: Snowflake, user_id: Snowflake, payload: dict[str, Any] ) -> Response[None]: r = Route( "PATCH", "/guilds/{guild_id}/voice-states/{user_id}", guild_id=guild_id, user_id=user_id @@ -1101,7 +1095,7 @@ def edit_channel( def bulk_channel_update( self, guild_id: Snowflake, - data: List[guild.ChannelPositionUpdate], + data: list[guild.ChannelPositionUpdate], *, reason: Optional[str] = None, ) -> Response[None]: @@ -1260,7 +1254,7 @@ def get_private_archived_threads( "GET", "/channels/{channel_id}/threads/archived/private", channel_id=channel_id ) - params: Dict[str, Any] = {} + params: dict[str, Any] = {} if before: params["before"] = before params["limit"] = limit @@ -1274,7 +1268,7 @@ def get_joined_private_archived_threads( "/channels/{channel_id}/users/@me/threads/archived/private", channel_id=channel_id, ) - params: Dict[str, Any] = {} + params: dict[str, Any] = {} if before: params["before"] = before params["limit"] = limit @@ -1295,7 +1289,7 @@ def get_thread_member( ) return self.request(route) - def get_thread_members(self, channel_id: Snowflake) -> Response[List[threads.ThreadMember]]: + def get_thread_members(self, channel_id: Snowflake) -> Response[list[threads.ThreadMember]]: route = Route("GET", "/channels/{channel_id}/thread-members", channel_id=channel_id) return self.request(route) @@ -1349,7 +1343,7 @@ def create_webhook( avatar: Optional[str] = None, reason: Optional[str] = None, ) -> Response[webhook.Webhook]: - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "name": name, } if avatar is not None: @@ -1358,10 +1352,10 @@ def create_webhook( r = Route("POST", "/channels/{channel_id}/webhooks", channel_id=channel_id) return self.request(r, json=payload, reason=reason) - def channel_webhooks(self, channel_id: Snowflake) -> Response[List[webhook.Webhook]]: + def channel_webhooks(self, channel_id: Snowflake) -> Response[list[webhook.Webhook]]: return self.request(Route("GET", "/channels/{channel_id}/webhooks", channel_id=channel_id)) - def guild_webhooks(self, guild_id: Snowflake) -> Response[List[webhook.Webhook]]: + def guild_webhooks(self, guild_id: Snowflake) -> Response[list[webhook.Webhook]]: return self.request(Route("GET", "/guilds/{guild_id}/webhooks", guild_id=guild_id)) def get_webhook(self, webhook_id: Snowflake) -> Response[webhook.Webhook]: @@ -1390,8 +1384,8 @@ def get_guilds( before: Optional[Snowflake] = None, after: Optional[Snowflake] = None, with_counts: bool = True, - ) -> Response[List[guild.Guild]]: - params: Dict[str, Any] = { + ) -> Response[list[guild.Guild]]: + params: dict[str, Any] = { "limit": limit, "with_counts": int(with_counts), } @@ -1421,8 +1415,8 @@ def create_guild( verification_level: Optional[guild.VerificationLevel] = None, default_message_notifications: Optional[guild.DefaultMessageNotificationLevel] = None, explicit_content_filter: Optional[guild.ExplicitContentFilterLevel] = None, - roles: Optional[List[guild.CreateGuildPlaceholderRole]] = None, - channels: Optional[List[guild.CreateGuildPlaceholderChannel]] = None, + roles: Optional[list[guild.CreateGuildPlaceholderRole]] = None, + channels: Optional[list[guild.CreateGuildPlaceholderChannel]] = None, afk_channel: Optional[Snowflake] = None, afk_timeout: Optional[int] = None, system_channel: Optional[Snowflake] = None, @@ -1495,7 +1489,7 @@ def edit_guild_incident_actions( def get_template(self, code: str) -> Response[template.Template]: return self.request(Route("GET", "/guilds/templates/{code}", code=code)) - def guild_templates(self, guild_id: Snowflake) -> Response[List[template.Template]]: + def guild_templates(self, guild_id: Snowflake) -> Response[list[template.Template]]: return self.request(Route("GET", "/guilds/{guild_id}/templates", guild_id=guild_id)) def create_template( @@ -1511,7 +1505,7 @@ def sync_template(self, guild_id: Snowflake, code: str) -> Response[template.Tem ) def edit_template( - self, guild_id: Snowflake, code: str, payload: Dict[str, Any] + self, guild_id: Snowflake, code: str, payload: dict[str, Any] ) -> Response[template.Template]: valid_keys = ( "name", @@ -1547,8 +1541,8 @@ def get_bans( limit: Optional[int] = None, before: Optional[Snowflake] = None, after: Optional[Snowflake] = None, - ) -> Response[List[guild.Ban]]: - params: Dict[str, Any] = {} + ) -> Response[list[guild.Ban]]: + params: dict[str, Any] = {} if limit is not None: params["limit"] = limit @@ -1572,7 +1566,7 @@ def get_vanity_code(self, guild_id: Snowflake) -> Response[invite.VanityInvite]: def change_vanity_code( self, guild_id: Snowflake, code: str, *, reason: Optional[str] = None ) -> Response[None]: - payload: Dict[str, Any] = {"code": code} + payload: dict[str, Any] = {"code": code} return self.request( Route("PATCH", "/guilds/{guild_id}/vanity-url", guild_id=guild_id), json=payload, @@ -1589,13 +1583,13 @@ def edit_mfa_level( reason=reason, ) - def get_all_guild_channels(self, guild_id: Snowflake) -> Response[List[guild.GuildChannel]]: + def get_all_guild_channels(self, guild_id: Snowflake) -> Response[list[guild.GuildChannel]]: return self.request(Route("GET", "/guilds/{guild_id}/channels", guild_id=guild_id)) def get_members( self, guild_id: Snowflake, limit: int, after: Optional[Snowflake] - ) -> Response[List[member.MemberWithUser]]: - params: Dict[str, Any] = { + ) -> Response[list[member.MemberWithUser]]: + params: dict[str, Any] = { "limit": limit, } if after: @@ -1621,11 +1615,11 @@ def prune_members( guild_id: Snowflake, days: int, compute_prune_count: bool, - roles: List[str], + roles: list[str], *, reason: Optional[str] = None, ) -> Response[guild.GuildPrune]: - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "days": days, "compute_prune_count": "true" if compute_prune_count else "false", } @@ -1642,9 +1636,9 @@ def estimate_pruned_members( self, guild_id: Snowflake, days: int, - roles: List[str], + roles: list[str], ) -> Response[guild.GuildPrune]: - params: Dict[str, Any] = { + params: dict[str, Any] = { "days": days, } if roles: @@ -1663,7 +1657,7 @@ def get_sticker_pack(self, pack_id: Snowflake) -> Response[sticker.StickerPack]: def list_sticker_packs(self) -> Response[sticker.ListStickerPacks]: return self.request(Route("GET", "/sticker-packs")) - def get_all_guild_stickers(self, guild_id: Snowflake) -> Response[List[sticker.GuildSticker]]: + def get_all_guild_stickers(self, guild_id: Snowflake) -> Response[list[sticker.GuildSticker]]: return self.request(Route("GET", "/guilds/{guild_id}/stickers", guild_id=guild_id)) def get_guild_sticker( @@ -1698,7 +1692,7 @@ def create_guild_sticker( finally: file.reset() - form: List[Dict[str, Any]] = [ + form: list[dict[str, Any]] = [ { "name": "file", "value": file.fp, @@ -1764,7 +1758,7 @@ def get_app_emoji(self, app_id: Snowflake, emoji_id: Snowflake) -> Response[emoj ) ) - def get_all_custom_emojis(self, guild_id: Snowflake) -> Response[List[emoji.Emoji]]: + def get_all_custom_emojis(self, guild_id: Snowflake) -> Response[list[emoji.Emoji]]: return self.request(Route("GET", "/guilds/{guild_id}/emojis", guild_id=guild_id)) def get_custom_emoji(self, guild_id: Snowflake, emoji_id: Snowflake) -> Response[emoji.Emoji]: @@ -1777,7 +1771,7 @@ def get_custom_emoji(self, guild_id: Snowflake, emoji_id: Snowflake) -> Response def create_app_emoji( self, app_id: Snowflake, *, name: str, image: str ) -> Response[emoji.Emoji]: - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "name": name, "image": image, } @@ -1788,7 +1782,7 @@ def create_app_emoji( def edit_app_emoji( self, app_id: Snowflake, emoji_id: Snowflake, *, name: str ) -> Response[emoji.Emoji]: - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "name": name, } @@ -1816,7 +1810,7 @@ def create_custom_emoji( roles: Optional[SnowflakeList] = None, reason: Optional[str] = None, ) -> Response[emoji.Emoji]: - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "name": name, "image": image, "roles": roles or [], @@ -1842,7 +1836,7 @@ def edit_custom_emoji( guild_id: Snowflake, emoji_id: Snowflake, *, - payload: Dict[str, Any], + payload: dict[str, Any], reason: Optional[str] = None, ) -> Response[emoji.Emoji]: r = Route( @@ -1850,7 +1844,7 @@ def edit_custom_emoji( ) return self.request(r, json=payload, reason=reason) - def get_all_integrations(self, guild_id: Snowflake) -> Response[List[integration.Integration]]: + def get_all_integrations(self, guild_id: Snowflake) -> Response[list[integration.Integration]]: r = Route("GET", "/guilds/{guild_id}/integrations", guild_id=guild_id) return self.request(r) @@ -1910,7 +1904,7 @@ def get_audit_logs( user_id: Optional[Snowflake] = None, action_type: Optional[audit_log.AuditLogEvent] = None, ) -> Response[audit_log.AuditLog]: - params: Dict[str, Any] = {"limit": limit} + params: dict[str, Any] = {"limit": limit} if before is not None: params["before"] = before if after is not None: @@ -1930,7 +1924,7 @@ def get_widget_settings(self, guild_id: Snowflake) -> Response[widget.WidgetSett return self.request(Route("GET", "/guilds/{guild_id}/widget", guild_id=guild_id)) def edit_widget( - self, guild_id: Snowflake, payload: Dict[str, Any], *, reason: Optional[str] = None + self, guild_id: Snowflake, payload: dict[str, Any], *, reason: Optional[str] = None ) -> Response[widget.WidgetSettings]: return self.request( Route("PATCH", "/guilds/{guild_id}/widget", guild_id=guild_id), @@ -1961,7 +1955,7 @@ def create_invite( target_application_id: Optional[Snowflake] = None, ) -> Response[invite.Invite]: r = Route("POST", "/channels/{channel_id}/invites", channel_id=channel_id) - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "max_age": max_age, "max_uses": max_uses, "temporary": temporary, @@ -1996,10 +1990,10 @@ def get_invite( Route("GET", "/invites/{invite_id}", invite_id=invite_id), params=params ) - def invites_from(self, guild_id: Snowflake) -> Response[List[invite.Invite]]: + def invites_from(self, guild_id: Snowflake) -> Response[list[invite.Invite]]: return self.request(Route("GET", "/guilds/{guild_id}/invites", guild_id=guild_id)) - def invites_from_channel(self, channel_id: Snowflake) -> Response[List[invite.Invite]]: + def invites_from_channel(self, channel_id: Snowflake) -> Response[list[invite.Invite]]: return self.request(Route("GET", "/channels/{channel_id}/invites", channel_id=channel_id)) def delete_invite(self, invite_id: str, *, reason: Optional[str] = None) -> Response[None]: @@ -2014,7 +2008,7 @@ def get_role(self, guild_id: Snowflake, role_id: Snowflake) -> Response[role.Rol Route("GET", "/guilds/{guild_id}/roles/{role_id}", guild_id=guild_id, role_id=role_id) ) - def get_roles(self, guild_id: Snowflake) -> Response[List[role.Role]]: + def get_roles(self, guild_id: Snowflake) -> Response[list[role.Role]]: return self.request(Route("GET", "/guilds/{guild_id}/roles", guild_id=guild_id)) def edit_role( @@ -2052,7 +2046,7 @@ def replace_roles( self, user_id: Snowflake, guild_id: Snowflake, - role_ids: List[int], + role_ids: list[int], *, reason: Optional[str] = None, ) -> Response[member.MemberWithUser]: @@ -2067,10 +2061,10 @@ def create_role( def move_role_position( self, guild_id: Snowflake, - positions: List[guild.RolePositionUpdate], + positions: list[guild.RolePositionUpdate], *, reason: Optional[str] = None, - ) -> Response[List[role.Role]]: + ) -> Response[list[role.Role]]: r = Route("PATCH", "/guilds/{guild_id}/roles", guild_id=guild_id) return self.request(r, json=positions, reason=reason) @@ -2197,7 +2191,7 @@ def delete_stage_instance( def get_guild_scheduled_events( self, guild_id: Snowflake, with_user_count: bool = False - ) -> Response[List[guild_scheduled_event.GuildScheduledEvent]]: + ) -> Response[list[guild_scheduled_event.GuildScheduledEvent]]: params = {"with_user_count": int(with_user_count)} r = Route("GET", "/guilds/{guild_id}/scheduled-events", guild_id=guild_id) return self.request(r, params=params) @@ -2211,14 +2205,14 @@ def create_guild_scheduled_event( scheduled_start_time: str, entity_type: int, channel_id: Optional[Snowflake] = None, - entity_metadata: Optional[Dict[str, Any]] = None, + entity_metadata: Optional[dict[str, Any]] = None, scheduled_end_time: Optional[str] = None, description: Optional[str] = None, image: Optional[str] = None, reason: Optional[str] = None, ) -> Response[guild_scheduled_event.GuildScheduledEvent]: r = Route("POST", "/guilds/{guild_id}/scheduled-events", guild_id=guild_id) - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "name": name, "privacy_level": privacy_level, "scheduled_start_time": scheduled_start_time, @@ -2290,8 +2284,8 @@ def get_guild_scheduled_event_users( with_member: Optional[bool] = None, before: Optional[Snowflake] = None, after: Optional[Snowflake] = None, - ) -> Response[List[guild_scheduled_event.GuildScheduledEventUser]]: - params: Dict[str, Any] = {} + ) -> Response[list[guild_scheduled_event.GuildScheduledEventUser]]: + params: dict[str, Any] = {} if limit is not None: params["limit"] = limit @@ -2340,7 +2334,7 @@ def edit_guild_welcome_screen( # Auto moderation - def get_auto_moderation_rules(self, guild_id: Snowflake) -> Response[List[automod.AutoModRule]]: + def get_auto_moderation_rules(self, guild_id: Snowflake) -> Response[list[automod.AutoModRule]]: return self.request( Route("GET", "/guilds/{guild_id}/auto-moderation/rules", guild_id=guild_id) ) @@ -2364,7 +2358,7 @@ def create_auto_moderation_rule( name: str, event_type: automod.AutoModEventType, trigger_type: automod.AutoModTriggerType, - actions: List[automod.AutoModAction], + actions: list[automod.AutoModAction], trigger_metadata: Optional[automod.AutoModTriggerMetadata] = None, enabled: Optional[bool] = None, exempt_roles: Optional[SnowflakeList] = None, @@ -2436,7 +2430,7 @@ def get_guild_onboarding(self, guild_id: Snowflake) -> Response[onboarding.Onboa # SKUs/Entitlements - def get_skus(self, application_id: Snowflake) -> Response[List[sku.SKU]]: + def get_skus(self, application_id: Snowflake) -> Response[list[sku.SKU]]: return self.request( Route("GET", "/applications/{application_id}/skus", application_id=application_id) ) @@ -2454,8 +2448,8 @@ def get_entitlements( sku_ids: Optional[SnowflakeList] = None, exclude_ended: bool = False, exclude_deleted: bool = False, - ) -> Response[List[entitlement.Entitlement]]: - params: Dict[str, Any] = { + ) -> Response[list[entitlement.Entitlement]]: + params: dict[str, Any] = { "limit": limit, "exclude_ended": int(exclude_ended), "exclude_deleted": int(exclude_deleted), @@ -2496,8 +2490,8 @@ def get_subscriptions( after: Optional[Snowflake] = None, limit: int = 50, user_id: Optional[Snowflake] = None, - ) -> Response[List[subscription.Subscription]]: - params: Dict[str, Any] = { + ) -> Response[list[subscription.Subscription]]: + params: dict[str, Any] = { "limit": limit, } if before is not None: @@ -2536,7 +2530,7 @@ def create_test_entitlement( *, owner_type: Literal[1, 2], # 1: guild, 2: user ) -> Response[entitlement.Entitlement]: - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "sku_id": sku_id, "owner_id": owner_id, "owner_type": owner_type, @@ -2583,8 +2577,8 @@ def get_global_commands( application_id: Snowflake, *, with_localizations: bool = True, - ) -> Response[List[interactions.ApplicationCommand]]: - params: Dict[str, Any] = {} + ) -> Response[list[interactions.ApplicationCommand]]: + params: dict[str, Any] = {} # the API currently interprets any non-empty value as truthy if with_localizations: params["with_localizations"] = int(with_localizations) @@ -2637,8 +2631,8 @@ def delete_global_command( return self.request(r) def bulk_upsert_global_commands( - self, application_id: Snowflake, payload: List[interactions.EditApplicationCommand] - ) -> Response[List[interactions.ApplicationCommand]]: + self, application_id: Snowflake, payload: list[interactions.EditApplicationCommand] + ) -> Response[list[interactions.ApplicationCommand]]: r = Route("PUT", "/applications/{application_id}/commands", application_id=application_id) return self.request(r, json=payload) @@ -2650,8 +2644,8 @@ def get_guild_commands( guild_id: Snowflake, *, with_localizations: bool = True, - ) -> Response[List[interactions.ApplicationCommand]]: - params: Dict[str, Any] = {} + ) -> Response[list[interactions.ApplicationCommand]]: + params: dict[str, Any] = {} # the API currently interprets any non-empty value as truthy if with_localizations: params["with_localizations"] = int(with_localizations) @@ -2728,8 +2722,8 @@ def bulk_upsert_guild_commands( self, application_id: Snowflake, guild_id: Snowflake, - payload: List[interactions.EditApplicationCommand], - ) -> Response[List[interactions.ApplicationCommand]]: + payload: list[interactions.EditApplicationCommand], + ) -> Response[list[interactions.ApplicationCommand]]: r = Route( "PUT", "/applications/{application_id}/guilds/{guild_id}/commands", @@ -2745,14 +2739,14 @@ def _edit_webhook_helper( route: Route, file: Optional[File] = None, content: Optional[str] = None, - embeds: Optional[List[embed.Embed]] = None, + embeds: Optional[list[embed.Embed]] = None, allowed_mentions: Optional[message.AllowedMentions] = None, - attachments: Optional[List[Attachment]] = None, + attachments: Optional[list[Attachment]] = None, ) -> Response[message.Message]: # TODO: this does not work how it should (e.g. `embeds=[]` is ignored). # This method (or rather its calling methods) is completely unused, and hence likely untested - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} if content: payload["content"] = content if embeds: @@ -2781,7 +2775,7 @@ def create_interaction_response( interaction_id=interaction_id, interaction_token=token, ) - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "type": type, } @@ -2809,9 +2803,9 @@ def edit_original_interaction_response( token: str, file: Optional[File] = None, content: Optional[str] = None, - embeds: Optional[List[embed.Embed]] = None, + embeds: Optional[list[embed.Embed]] = None, allowed_mentions: Optional[message.AllowedMentions] = None, - attachments: Optional[List[Attachment]] = None, + attachments: Optional[list[Attachment]] = None, ) -> Response[message.Message]: r = Route( "PATCH", @@ -2843,10 +2837,10 @@ def create_followup_message( self, application_id: Snowflake, token: str, - files: Optional[List[File]] = None, + files: Optional[list[File]] = None, content: Optional[str] = None, tts: bool = False, - embeds: Optional[List[embed.Embed]] = None, + embeds: Optional[list[embed.Embed]] = None, allowed_mentions: Optional[message.AllowedMentions] = None, ) -> Response[message.Message]: r = Route( @@ -2873,9 +2867,9 @@ def edit_followup_message( message_id: Snowflake, file: Optional[File] = None, content: Optional[str] = None, - embeds: Optional[List[embed.Embed]] = None, + embeds: Optional[list[embed.Embed]] = None, allowed_mentions: Optional[message.AllowedMentions] = None, - attachments: Optional[List[Attachment]] = None, + attachments: Optional[list[Attachment]] = None, ) -> Response[message.Message]: r = Route( "PATCH", @@ -2909,7 +2903,7 @@ def get_guild_application_command_permissions( self, application_id: Snowflake, guild_id: Snowflake, - ) -> Response[List[interactions.GuildApplicationCommandPermissions]]: + ) -> Response[list[interactions.GuildApplicationCommandPermissions]]: r = Route( "GET", "/applications/{application_id}/guilds/{guild_id}/commands/permissions", @@ -2935,7 +2929,7 @@ def get_application_command_permissions( # Soundboard - def get_default_soundboard_sounds(self) -> Response[List[soundboard.SoundboardSound]]: + def get_default_soundboard_sounds(self) -> Response[list[soundboard.SoundboardSound]]: return self.request(Route("GET", "/soundboard-default-sounds")) def get_guild_soundboard_sound( @@ -2972,7 +2966,7 @@ def create_guild_soundboard_sound( emoji_name: Optional[str] = None, reason: Optional[str] = None, ) -> Response[soundboard.GuildSoundboardSound]: - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "name": name, "sound": sound, } @@ -3040,7 +3034,7 @@ def send_soundboard_sound( *, source_guild_id: Optional[Snowflake] = None, ) -> Response[None]: - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "sound_id": sound_id, } if source_guild_id is not None: @@ -3053,7 +3047,7 @@ def send_soundboard_sound( # Misc - def get_voice_regions(self) -> Response[List[voice.VoiceRegion]]: + def get_voice_regions(self) -> Response[list[voice.VoiceRegion]]: return self.request(Route("GET", "/voice/regions")) def application_info(self) -> Response[appinfo.AppInfo]: @@ -3064,7 +3058,7 @@ def edit_application_info(self, **fields: Any) -> Response[appinfo.AppInfo]: def get_application_role_connection_metadata_records( self, application_id: Snowflake - ) -> Response[List[application_role_connection.ApplicationRoleConnectionMetadata]]: + ) -> Response[list[application_role_connection.ApplicationRoleConnectionMetadata]]: return self.request( Route( "GET", @@ -3077,7 +3071,7 @@ def edit_application_role_connection_metadata_records( self, application_id: Snowflake, records: Sequence[application_role_connection.ApplicationRoleConnectionMetadata], - ) -> Response[List[application_role_connection.ApplicationRoleConnectionMetadata]]: + ) -> Response[list[application_role_connection.ApplicationRoleConnectionMetadata]]: return self.request( Route( "PUT", @@ -3097,7 +3091,7 @@ async def get_gateway(self, *, encoding: str = "json", zlib: bool = True) -> str async def get_bot_gateway( self, *, encoding: str = "json", zlib: bool = True - ) -> Tuple[int, str, gateway.SessionStartLimit]: + ) -> tuple[int, str, gateway.SessionStartLimit]: try: data: gateway.GatewayBot = await self.request(Route("GET", "/gateway/bot")) except HTTPException as exc: diff --git a/disnake/i18n.py b/disnake/i18n.py index 79de355d6d..88fed77b94 100644 --- a/disnake/i18n.py +++ b/disnake/i18n.py @@ -11,13 +11,9 @@ from typing import ( TYPE_CHECKING, Any, - DefaultDict, - Dict, Generic, Literal, Optional, - Set, - Type, TypeVar, Union, overload, @@ -48,7 +44,7 @@ _log = logging.getLogger(__name__) -LocalizationsDict = Union[Dict[Locale, str], Dict[str, str]] +LocalizationsDict = Union[dict[Locale, str], dict[str, str]] Localizations = Union[str, LocalizationsDict] StringT = TypeVar("StringT", str, Optional[str], covariant=True) @@ -139,7 +135,7 @@ def _cast(cls, string: LocalizedRequired, required: Literal[True]) -> Localized[ @classmethod def _cast( - cls: Type[Localized[Any]], string: Union[Optional[str], Localized[Any]], required: bool + cls: type[Localized[Any]], string: Union[Optional[str], Localized[Any]], required: bool ) -> Localized[Any]: if not isinstance(string, Localized): string = cls(string, data=None) @@ -184,7 +180,7 @@ class LocalizationValue: def __init__(self, localizations: Optional[Localizations]) -> None: self._key: Optional[str] - self._data: Optional[Dict[str, str]] + self._data: Optional[dict[str, str]] if localizations is None: # no localization @@ -234,7 +230,7 @@ def _copy(self) -> LocalizationValue: return ins @property - def data(self) -> Optional[Dict[str, str]]: + def data(self) -> Optional[dict[str, str]]: """:class:`dict`\\[:class:`str`, :class:`str`] | :data:`None`: A dict with a locale -> localization mapping, if available.""" if self._data is MISSING: # This will happen when `_link(store)` hasn't been called yet, which *shouldn't* occur under normal circumstances. @@ -267,7 +263,7 @@ class LocalizationProtocol(ABC): """ @abstractmethod - def get(self, key: str) -> Optional[Dict[str, str]]: + def get(self, key: str) -> Optional[dict[str, str]]: """Returns localizations for the specified key. Parameters @@ -327,10 +323,10 @@ class LocalizationStore(LocalizationProtocol): def __init__(self, *, strict: bool) -> None: self.strict = strict - self._loc: DefaultDict[str, Dict[str, str]] = defaultdict(dict) - self._paths: Set[Path] = set() + self._loc: defaultdict[str, dict[str, str]] = defaultdict(dict) + self._paths: set[Path] = set() - def get(self, key: str) -> Optional[Dict[str, str]]: + def get(self, key: str) -> Optional[dict[str, str]]: """Returns localizations for the specified key. Parameters @@ -419,7 +415,7 @@ def _load_file(self, path: Path) -> None: msg = f"Unable to load '{path}': {e}" raise RuntimeError(msg) from e - def _load_dict(self, data: Dict[str, Optional[str]], locale: str) -> None: + def _load_dict(self, data: dict[str, Optional[str]], locale: str) -> None: if not isinstance(data, dict) or not all( o is None or isinstance(o, str) for o in data.values() ): diff --git a/disnake/integrations.py b/disnake/integrations.py index bd80048ae3..6e87ac3f06 100644 --- a/disnake/integrations.py +++ b/disnake/integrations.py @@ -3,7 +3,7 @@ from __future__ import annotations import datetime -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type +from typing import TYPE_CHECKING, Any, Optional from .enums import ExpireBehaviour, try_enum from .user import User @@ -287,7 +287,7 @@ async def edit( TypeError ``expire_behaviour`` did not receive a :class:`ExpireBehaviour`. """ - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} if expire_behaviour is not MISSING: if not isinstance(expire_behaviour, ExpireBehaviour): msg = "expire_behaviour field must be of type ExpireBehaviour" @@ -416,13 +416,13 @@ def _from_data(self, data: BotIntegrationPayload) -> None: self.application: IntegrationApplication = IntegrationApplication( data=data["application"], state=self._state ) - self.scopes: List[str] = data.get("scopes") or [] + self.scopes: list[str] = data.get("scopes") or [] def __repr__(self) -> str: return f"<{self.__class__.__name__} id={self.id} name={self.name!r} scopes={self.scopes!r}>" -def _integration_factory(value: str) -> Tuple[Type[Integration], str]: +def _integration_factory(value: str) -> tuple[type[Integration], str]: if value == "discord": return BotIntegration, value elif value in ("twitch", "youtube"): diff --git a/disnake/interactions/application_command.py b/disnake/interactions/application_command.py index 3f92637488..e8f275d047 100644 --- a/disnake/interactions/application_command.py +++ b/disnake/interactions/application_command.py @@ -2,7 +2,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Tuple, Union +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Optional, Union from .. import utils from ..enums import ApplicationCommandType, Locale, OptionType, try_enum @@ -159,12 +160,12 @@ def target(self) -> Optional[Union[User, Member, Message]]: return self.data.target @property - def options(self) -> Dict[str, Any]: + def options(self) -> dict[str, Any]: """:class:`dict`\\[:class:`str`, :class:`Any`]: The full option tree, including nestings""" return {opt.name: opt._simplified_value() for opt in self.data.options} @property - def filled_options(self) -> Dict[str, Any]: + def filled_options(self) -> dict[str, Any]: """:class:`dict`\\[:class:`str`, :class:`Any`]: The options of the command (or sub-command) being invoked""" _, kwargs = self.data._get_chain_and_kwargs() return kwargs @@ -213,7 +214,7 @@ class MessageCommandInteraction(ApplicationCommandInteraction[ClientT]): target: Message -class ApplicationCommandInteractionData(Dict[str, Any]): +class ApplicationCommandInteractionData(dict[str, Any]): """Represents the data of an interaction with an application command. .. versionadded:: 2.1 @@ -262,7 +263,7 @@ def __init__( target = self.resolved.get_by_id(self.target_id) self.target: Optional[Union[User, Member, Message]] = target # type: ignore - self.options: List[ApplicationCommandInteractionDataOption] = [ + self.options: list[ApplicationCommandInteractionDataOption] = [ ApplicationCommandInteractionDataOption(data=d, resolved=self.resolved) for d in data.get("options", []) ] @@ -274,8 +275,8 @@ def __repr__(self) -> str: ) def _get_chain_and_kwargs( - self, chain: Optional[Tuple[str, ...]] = None - ) -> Tuple[Tuple[str, ...], Dict[str, Any]]: + self, chain: Optional[tuple[str, ...]] = None + ) -> tuple[tuple[str, ...], dict[str, Any]]: """Returns a chain of sub-command names and a dict of filled options.""" if chain is None: chain = () @@ -305,7 +306,7 @@ def focused_option(self) -> ApplicationCommandInteractionDataOption: return self._get_focused_option() # type: ignore -class ApplicationCommandInteractionDataOption(Dict[str, Any]): +class ApplicationCommandInteractionDataOption(dict[str, Any]): """Represents the structure of an interaction data option from the API. Attributes @@ -334,7 +335,7 @@ def __init__(self, *, data: Mapping[str, Any], resolved: InteractionDataResolved if (value := data.get("value")) is not None: self.value: Any = resolved.get_with_type(value, self.type, value) - self.options: List[ApplicationCommandInteractionDataOption] = [ + self.options: list[ApplicationCommandInteractionDataOption] = [ ApplicationCommandInteractionDataOption(data=d, resolved=resolved) for d in data.get("options", []) ] @@ -360,8 +361,8 @@ def _get_focused_option(self) -> Optional[ApplicationCommandInteractionDataOptio return None def _get_chain_and_kwargs( - self, chain: Optional[Tuple[str, ...]] = None - ) -> Tuple[Tuple[str, ...], Dict[str, Any]]: + self, chain: Optional[tuple[str, ...]] = None + ) -> tuple[tuple[str, ...], dict[str, Any]]: if chain is None: chain = () for option in self.options: diff --git a/disnake/interactions/base.py b/disnake/interactions/base.py index ddd6b779e9..383e6d8651 100644 --- a/disnake/interactions/base.py +++ b/disnake/interactions/base.py @@ -3,17 +3,13 @@ from __future__ import annotations import asyncio +from collections.abc import Mapping, Sequence from datetime import timedelta from typing import ( TYPE_CHECKING, Any, - Dict, Generic, - List, - Mapping, Optional, - Sequence, - Tuple, TypeVar, Union, cast, @@ -200,7 +196,7 @@ class Interaction(Generic[ClientT]): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "data", "id", "type", @@ -276,7 +272,7 @@ def __init__(self, *, data: InteractionPayload, state: ConnectionState) -> None: data["channel"], guild_fallback, return_messageable=True ) - self.entitlements: List[Entitlement] = ( + self.entitlements: list[Entitlement] = ( [Entitlement(data=e, state=state) for e in entitlements_data] if (entitlements_data := data.get("entitlements")) else [] @@ -445,10 +441,10 @@ async def edit_original_response( content: Optional[str] = MISSING, *, embed: Optional[Embed] = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, file: File = MISSING, - files: List[File] = MISSING, - attachments: Optional[List[Attachment]] = MISSING, + files: list[File] = MISSING, + attachments: Optional[list[Attachment]] = MISSING, view: Optional[View] = MISSING, components: Optional[MessageComponents] = MISSING, poll: Poll = MISSING, @@ -695,9 +691,9 @@ async def send( content: Optional[str] = None, *, embed: Embed = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, file: File = MISSING, - files: List[File] = MISSING, + files: list[File] = MISSING, allowed_mentions: AllowedMentions = MISSING, view: View = MISSING, components: MessageComponents = MISSING, @@ -834,7 +830,7 @@ class InteractionResponse: .. versionadded:: 2.0 """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "_parent", "_response_type", ) @@ -916,7 +912,7 @@ async def defer( raise InteractionResponded(self._parent) defer_type: Optional[InteractionResponseType] = None - data: Dict[str, Any] = {} + data: dict[str, Any] = {} parent = self._parent if parent.type is InteractionType.application_command: @@ -985,9 +981,9 @@ async def send_message( content: Optional[str] = None, *, embed: Embed = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, file: File = MISSING, - files: List[File] = MISSING, + files: list[File] = MISSING, allowed_mentions: AllowedMentions = MISSING, view: View = MISSING, components: MessageComponents = MISSING, @@ -1086,7 +1082,7 @@ async def send_message( if self._response_type is not None: raise InteractionResponded(self._parent) - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "tts": tts, } @@ -1200,10 +1196,10 @@ async def edit_message( content: Optional[str] = MISSING, *, embed: Optional[Embed] = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, file: File = MISSING, - files: List[File] = MISSING, - attachments: Optional[List[Attachment]] = MISSING, + files: list[File] = MISSING, + attachments: Optional[list[Attachment]] = MISSING, view: Optional[View] = MISSING, components: Optional[MessageComponents] = MISSING, flags: MessageFlags = MISSING, @@ -1439,7 +1435,7 @@ async def autocomplete(self, *, choices: Choices) -> None: if self._response_type is not None: raise InteractionResponded(self._parent) - choices_data: List[ApplicationCommandOptionChoicePayload] + choices_data: list[ApplicationCommandOptionChoicePayload] if isinstance(choices, Mapping): choices_data = [{"name": n, "value": v} for n, v in choices.items()] else: @@ -1565,7 +1561,7 @@ async def send_modal( "title": title, "custom_id": custom_id, "components": cast( - "List[ModalTopLevelComponentPayload]", + "list[ModalTopLevelComponentPayload]", [component.to_component_dict() for component in items], ), } @@ -1743,7 +1739,7 @@ async def edit( *, embed: Optional[Embed] = ..., file: File = ..., - attachments: Optional[List[Attachment]] = ..., + attachments: Optional[list[Attachment]] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., allowed_mentions: Optional[AllowedMentions] = ..., @@ -1758,8 +1754,8 @@ async def edit( content: Optional[str] = ..., *, embed: Optional[Embed] = ..., - files: List[File] = ..., - attachments: Optional[List[Attachment]] = ..., + files: list[File] = ..., + attachments: Optional[list[Attachment]] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., allowed_mentions: Optional[AllowedMentions] = ..., @@ -1773,9 +1769,9 @@ async def edit( self, content: Optional[str] = ..., *, - embeds: List[Embed] = ..., + embeds: list[Embed] = ..., file: File = ..., - attachments: Optional[List[Attachment]] = ..., + attachments: Optional[list[Attachment]] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., allowed_mentions: Optional[AllowedMentions] = ..., @@ -1789,9 +1785,9 @@ async def edit( self, content: Optional[str] = ..., *, - embeds: List[Embed] = ..., - files: List[File] = ..., - attachments: Optional[List[Attachment]] = ..., + embeds: list[Embed] = ..., + files: list[File] = ..., + attachments: Optional[list[Attachment]] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., allowed_mentions: Optional[AllowedMentions] = ..., @@ -1805,10 +1801,10 @@ async def edit( content: Optional[str] = MISSING, *, embed: Optional[Embed] = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, file: File = MISSING, - files: List[File] = MISSING, - attachments: Optional[List[Attachment]] = MISSING, + files: list[File] = MISSING, + attachments: Optional[list[Attachment]] = MISSING, suppress_embeds: bool = MISSING, flags: MessageFlags = MISSING, allowed_mentions: Optional[AllowedMentions] = MISSING, @@ -1996,7 +1992,7 @@ async def inner_call(delay: float = delay) -> None: await self._state._interaction.delete_original_response() -class InteractionDataResolved(Dict[str, Any]): +class InteractionDataResolved(dict[str, Any]): """Represents the resolved data related to an interaction. .. versionadded:: 2.1 @@ -2034,12 +2030,12 @@ def __init__( data = data or {} super().__init__(data) - self.members: Dict[int, Member] = {} - self.users: Dict[int, User] = {} - self.roles: Dict[int, Role] = {} - self.channels: Dict[int, AnyChannel] = {} - self.messages: Dict[int, Message] = {} - self.attachments: Dict[int, Attachment] = {} + self.members: dict[int, Member] = {} + self.users: dict[int, User] = {} + self.roles: dict[int, Role] = {} + self.channels: dict[int, AnyChannel] = {} + self.messages: dict[int, Message] = {} + self.attachments: dict[int, Attachment] = {} users = data.get("users", {}) members = data.get("members", {}) diff --git a/disnake/interactions/message.py b/disnake/interactions/message.py index 0a984dac2c..ed6e21d835 100644 --- a/disnake/interactions/message.py +++ b/disnake/interactions/message.py @@ -2,7 +2,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Union +from collections.abc import Sequence +from typing import TYPE_CHECKING, Any, Optional, Union from ..components import VALID_ACTION_ROW_MESSAGE_COMPONENT_TYPES, ActionRowMessageComponent from ..enums import ComponentType, try_enum @@ -136,7 +137,7 @@ def __init__(self, *, data: MessageInteractionPayload, state: ConnectionState) - self.message = Message(state=self._state, channel=self.channel, data=data["message"]) @property - def values(self) -> Optional[List[str]]: + def values(self) -> Optional[list[str]]: """:class:`list`\\[:class:`str`] | :data:`None`: The values the user selected. For select menus of type :attr:`~ComponentType.string_select`, @@ -168,7 +169,7 @@ def resolved_values( return self.data.values resolved = self.data.resolved - values: List[Union[Member, User, Role, AnyChannel]] = [] + values: list[Union[Member, User, Role, AnyChannel]] = [] for key in self.data.values: # force upcast to avoid typing issues; we expect the api to only provide valid values value: Any = resolved.get_with_type(key, component_type, key) @@ -190,7 +191,7 @@ def component(self) -> ActionRowMessageComponent: raise Exception(msg) # noqa: TRY002 -class MessageInteractionData(Dict[str, Any]): +class MessageInteractionData(dict[str, Any]): """Represents the data of an interaction with a message component. .. versionadded:: 2.1 @@ -221,7 +222,7 @@ def __init__( super().__init__(data) self.custom_id: str = data["custom_id"] self.component_type: ComponentType = try_enum(ComponentType, data["component_type"]) - self.values: Optional[List[str]] = ( + self.values: Optional[list[str]] = ( list(map(str, values)) if (values := data.get("values")) else None ) diff --git a/disnake/interactions/modal.py b/disnake/interactions/modal.py index 0a1401863e..a409d790c4 100644 --- a/disnake/interactions/modal.py +++ b/disnake/interactions/modal.py @@ -2,15 +2,12 @@ from __future__ import annotations +from collections.abc import Generator, Sequence from typing import ( TYPE_CHECKING, Any, Callable, - Dict, - Generator, - List, Optional, - Sequence, TypeVar, Union, ) @@ -41,7 +38,7 @@ T = TypeVar("T") # {custom_id: text_input_value | select_values} -ResolvedValues = Dict[str, Union[str, Sequence[T]]] +ResolvedValues = dict[str, Union[str, Sequence[T]]] class ModalInteraction(Interaction[ClientT]): @@ -236,7 +233,7 @@ def resolved_values(self) -> ResolvedValues[Union[str, Member, User, Role, AnyCh return self._resolve_values(lambda id, type: resolved_data.get_with_type(id, type, str(id))) # type: ignore @cached_slot_property("_cs_text_values") - def text_values(self) -> Dict[str, str]: + def text_values(self) -> dict[str, str]: """:class:`dict`\\[:class:`str`, :class:`str`]: Returns the text values the user has entered in the modal. This is a dict of the form ``{custom_id: value}``. """ @@ -253,7 +250,7 @@ def custom_id(self) -> str: return self.data.custom_id -class ModalInteractionData(Dict[str, Any]): +class ModalInteractionData(dict[str, Any]): """Represents the data of an interaction with a modal. .. versionadded:: 2.4 @@ -286,7 +283,7 @@ def __init__( # This uses stripped-down component dicts, as we only receive # partial data from the API, generally only containing `type`, `custom_id`, `id`, # and relevant fields like a select's `values`. - self.components: List[ModalInteractionComponentDataPayload] = data["components"] + self.components: list[ModalInteractionComponentDataPayload] = data["components"] self.resolved: InteractionDataResolved = InteractionDataResolved( data=data.get("resolved", {}), parent=parent ) diff --git a/disnake/invite.py b/disnake/invite.py index adb6e15847..d719c01dca 100644 --- a/disnake/invite.py +++ b/disnake/invite.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, List, Optional, Union +from typing import TYPE_CHECKING, Optional, Union from .appinfo import PartialAppInfo from .asset import Asset @@ -95,7 +95,7 @@ def __init__(self, *, state: ConnectionState, data: InviteChannelPayload) -> Non self.name: Optional[str] = data.get("name") self.type: ChannelType = try_enum(ChannelType, data["type"]) if self.type is ChannelType.group: - self._recipients: List[GroupInviteRecipientPayload] = data.get("recipients", []) + self._recipients: list[GroupInviteRecipientPayload] = data.get("recipients", []) else: self._recipients = [] self._icon: Optional[str] = data.get("icon") @@ -202,7 +202,7 @@ def __init__(self, state: ConnectionState, data: InviteGuildPayload, id: int) -> self._state: ConnectionState = state self.id: int = id self.name: str = data["name"] - self.features: List[GuildFeature] = data.get("features", []) + self.features: list[GuildFeature] = data.get("features", []) self._icon: Optional[str] = data.get("icon") self._banner: Optional[str] = data.get("banner") self._splash: Optional[str] = data.get("splash") diff --git a/disnake/iterators.py b/disnake/iterators.py index a662de5c7b..a92cd5d81d 100644 --- a/disnake/iterators.py +++ b/disnake/iterators.py @@ -4,15 +4,11 @@ import asyncio import datetime +from collections.abc import AsyncIterator, Awaitable, Generator from typing import ( TYPE_CHECKING, Any, - AsyncIterator, - Awaitable, Callable, - Dict, - Generator, - List, Optional, TypeVar, Union, @@ -119,7 +115,7 @@ def map(self, func: _Func[T, OT]) -> _MappedAsyncIterator[OT]: def filter(self, predicate: Optional[_Func[T, bool]]) -> _FilteredAsyncIterator[T]: return _FilteredAsyncIterator(self, predicate) - async def flatten(self) -> List[T]: + async def flatten(self) -> list[T]: return [element async for element in self] async def __anext__(self) -> T: @@ -129,13 +125,13 @@ async def __anext__(self) -> T: raise StopAsyncIteration from None -class _ChunkedAsyncIterator(_AsyncIterator[List[T]]): +class _ChunkedAsyncIterator(_AsyncIterator[list[T]]): def __init__(self, iterator: _AsyncIterator[T], max_size: int) -> None: self.iterator = iterator self.max_size = max_size - async def next(self) -> List[T]: - ret: List[T] = [] + async def next(self) -> list[T]: + ret: list[T] = [] n = 0 while n < self.max_size: try: @@ -208,7 +204,7 @@ async def fill_users(self) -> None: retrieve = min(self.limit, 100) after = self.after.id if self.after else None - data: List[PartialUserPayload] = await self.getter( + data: list[PartialUserPayload] = await self.getter( self.channel_id, self.message.id, self.emoji, retrieve, after=after ) @@ -360,35 +356,35 @@ async def fill_messages(self) -> None: for element in data: await self.messages.put(self.state.create_message(channel=channel, data=element)) - async def _retrieve_messages(self, retrieve: int) -> List[MessagePayload]: + async def _retrieve_messages(self, retrieve: int) -> list[MessagePayload]: """Retrieve messages and update next parameters.""" raise NotImplementedError - async def _retrieve_messages_before_strategy(self, retrieve: int) -> List[MessagePayload]: + async def _retrieve_messages_before_strategy(self, retrieve: int) -> list[MessagePayload]: """Retrieve messages using before parameter.""" before = self.before.id if self.before else None - data: List[MessagePayload] = await self.logs_from(self.channel.id, retrieve, before=before) + data: list[MessagePayload] = await self.logs_from(self.channel.id, retrieve, before=before) if len(data): if self.limit is not None: self.limit -= retrieve self.before = Object(id=int(data[-1]["id"])) return data - async def _retrieve_messages_after_strategy(self, retrieve: int) -> List[MessagePayload]: + async def _retrieve_messages_after_strategy(self, retrieve: int) -> list[MessagePayload]: """Retrieve messages using after parameter.""" after = self.after.id if self.after else None - data: List[MessagePayload] = await self.logs_from(self.channel.id, retrieve, after=after) + data: list[MessagePayload] = await self.logs_from(self.channel.id, retrieve, after=after) if len(data): if self.limit is not None: self.limit -= retrieve self.after = Object(id=int(data[0]["id"])) return data - async def _retrieve_messages_around_strategy(self, retrieve: int) -> List[MessagePayload]: + async def _retrieve_messages_around_strategy(self, retrieve: int) -> list[MessagePayload]: """Retrieve messages using around parameter.""" if self.around: around = self.around.id if self.around else None - data: List[MessagePayload] = await self.logs_from( + data: list[MessagePayload] = await self.logs_from( self.channel.id, retrieve, around=around ) self.around = None @@ -477,20 +473,20 @@ async def fill_bans(self) -> None: ) ) - async def _retrieve_bans_before_strategy(self, retrieve: int) -> List[BanPayload]: + async def _retrieve_bans_before_strategy(self, retrieve: int) -> list[BanPayload]: """Retrieve bans using before parameter.""" before = self.before.id if self.before else None - data: List[BanPayload] = await self.get_bans(self.guild.id, retrieve, before=before) + data: list[BanPayload] = await self.get_bans(self.guild.id, retrieve, before=before) if len(data): if self.limit is not None: self.limit -= len(data) self.before = Object(id=int(data[0]["user"]["id"])) return data - async def _retrieve_bans_after_strategy(self, retrieve: int) -> List[BanPayload]: + async def _retrieve_bans_after_strategy(self, retrieve: int) -> list[BanPayload]: """Retrieve bans using after parameter.""" after = self.after.id if self.after else None - data: List[BanPayload] = await self.get_bans(self.guild.id, retrieve, after=after) + data: list[BanPayload] = await self.get_bans(self.guild.id, retrieve, after=after) if len(data): if self.limit is not None: self.limit -= len(data) @@ -602,7 +598,7 @@ async def _fill(self) -> None: state = self._state - appcmds: Dict[int, APIApplicationCommand] = {} + appcmds: dict[int, APIApplicationCommand] = {} for data in log_data.get("application_commands", []): try: cmd = application_command_factory(data) @@ -752,14 +748,14 @@ async def fill_guilds(self) -> None: for element in data: await self.guilds.put(self.create_guild(element)) - async def _retrieve_guilds(self, retrieve: int) -> List[GuildPayload]: + async def _retrieve_guilds(self, retrieve: int) -> list[GuildPayload]: """Retrieve guilds and update next parameters.""" raise NotImplementedError - async def _retrieve_guilds_before_strategy(self, retrieve: int) -> List[GuildPayload]: + async def _retrieve_guilds_before_strategy(self, retrieve: int) -> list[GuildPayload]: """Retrieve guilds using before parameter.""" before = self.before.id if self.before else None - data: List[GuildPayload] = await self.get_guilds( + data: list[GuildPayload] = await self.get_guilds( retrieve, before=before, with_counts=self.with_counts ) if len(data): @@ -768,10 +764,10 @@ async def _retrieve_guilds_before_strategy(self, retrieve: int) -> List[GuildPay self.before = Object(id=int(data[0]["id"])) return data - async def _retrieve_guilds_after_strategy(self, retrieve: int) -> List[GuildPayload]: + async def _retrieve_guilds_after_strategy(self, retrieve: int) -> list[GuildPayload]: """Retrieve guilds using after parameter.""" after = self.after.id if self.after else None - data: List[GuildPayload] = await self.get_guilds( + data: list[GuildPayload] = await self.get_guilds( retrieve, after=after, with_counts=self.with_counts ) if len(data): @@ -909,7 +905,7 @@ async def fill_queue(self) -> None: # endpoint requires at least 2, for unknown reasons data = await self.endpoint(self.channel_id, before=self.before, limit=max(2, limit)) - threads: List[ThreadPayload] = data.get("threads", []) + threads: list[ThreadPayload] = data.get("threads", []) # special case: since the minimum limit the endpoint accepts is 2, # we request 2 threads when only needing 1, so slice the list before yielding if limit == 1: @@ -1010,7 +1006,7 @@ async def fill_users(self) -> None: for user in data: await self.users.put(self.create_user(user)) - async def _before_strategy(self, retrieve: int) -> List[GuildScheduledEventUserPayload]: + async def _before_strategy(self, retrieve: int) -> list[GuildScheduledEventUserPayload]: before = self.before.id if self.before else None data = await self.get_event_users( self.event.guild_id, @@ -1027,7 +1023,7 @@ async def _before_strategy(self, retrieve: int) -> List[GuildScheduledEventUserP self.before = Object(id=int(data[0]["user"]["id"])) return data - async def _after_strategy(self, retrieve: int) -> List[GuildScheduledEventUserPayload]: + async def _after_strategy(self, retrieve: int) -> list[GuildScheduledEventUserPayload]: after = self.after.id if self.after else None data = await self.get_event_users( self.event.guild_id, @@ -1056,7 +1052,7 @@ def __init__( limit: Optional[int], user_id: Optional[int] = None, guild_id: Optional[int] = None, - sku_ids: Optional[List[int]] = None, + sku_ids: Optional[list[int]] = None, before: Optional[Union[Snowflake, datetime.datetime]] = None, after: Optional[Union[Snowflake, datetime.datetime]] = None, exclude_ended: bool = False, @@ -1074,7 +1070,7 @@ def __init__( self.after: Snowflake = after or OLDEST_OBJECT self.user_id: Optional[int] = user_id self.guild_id: Optional[int] = guild_id - self.sku_ids: Optional[List[int]] = sku_ids + self.sku_ids: Optional[list[int]] = sku_ids self.exclude_ended: bool = exclude_ended self.exclude_deleted: bool = exclude_deleted @@ -1125,7 +1121,7 @@ async def _fill(self) -> None: for entitlement in data: await self.entitlements.put(Entitlement(data=entitlement, state=self.state)) - async def _before_strategy(self, retrieve: int) -> List[EntitlementPayload]: + async def _before_strategy(self, retrieve: int) -> list[EntitlementPayload]: before = self.before.id if self.before else None data = await self.request( self.application_id, @@ -1143,7 +1139,7 @@ async def _before_strategy(self, retrieve: int) -> List[EntitlementPayload]: self.before = Object(id=int(data[-1]["id"])) return data - async def _after_strategy(self, retrieve: int) -> List[EntitlementPayload]: + async def _after_strategy(self, retrieve: int) -> list[EntitlementPayload]: after = self.after.id data = await self.request( self.application_id, @@ -1229,7 +1225,7 @@ async def _fill(self) -> None: for subscription in data: await self.subscriptions.put(Subscription(data=subscription, state=self._state)) - async def _before_strategy(self, retrieve: int) -> List[SubscriptionPayload]: + async def _before_strategy(self, retrieve: int) -> list[SubscriptionPayload]: before = self.before.id if self.before else None data = await self.request( self.sku_id, @@ -1245,7 +1241,7 @@ async def _before_strategy(self, retrieve: int) -> List[SubscriptionPayload]: self.before = Object(id=min(int(data[0]["id"]), int(data[-1]["id"]))) return data - async def _after_strategy(self, retrieve: int) -> List[SubscriptionPayload]: + async def _after_strategy(self, retrieve: int) -> list[SubscriptionPayload]: after = self.after.id data = await self.request( self.sku_id, @@ -1351,7 +1347,7 @@ def __init__( # defined to maintain backward compatibility with the old `pins` method @deprecated("async for msg in channel.pins()") - def __await__(self) -> Generator[None, None, List[Message]]: + def __await__(self) -> Generator[None, None, list[Message]]: return self.flatten().__await__() async def next(self) -> Message: diff --git a/disnake/member.py b/disnake/member.py index aae354f268..365bbea489 100644 --- a/disnake/member.py +++ b/disnake/member.py @@ -5,18 +5,14 @@ import datetime import itertools import sys +from collections.abc import Sequence from operator import attrgetter from typing import ( TYPE_CHECKING, Any, Callable, - Dict, - List, Literal, Optional, - Sequence, - Tuple, - Type, Union, cast, overload, @@ -166,7 +162,7 @@ def __repr__(self) -> str: return f"<{self.__class__.__name__} {inner}>" -def flatten_user(cls: Type[Member]) -> Type[Member]: +def flatten_user(cls: type[Member]) -> type[Member]: for attr, value in itertools.chain(BaseUser.__dict__.items(), User.__dict__.items()): # ignore private/special methods if attr.startswith("_"): @@ -292,7 +288,7 @@ class Member(disnake.abc.Messageable, _UserTag): avatar: Optional[Asset] dm_channel: Optional[DMChannel] create_dm = User.create_dm - mutual_guilds: List[Guild] + mutual_guilds: list[Guild] public_flags: PublicUserFlags banner: Optional[Asset] accent_color: Optional[Colour] @@ -339,8 +335,8 @@ def __init__( data.get("premium_since") ) self._roles: utils.SnowflakeList = utils.SnowflakeList(map(int, data["roles"])) - self._client_status: Dict[Optional[str], str] = {None: "offline"} - self.activities: Tuple[ActivityTypes, ...] = () + self._client_status: dict[Optional[str], str] = {None: "offline"} + self.activities: tuple[ActivityTypes, ...] = () self.nick: Optional[str] = data.get("nick") self.pending: bool = data.get("pending", False) self._avatar: Optional[str] = data.get("avatar") @@ -450,7 +446,7 @@ def _update(self, data: GuildMemberUpdateEvent) -> None: def _presence_update( self, data: PresenceData, user: UserPayload - ) -> Optional[Tuple[User, User]]: + ) -> Optional[tuple[User, User]]: self.activities = tuple(create_activity(a, state=self._state) for a in data["activities"]) self._client_status = { sys.intern(key): sys.intern(value) # type: ignore @@ -462,7 +458,7 @@ def _presence_update( return self._update_inner_user(user) return None - def _update_inner_user(self, user: UserPayload) -> Optional[Tuple[User, User]]: + def _update_inner_user(self, user: UserPayload) -> Optional[tuple[User, User]]: u = self._user original = ( u.name, @@ -574,14 +570,14 @@ def color(self) -> Colour: return self.colour @property - def roles(self) -> List[Role]: + def roles(self) -> list[Role]: """:class:`list`\\[:class:`Role`]: A :class:`list` of :class:`Role` that the member belongs to. Note that the first element of this list is always the default '@everyone' role. These roles are sorted by their position in the role hierarchy. """ - result: List[Role] = [] + result: list[Role] = [] g = self.guild for role_id in self._roles: role = g.get_role(role_id) @@ -865,7 +861,7 @@ async def _edit_self( banner: Optional[AssetBytes] = MISSING, reason: Optional[str] = None, ) -> Optional[Member]: - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} if nick is not MISSING: payload["nick"] = nick or "" @@ -1023,7 +1019,7 @@ async def edit( me = self._state.self_id == self.id member: Optional[Member] = None # return value - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} if me and any(v is not MISSING for v in (nick, bio, avatar, banner)): member = await self._edit_self( @@ -1046,7 +1042,7 @@ async def edit( msg = "Cannot suppress a member which isn't in a vc" raise Exception(msg) # noqa: TRY002 - voice_state_payload: Dict[str, Any] = { + voice_state_payload: dict[str, Any] = { "channel_id": self.voice.channel.id, "suppress": suppress, } diff --git a/disnake/mentions.py b/disnake/mentions.py index c79eaa7ccd..4279b64350 100644 --- a/disnake/mentions.py +++ b/disnake/mentions.py @@ -2,7 +2,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, List, Sequence, Union, cast +from collections.abc import Sequence +from typing import TYPE_CHECKING, Any, Union, cast from .enums import MessageType @@ -75,8 +76,8 @@ def __init__( ) -> None: self.everyone = everyone # TODO(3.0): annotate attributes as `Sequence` instead of copying to list - self.users: Union[bool, List[Snowflake]] - self.roles: Union[bool, List[Snowflake]] + self.users: Union[bool, list[Snowflake]] + self.roles: Union[bool, list[Snowflake]] if users is default or isinstance(users, bool): self.users = cast("bool", users) else: @@ -129,7 +130,7 @@ def from_message(cls, message: Message) -> Self: def to_dict(self) -> AllowedMentionsPayload: # n.b. this runs nearly every time a message is sent - parse: List[AllowedMentionTypePayload] = [] + parse: list[AllowedMentionTypePayload] = [] data: AllowedMentionsPayload = {} # type: ignore if self.everyone: diff --git a/disnake/message.py b/disnake/message.py index 62e5072e22..8802f6dadf 100644 --- a/disnake/message.py +++ b/disnake/message.py @@ -13,11 +13,7 @@ Any, Callable, ClassVar, - Dict, - List, Optional, - Tuple, - Type, Union, cast, overload, @@ -119,9 +115,7 @@ def convert_emoji_reaction(emoji: Union[EmojiInputType, Reaction]) -> str: # No existing emojis start/end with `<>` or `:`, so this should be okay. s = emoji.strip("<>:") - # `str.removeprefix` is py 3.9 only - if s.startswith("a:"): - s = s[2:] + s = s.removeprefix("a:") return s assert_never(emoji) @@ -139,10 +133,10 @@ async def _edit_handler( # all of which can be set to `MISSING` content: Optional[str], embed: Optional[Embed], - embeds: List[Embed], + embeds: list[Embed], file: File, - files: List[File], - attachments: Optional[List[Attachment]], + files: list[File], + attachments: Optional[list[Attachment]], suppress: bool, # deprecated suppress_embeds: bool, flags: MessageFlags, @@ -169,7 +163,7 @@ async def _edit_handler( utils.warn_deprecated(suppress_deprecated_msg, stacklevel=3) suppress_embeds = suppress - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} if content is not MISSING: if content is not None: payload["content"] = str(content) @@ -961,7 +955,7 @@ def __init__(self, data: RoleSubscriptionDataPayload) -> None: self.is_renewal: bool = data["is_renewal"] -def flatten_handlers(cls: Type[Message]) -> Type[Message]: +def flatten_handlers(cls: type[Message]) -> type[Message]: prefix = len("_handle_") handlers = [ (key[prefix:], value) @@ -997,7 +991,7 @@ def __init__(self, *, data: MessageCallPayload) -> None: self.ended_timestamp: Optional[datetime.datetime] = utils.parse_time( data.get("ended_timestamp") ) - self.participant_ids: List[int] = [ + self.participant_ids: list[int] = [ int(participant) for participant in data.get("participants", []) ] @@ -1195,13 +1189,13 @@ class Message(Hashable): ) if TYPE_CHECKING: - _HANDLERS: ClassVar[List[Tuple[str, Callable[..., None]]]] - _CACHED_SLOTS: ClassVar[List[str]] + _HANDLERS: ClassVar[list[tuple[str, Callable[..., None]]]] + _CACHED_SLOTS: ClassVar[list[str]] guild: Optional[Guild] reference: Optional[MessageReference] - mentions: List[Union[User, Member]] + mentions: list[Union[User, Member]] author: Union[User, Member] - role_mentions: List[Role] + role_mentions: list[Role] def __init__( self, @@ -1214,13 +1208,13 @@ def __init__( self.id: int = int(data["id"]) self.application_id: Optional[int] = utils._get_as_snowflake(data, "application_id") self.webhook_id: Optional[int] = utils._get_as_snowflake(data, "webhook_id") - self.reactions: List[Reaction] = [ + self.reactions: list[Reaction] = [ Reaction(message=self, data=d) for d in data.get("reactions", []) ] - self.attachments: List[Attachment] = [ + self.attachments: list[Attachment] = [ Attachment(data=a, state=self._state) for a in data["attachments"] ] - self.embeds: List[Embed] = [Embed.from_dict(a) for a in data["embeds"]] + self.embeds: list[Embed] = [Embed.from_dict(a) for a in data["embeds"]] self.application: Optional[MessageApplicationPayload] = data.get("application") self.activity: Optional[MessageActivityPayload] = data.get("activity") # for user experience, on_message has no business getting partials @@ -1238,10 +1232,10 @@ def __init__( self.tts: bool = data["tts"] self.content: str = data["content"] self.nonce: Optional[Union[int, str]] = data.get("nonce") - self.stickers: List[StickerItem] = [ + self.stickers: list[StickerItem] = [ StickerItem(data=d, state=state) for d in data.get("sticker_items", []) ] - self.components: List[MessageTopLevelComponent] = [ + self.components: list[MessageTopLevelComponent] = [ _message_component_factory(d) for d in data.get("components", []) ] @@ -1296,7 +1290,7 @@ def __init__( ref.resolved = self.__class__(channel=chan, data=resolved, state=state) # type: ignore _ref = data.get("message_reference", {}) - self.message_snapshots: List[ForwardedMessage] = [ + self.message_snapshots: list[ForwardedMessage] = [ ForwardedMessage( state=self._state, channel_id=utils._get_as_snowflake(_ref, "channel_id"), @@ -1428,10 +1422,10 @@ def _handle_type(self, value: int) -> None: def _handle_content(self, value: str) -> None: self.content = value - def _handle_attachments(self, value: List[AttachmentPayload]) -> None: + def _handle_attachments(self, value: list[AttachmentPayload]) -> None: self.attachments = [Attachment(data=a, state=self._state) for a in value] - def _handle_embeds(self, value: List[EmbedPayload]) -> None: + def _handle_embeds(self, value: list[EmbedPayload]) -> None: self.embeds = [Embed.from_dict(data) for data in value] def _handle_nonce(self, value: Union[str, int]) -> None: @@ -1461,7 +1455,7 @@ def _handle_member(self, member: MemberPayload) -> None: self.author = Member._from_message(message=self, data=member) def _handle_mentions( - self, mentions: Union[List[UserPayload], List[UserWithMemberPayload]] + self, mentions: Union[list[UserPayload], list[UserWithMemberPayload]] ) -> None: self.mentions = r = [] guild = self.guild @@ -1478,7 +1472,7 @@ def _handle_mentions( else: r.append(Member._try_upgrade(data=mention, guild=guild, state=state)) - def _handle_mention_roles(self, role_mentions: List[int]) -> None: + def _handle_mention_roles(self, role_mentions: list[int]) -> None: self.role_mentions = [] if isinstance(self.guild, Guild): for role_id in map(int, role_mentions): @@ -1486,7 +1480,7 @@ def _handle_mention_roles(self, role_mentions: List[int]) -> None: if role is not None: self.role_mentions.append(role) - def _handle_components(self, components: List[MessageTopLevelComponentPayload]) -> None: + def _handle_components(self, components: list[MessageTopLevelComponentPayload]) -> None: self.components = [_message_component_factory(d) for d in components] def _rebind_cached_references(self, new_guild: Guild, new_channel: GuildMessageable) -> None: @@ -1501,7 +1495,7 @@ def _rebind_cached_references(self, new_guild: Guild, new_channel: GuildMessagea self._interaction.user.guild = new_guild @utils.cached_slot_property("_cs_raw_mentions") - def raw_mentions(self) -> List[int]: + def raw_mentions(self) -> list[int]: """:class:`list`\\[:class:`int`]: A property that returns an array of user IDs matched with the syntax of ``<@user_id>`` in the message content. @@ -1511,21 +1505,21 @@ def raw_mentions(self) -> List[int]: return [int(x) for x in re.findall(r"<@!?([0-9]{17,19})>", self.content)] @utils.cached_slot_property("_cs_raw_channel_mentions") - def raw_channel_mentions(self) -> List[int]: + def raw_channel_mentions(self) -> list[int]: """:class:`list`\\[:class:`int`]: A property that returns an array of channel IDs matched with the syntax of ``<#channel_id>`` in the message content. """ return [int(x) for x in re.findall(r"<#([0-9]{17,19})>", self.content)] @utils.cached_slot_property("_cs_raw_role_mentions") - def raw_role_mentions(self) -> List[int]: + def raw_role_mentions(self) -> list[int]: """:class:`list`\\[:class:`int`]: A property that returns an array of role IDs matched with the syntax of ``<@&role_id>`` in the message content. """ return [int(x) for x in re.findall(r"<@&([0-9]{17,19})>", self.content)] @utils.cached_slot_property("_cs_channel_mentions") - def channel_mentions(self) -> List[GuildChannel]: + def channel_mentions(self) -> list[GuildChannel]: """:class:`list`\\[:class:`abc.GuildChannel`]: A list of :class:`abc.GuildChannel` that were mentioned. If the message is in a private message then the list is always empty. """ @@ -1836,7 +1830,7 @@ def system_content(self) -> Optional[str]: return poll_result_embed = self.embeds[0] - poll_embed_fields: Dict[str, str] = {} + poll_embed_fields: dict[str, str] = {} if not poll_result_embed._fields: return @@ -1925,7 +1919,7 @@ async def edit( *, embed: Optional[Embed] = ..., file: File = ..., - attachments: Optional[List[Attachment]] = ..., + attachments: Optional[list[Attachment]] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., allowed_mentions: Optional[AllowedMentions] = ..., @@ -1940,8 +1934,8 @@ async def edit( content: Optional[str] = ..., *, embed: Optional[Embed] = ..., - files: List[File] = ..., - attachments: Optional[List[Attachment]] = ..., + files: list[File] = ..., + attachments: Optional[list[Attachment]] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., allowed_mentions: Optional[AllowedMentions] = ..., @@ -1955,9 +1949,9 @@ async def edit( self, content: Optional[str] = ..., *, - embeds: List[Embed] = ..., + embeds: list[Embed] = ..., file: File = ..., - attachments: Optional[List[Attachment]] = ..., + attachments: Optional[list[Attachment]] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., allowed_mentions: Optional[AllowedMentions] = ..., @@ -1971,9 +1965,9 @@ async def edit( self, content: Optional[str] = ..., *, - embeds: List[Embed] = ..., - files: List[File] = ..., - attachments: Optional[List[Attachment]] = ..., + embeds: list[Embed] = ..., + files: list[File] = ..., + attachments: Optional[list[Attachment]] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., allowed_mentions: Optional[AllowedMentions] = ..., @@ -1987,10 +1981,10 @@ async def edit( content: Optional[str] = MISSING, *, embed: Optional[Embed] = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, file: File = MISSING, - files: List[File] = MISSING, - attachments: Optional[List[Attachment]] = MISSING, + files: list[File] = MISSING, + attachments: Optional[list[Attachment]] = MISSING, suppress: bool = MISSING, # deprecated suppress_embeds: bool = MISSING, flags: MessageFlags = MISSING, @@ -2699,7 +2693,7 @@ async def edit( *, embed: Optional[Embed] = ..., file: File = ..., - attachments: Optional[List[Attachment]] = ..., + attachments: Optional[list[Attachment]] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., allowed_mentions: Optional[AllowedMentions] = ..., @@ -2714,8 +2708,8 @@ async def edit( content: Optional[str] = ..., *, embed: Optional[Embed] = ..., - files: List[File] = ..., - attachments: Optional[List[Attachment]] = ..., + files: list[File] = ..., + attachments: Optional[list[Attachment]] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., allowed_mentions: Optional[AllowedMentions] = ..., @@ -2729,9 +2723,9 @@ async def edit( self, content: Optional[str] = ..., *, - embeds: List[Embed] = ..., + embeds: list[Embed] = ..., file: File = ..., - attachments: Optional[List[Attachment]] = ..., + attachments: Optional[list[Attachment]] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., allowed_mentions: Optional[AllowedMentions] = ..., @@ -2745,9 +2739,9 @@ async def edit( self, content: Optional[str] = ..., *, - embeds: List[Embed] = ..., - files: List[File] = ..., - attachments: Optional[List[Attachment]] = ..., + embeds: list[Embed] = ..., + files: list[File] = ..., + attachments: Optional[list[Attachment]] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., allowed_mentions: Optional[AllowedMentions] = ..., @@ -2761,10 +2755,10 @@ async def edit( content: Optional[str] = MISSING, *, embed: Optional[Embed] = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, file: File = MISSING, - files: List[File] = MISSING, - attachments: Optional[List[Attachment]] = MISSING, + files: list[File] = MISSING, + attachments: Optional[list[Attachment]] = MISSING, suppress: bool = MISSING, # deprecated suppress_embeds: bool = MISSING, flags: MessageFlags = MISSING, @@ -2999,10 +2993,10 @@ def __init__( self._state = state self.type: MessageType = try_enum(MessageType, data["type"]) self.content: str = data["content"] - self.embeds: List[Embed] = [Embed.from_dict(a) for a in data["embeds"]] + self.embeds: list[Embed] = [Embed.from_dict(a) for a in data["embeds"]] # should never be None in message_reference(s) that are forwarding self.channel_id: int = channel_id # type: ignore - self.attachments: List[Attachment] = [ + self.attachments: list[Attachment] = [ Attachment(data=a, state=state) for a in data["attachments"] ] self._timestamp: datetime.datetime = utils.parse_time(data["timestamp"]) @@ -3010,15 +3004,15 @@ def __init__( data["edited_timestamp"] ) self.flags: MessageFlags = MessageFlags._from_value(data.get("flags", 0)) - self.stickers: List[StickerItem] = [ + self.stickers: list[StickerItem] = [ StickerItem(data=d, state=state) for d in data.get("sticker_items", []) ] - self.components: List[MessageTopLevelComponent] = [ + self.components: list[MessageTopLevelComponent] = [ _message_component_factory(d) for d in data.get("components", []) ] self.guild_id = guild_id - self.mentions: List[Union[User, Member]] = [] + self.mentions: list[Union[User, Member]] = [] if self.guild is None: self.mentions = [state.store_user(m) for m in data["mentions"]] else: @@ -3032,7 +3026,7 @@ def __init__( Member._try_upgrade(data=mention, guild=self.guild, state=state) ) - self.role_mentions: List[Role] = [] + self.role_mentions: list[Role] = [] if self.guild is not None: for role_id in map(int, data.get("mention_roles", [])): role = self.guild.get_role(role_id) diff --git a/disnake/oggparse.py b/disnake/oggparse.py index 2c7dc7ce1a..2b3918d1ad 100644 --- a/disnake/oggparse.py +++ b/disnake/oggparse.py @@ -3,7 +3,8 @@ from __future__ import annotations import struct -from typing import IO, TYPE_CHECKING, ClassVar, Generator, Optional, Tuple +from collections.abc import Generator +from typing import IO, TYPE_CHECKING, ClassVar, Optional from .errors import DiscordException @@ -54,7 +55,7 @@ def __init__(self, stream: IO[bytes]) -> None: msg = "bad data stream" raise OggError(msg) from None - def iter_packets(self) -> Generator[Tuple[bytes, bool], None, None]: + def iter_packets(self) -> Generator[tuple[bytes, bool], None, None]: packetlen = offset = 0 partial = True diff --git a/disnake/onboarding.py b/disnake/onboarding.py index cca83845d3..7988061752 100644 --- a/disnake/onboarding.py +++ b/disnake/onboarding.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT from __future__ import annotations -from typing import TYPE_CHECKING, FrozenSet, List, Optional, Union +from typing import TYPE_CHECKING, Optional, Union from .enums import OnboardingPromptType, try_enum from .mixins import Hashable @@ -52,11 +52,11 @@ def __init__(self, *, guild: Guild, data: OnboardingPayload) -> None: self._from_data(data) def _from_data(self, data: OnboardingPayload) -> None: - self.prompts: List[OnboardingPrompt] = [ + self.prompts: list[OnboardingPrompt] = [ OnboardingPrompt(data=prompt, guild=self.guild) for prompt in data["prompts"] ] self.enabled: bool = data["enabled"] - self.default_channel_ids: FrozenSet[int] = ( + self.default_channel_ids: frozenset[int] = ( frozenset(map(int, exempt_channels)) if (exempt_channels := data["default_channel_ids"]) else frozenset() @@ -68,7 +68,7 @@ def __repr__(self) -> str: ) @property - def default_channels(self) -> List[GuildChannel]: + def default_channels(self) -> list[GuildChannel]: """:class:`list`\\[:class:`abc.GuildChannel`]: The list of channels that will be shown to new members by default.""" return list(filter(None, map(self.guild.get_channel, self.default_channel_ids))) @@ -113,7 +113,7 @@ def __init__(self, *, guild: Guild, data: OnboardingPromptPayload) -> None: self.id: int = int(data["id"]) self.title: str = data["title"] - self.options: List[OnboardingPromptOption] = [ + self.options: list[OnboardingPromptOption] = [ OnboardingPromptOption(data=option, guild=guild) for option in data["options"] ] self.single_select: bool = data["single_select"] @@ -161,10 +161,10 @@ def __init__(self, *, guild: Guild, data: OnboardingPromptOptionPayload) -> None self.id: int = int(data["id"]) self.title: str = data["title"] self.description: Optional[str] = data["description"] - self.role_ids: FrozenSet[int] = ( + self.role_ids: frozenset[int] = ( frozenset(map(int, roles_ids)) if (roles_ids := data.get("role_ids")) else frozenset() ) - self.channel_ids: FrozenSet[int] = ( + self.channel_ids: frozenset[int] = ( frozenset(map(int, channels_ids)) if (channels_ids := data.get("channel_ids")) else frozenset() @@ -186,11 +186,11 @@ def __repr__(self) -> str: ) @property - def roles(self) -> List[Role]: + def roles(self) -> list[Role]: """:class:`list`\\[:class:`Role`]: A list of roles that will be added to the user when they select this option.""" return list(filter(None, map(self.guild.get_role, self.role_ids))) @property - def channels(self) -> List[GuildChannel]: + def channels(self) -> list[GuildChannel]: """:class:`list`\\[:class:`abc.GuildChannel`]: A list of channels that the user will see when they select this option.""" return list(filter(None, map(self.guild.get_channel, self.channel_ids))) diff --git a/disnake/opus.py b/disnake/opus.py index 142cfe48ef..88fc305580 100644 --- a/disnake/opus.py +++ b/disnake/opus.py @@ -14,11 +14,8 @@ TYPE_CHECKING, Any, Callable, - List, Literal, Optional, - Tuple, - Type, TypedDict, TypeVar, overload, @@ -108,14 +105,14 @@ class DecoderStruct(ctypes.Structure): } -def _err_lt(result: int, func: Callable[..., Any], args: List[Any]) -> int: +def _err_lt(result: int, func: Callable[..., Any], args: list[Any]) -> int: if result < OK: _log.info("error has happened in %s", func.__name__) raise OpusError(result) return result -def _err_ne(result: T, func: Callable[..., Any], args: List[Any]) -> T: +def _err_ne(result: T, func: Callable[..., Any], args: list[Any]) -> T: ret = args[-1]._obj if ret.value != OK: _log.info("error has happened in %s", func.__name__) @@ -128,8 +125,8 @@ def _err_ne(result: T, func: Callable[..., Any], args: List[Any]) -> T: # The second one are the types of arguments it takes. # The third is the result type. # The fourth is the error handler. -exported_functions: List[ - Tuple[str, Optional[List[Type[ctypes._CData]]], Optional[Type[ctypes._CData]], Any] +exported_functions: list[ + tuple[str, Optional[list[type[ctypes._CData]]], Optional[type[ctypes._CData]], Any] ] = [ # Generic ("opus_get_version_string", [], ctypes.c_char_p, None), diff --git a/disnake/partial_emoji.py b/disnake/partial_emoji.py index 9693f39c4d..0452e21aa9 100644 --- a/disnake/partial_emoji.py +++ b/disnake/partial_emoji.py @@ -3,7 +3,7 @@ from __future__ import annotations import re -from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Union +from typing import TYPE_CHECKING, Any, Optional, Union from . import utils from .asset import Asset, AssetMixin @@ -85,7 +85,7 @@ def __init__(self, *, name: str, animated: bool = False, id: Optional[int] = Non @classmethod def from_dict( - cls, data: Union[PartialEmojiPayload, ActivityEmojiPayload, Dict[str, Any]] + cls, data: Union[PartialEmojiPayload, ActivityEmojiPayload, dict[str, Any]] ) -> Self: return cls( animated=data.get("animated", False), @@ -256,7 +256,7 @@ async def read(self) -> bytes: @staticmethod def _emoji_to_name_id( emoji: Optional[Union[str, Emoji, PartialEmoji]], - ) -> Tuple[Optional[str], Optional[int]]: + ) -> tuple[Optional[str], Optional[int]]: if emoji is None: return None, None diff --git a/disnake/permissions.py b/disnake/permissions.py index bcc2368f7c..07f9181f92 100644 --- a/disnake/permissions.py +++ b/disnake/permissions.py @@ -2,17 +2,14 @@ from __future__ import annotations +from collections.abc import Iterator from functools import wraps from typing import ( TYPE_CHECKING, Any, Callable, ClassVar, - Dict, - Iterator, Optional, - Set, - Tuple, overload, ) @@ -1216,8 +1213,8 @@ class PermissionOverwrite: view_guild_insights: Optional[bool] if TYPE_CHECKING: - VALID_NAMES: ClassVar[Set[str]] - PURE_FLAGS: ClassVar[Set[str]] + VALID_NAMES: ClassVar[set[str]] + PURE_FLAGS: ClassVar[set[str]] @overload @_generated @@ -1293,7 +1290,7 @@ def __init__( @_overload_with_permissions def __init__(self, **kwargs: Optional[bool]) -> None: - self._values: Dict[str, Optional[bool]] = {} + self._values: dict[str, Optional[bool]] = {} for key, value in kwargs.items(): if key not in self.VALID_NAMES: @@ -1315,7 +1312,7 @@ def _set(self, key: str, value: Optional[bool]) -> None: else: self._values[key] = value - def pair(self) -> Tuple[Permissions, Permissions]: + def pair(self) -> tuple[Permissions, Permissions]: """:class:`tuple`\\[:class:`Permissions`, :class:`Permissions`]: Returns the (allow, deny) pair from this overwrite.""" allow = Permissions.none() deny = Permissions.none() @@ -1446,6 +1443,6 @@ def update(self, **kwargs: Optional[bool]) -> None: setattr(self, key, value) - def __iter__(self) -> Iterator[Tuple[str, Optional[bool]]]: + def __iter__(self) -> Iterator[tuple[str, Optional[bool]]]: for key in self.PURE_FLAGS: yield key, self._values.get(key) diff --git a/disnake/player.py b/disnake/player.py index 1b7ec78b88..aca6cc5895 100644 --- a/disnake/player.py +++ b/disnake/player.py @@ -13,7 +13,7 @@ import time import traceback import warnings -from typing import IO, TYPE_CHECKING, Any, Callable, Generic, Optional, Tuple, TypeVar, Union +from typing import IO, TYPE_CHECKING, Any, Callable, Generic, Optional, TypeVar, Union from . import utils from .errors import ClientException @@ -446,7 +446,7 @@ async def from_probe( source: str, *, method: Optional[ - Union[str, Callable[[str, str], Tuple[Optional[str], Optional[int]]]] + Union[str, Callable[[str, str], tuple[Optional[str], Optional[int]]]] ] = None, **kwargs: Any, ) -> Self: @@ -513,10 +513,10 @@ async def probe( source: str, *, method: Optional[ - Union[str, Callable[[str, str], Tuple[Optional[str], Optional[int]]]] + Union[str, Callable[[str, str], tuple[Optional[str], Optional[int]]]] ] = None, executable: Optional[str] = None, - ) -> Tuple[Optional[str], Optional[int]]: + ) -> tuple[Optional[str], Optional[int]]: """|coro| Probes the input source for bitrate and codec information. @@ -589,7 +589,7 @@ async def probe( @staticmethod def _probe_codec_native( source, executable: str = "ffmpeg" - ) -> Tuple[Optional[str], Optional[int]]: + ) -> tuple[Optional[str], Optional[int]]: exe = executable[:2] + "probe" if executable in ("ffmpeg", "avconv") else executable args = [ exe, @@ -618,7 +618,7 @@ def _probe_codec_native( @staticmethod def _probe_codec_fallback( source, executable: str = "ffmpeg" - ) -> Tuple[Optional[str], Optional[int]]: + ) -> tuple[Optional[str], Optional[int]]: args = [executable, "-hide_banner", "-i", source] proc = subprocess.Popen( args, creationflags=CREATE_NO_WINDOW, stdout=subprocess.PIPE, stderr=subprocess.STDOUT diff --git a/disnake/poll.py b/disnake/poll.py index bea0109987..c4166e6b21 100644 --- a/disnake/poll.py +++ b/disnake/poll.py @@ -3,7 +3,7 @@ from __future__ import annotations from datetime import timedelta -from typing import TYPE_CHECKING, Dict, List, Optional, Union +from typing import TYPE_CHECKING, Optional, Union from . import utils from .abc import Snowflake @@ -242,7 +242,7 @@ def __init__( self, question: Union[str, PollMedia], *, - answers: List[Union[str, PollAnswer]], + answers: list[Union[str, PollAnswer]], duration: timedelta = timedelta(hours=24), allow_multiselect: bool = False, layout_type: PollLayoutType = PollLayoutType.default, @@ -257,7 +257,7 @@ def __init__( msg = f"Expected 'str' or 'PollMedia' for 'question', got {question.__class__.__name__!r}." raise TypeError(msg) - self._answers: Dict[int, PollAnswer] = {} + self._answers: dict[int, PollAnswer] = {} for i, answer in enumerate(answers, 1): if isinstance(answer, PollAnswer): self._answers[i] = answer @@ -276,7 +276,7 @@ def __repr__(self) -> str: return f"<{self.__class__.__name__} question={self.question!r} answers={self.answers!r}>" @property - def answers(self) -> List[PollAnswer]: + def answers(self) -> list[PollAnswer]: """:class:`list`\\[:class:`PollAnswer`]: The list of answers for this poll. See also :meth:`get_answer` to get specific answers by ID. diff --git a/disnake/raw_models.py b/disnake/raw_models.py index 4d276c6714..8a12feb40c 100644 --- a/disnake/raw_models.py +++ b/disnake/raw_models.py @@ -3,7 +3,7 @@ from __future__ import annotations import datetime -from typing import TYPE_CHECKING, List, Literal, Optional, Set, Union, cast +from typing import TYPE_CHECKING, Literal, Optional, Union, cast from .enums import ChannelType, try_enum from .utils import _get_as_snowflake, get_slots @@ -104,9 +104,9 @@ class RawBulkMessageDeleteEvent(_RawReprMixin): __slots__ = ("message_ids", "channel_id", "guild_id", "cached_messages") def __init__(self, data: MessageDeleteBulkEvent) -> None: - self.message_ids: Set[int] = {int(x) for x in data.get("ids", [])} + self.message_ids: set[int] = {int(x) for x in data.get("ids", [])} self.channel_id: int = int(data["channel_id"]) - self.cached_messages: List[Message] = [] + self.cached_messages: list[Message] = [] self.guild_id: Optional[int] = _get_as_snowflake(data, "guild_id") diff --git a/disnake/role.py b/disnake/role.py index 15ad2ad61d..2b51921f95 100644 --- a/disnake/role.py +++ b/disnake/role.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union +from typing import TYPE_CHECKING, Any, Optional, Union from .asset import Asset from .colour import Colour @@ -485,7 +485,7 @@ def mention(self) -> str: return f"<@&{self.id}>" @property - def members(self) -> List[Member]: + def members(self) -> list[Member]: """:class:`list`\\[:class:`Member`]: Returns all the members with this role.""" all_members = self.guild.members if self.is_default(): @@ -518,7 +518,7 @@ async def _move(self, position: int, reason: Optional[str]) -> None: else: roles.append(self.id) - payload: List[RolePositionUpdate] = [ + payload: list[RolePositionUpdate] = [ {"id": z[0], "position": z[1]} for z in zip(roles, change_range) ] await http.move_role_position(self.guild.id, payload, reason=reason) @@ -628,9 +628,9 @@ async def edit( if position is not MISSING: await self._move(position, reason=reason) - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} - colors: Dict[str, Any] = { + colors: dict[str, Any] = { "primary_color": self._primary_color, "secondary_color": self._secondary_color, "tertiary_color": self._tertiary_color, diff --git a/disnake/shard.py b/disnake/shard.py index c85ad2312f..3846ddc32d 100644 --- a/disnake/shard.py +++ b/disnake/shard.py @@ -9,13 +9,9 @@ TYPE_CHECKING, Any, Callable, - Dict, - List, Literal, NoReturn, Optional, - Tuple, - Type, Union, overload, ) @@ -99,7 +95,7 @@ def __init__( self._reconnect = client._reconnect self._backoff: ExponentialBackoff[Literal[False]] = ExponentialBackoff() self._task: Optional[asyncio.Task] = None - self._handled_exceptions: Tuple[Type[Exception], ...] = ( + self._handled_exceptions: tuple[type[Exception], ...] = ( OSError, HTTPException, GatewayNotFound, @@ -349,7 +345,7 @@ def __init__( *, asyncio_debug: bool = False, loop: Optional[asyncio.AbstractEventLoop] = None, - shard_ids: Optional[List[int]] = None, # instead of Client's shard_id: Optional[int] + shard_ids: Optional[list[int]] = None, # instead of Client's shard_id: Optional[int] shard_count: Optional[int] = None, enable_debug_events: bool = False, enable_gateway_error_handler: bool = True, @@ -375,7 +371,7 @@ def __init__( @overload def __init__(self: NoReturn) -> None: ... - def __init__(self, *args: Any, shard_ids: Optional[List[int]] = None, **kwargs: Any) -> None: + def __init__(self, *args: Any, shard_ids: Optional[list[int]] = None, **kwargs: Any) -> None: self.shard_ids = shard_ids super().__init__(*args, **kwargs) @@ -425,7 +421,7 @@ def latency(self) -> float: return sum(latency for _, latency in self.latencies) / len(self.__shards) @property - def latencies(self) -> List[Tuple[int, float]]: + def latencies(self) -> list[tuple[int, float]]: """:class:`list`\\[:class:`tuple`\\[:class:`int`, :class:`float`]]: A list of latencies between a HEARTBEAT and a HEARTBEAT_ACK in seconds. This returns a list of tuples with elements ``(shard_id, latency)``. @@ -445,7 +441,7 @@ def get_shard(self, shard_id: int) -> Optional[ShardInfo]: return ShardInfo(parent, self.shard_count) @property - def shards(self) -> Dict[int, ShardInfo]: + def shards(self) -> dict[int, ShardInfo]: """:class:`~collections.abc.Mapping`\\[:class:`int`, :class:`ShardInfo`]: Returns a mapping of shard IDs to their respective info object.""" return { shard_id: ShardInfo(parent, self.shard_count) diff --git a/disnake/soundboard.py b/disnake/soundboard.py index 70fa659835..016aac86a4 100644 --- a/disnake/soundboard.py +++ b/disnake/soundboard.py @@ -3,7 +3,7 @@ from __future__ import annotations import datetime -from typing import TYPE_CHECKING, Any, Dict, Optional, Union +from typing import TYPE_CHECKING, Any, Optional, Union from .asset import Asset, AssetMixin from .mixins import Hashable @@ -272,7 +272,7 @@ async def edit( :class:`GuildSoundboardSound` The newly modified soundboard sound. """ - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} if name is not MISSING: payload["name"] = name diff --git a/disnake/state.py b/disnake/state.py index 9922963a40..c00fd0d18e 100644 --- a/disnake/state.py +++ b/disnake/state.py @@ -11,19 +11,14 @@ import os import weakref from collections import OrderedDict, deque +from collections.abc import Coroutine, Sequence from typing import ( TYPE_CHECKING, Any, Callable, - Coroutine, - Deque, - Dict, Generic, - List, Literal, Optional, - Sequence, - Tuple, TypeVar, Union, overload, @@ -128,7 +123,7 @@ class AsyncRequest(Generic[T]): def __init__(self, guild_id: int, loop: asyncio.AbstractEventLoop) -> None: self.guild_id: int = guild_id self.loop: asyncio.AbstractEventLoop = loop - self.waiters: List[asyncio.Future[T]] = [] + self.waiters: list[asyncio.Future[T]] = [] async def wait(self) -> T: future: asyncio.Future[T] = self.loop.create_future() @@ -149,7 +144,7 @@ def set_result(self, result: T) -> None: future.set_result(result) -class ChunkRequest(AsyncRequest[List[Member]]): +class ChunkRequest(AsyncRequest[list[Member]]): def __init__( self, guild_id: int, @@ -162,9 +157,9 @@ def __init__( self.resolver: Callable[[int], Any] = resolver self.cache: bool = cache self.nonce: str = os.urandom(16).hex() - self.buffer: List[Member] = [] + self.buffer: list[Member] = [] - def add_members(self, members: List[Member]) -> None: + def add_members(self, members: list[Member]) -> None: self.buffer.extend(members) if self.cache: guild = self.resolver(self.guild_id) @@ -194,14 +189,14 @@ class ConnectionState: if TYPE_CHECKING: _get_websocket: Callable[..., DiscordWebSocket] _get_client: Callable[..., Client] - _parsers: Dict[str, Callable[[Dict[str, Any]], None]] + _parsers: dict[str, Callable[[dict[str, Any]], None]] def __init__( self, *, dispatch: Callable[Concatenate[str, ...], Any], - handlers: Dict[str, Callable[..., Any]], - hooks: Dict[str, Callable[..., Any]], + handlers: dict[str, Callable[..., Any]], + hooks: dict[str, Callable[..., Any]], http: HTTPClient, loop: asyncio.AbstractEventLoop, max_messages: Optional[int] = 1000, @@ -222,8 +217,8 @@ def __init__( self.max_messages = 1000 self.dispatch: Callable[Concatenate[str, ...], Any] = dispatch - self.handlers: Dict[str, Callable[..., Any]] = handlers - self.hooks: Dict[str, Callable[..., Any]] = hooks + self.handlers: dict[str, Callable[..., Any]] = handlers + self.hooks: dict[str, Callable[..., Any]] = hooks self.shard_count: Optional[int] = None self._ready_task: Optional[asyncio.Task] = None self.application_id: Optional[int] = None if application_id is None else int(application_id) @@ -238,7 +233,7 @@ def __init__( raise TypeError(msg) self.allowed_mentions: Optional[AllowedMentions] = allowed_mentions - self._chunk_requests: Dict[Union[int, str], ChunkRequest] = {} + self._chunk_requests: dict[Union[int, str], ChunkRequest] = {} if activity: if not isinstance(activity, BaseActivity): @@ -309,14 +304,14 @@ def clear( # - the weakref slot + object in user objects likely results in a small increase in memory usage # - accesses on `_users` are slower, e.g. `__getitem__` takes ~1us with weakrefs and ~0.2us without self._users: weakref.WeakValueDictionary[int, User] = weakref.WeakValueDictionary() - self._emojis: Dict[int, Emoji] = {} - self._stickers: Dict[int, GuildSticker] = {} - self._soundboard_sounds: Dict[int, GuildSoundboardSound] = {} - self._guilds: Dict[int, Guild] = {} + self._emojis: dict[int, Emoji] = {} + self._stickers: dict[int, GuildSticker] = {} + self._soundboard_sounds: dict[int, GuildSoundboardSound] = {} + self._guilds: dict[int, Guild] = {} if application_commands: - self._global_application_commands: Dict[int, APIApplicationCommand] = {} - self._guild_application_commands: Dict[int, Dict[int, APIApplicationCommand]] = {} + self._global_application_commands: dict[int, APIApplicationCommand] = {} + self._guild_application_commands: dict[int, dict[int, APIApplicationCommand]] = {} if views: self._view_store: ViewStore = ViewStore(self) @@ -324,19 +319,19 @@ def clear( if modals: self._modal_store: ModalStore = ModalStore(self) - self._voice_clients: Dict[int, VoiceProtocol] = {} + self._voice_clients: dict[int, VoiceProtocol] = {} # LRU of max size 128 self._private_channels: OrderedDict[int, PrivateChannel] = OrderedDict() # extra dict to look up private channels by user id - self._private_channels_by_user: Dict[int, DMChannel] = {} + self._private_channels_by_user: dict[int, DMChannel] = {} if self.max_messages is not None: - self._messages: Optional[Deque[Message]] = deque(maxlen=self.max_messages) + self._messages: Optional[deque[Message]] = deque(maxlen=self.max_messages) else: - self._messages: Optional[Deque[Message]] = None + self._messages: Optional[deque[Message]] = None def process_chunk_requests( - self, guild_id: int, nonce: Optional[str], members: List[Member], complete: bool + self, guild_id: int, nonce: Optional[str], members: list[Member], complete: bool ) -> None: removed = [] for key, request in self._chunk_requests.items(): @@ -377,7 +372,7 @@ def intents(self) -> Intents: return ret @property - def voice_clients(self) -> List[VoiceProtocol]: + def voice_clients(self) -> list[VoiceProtocol]: return list(self._voice_clients.values()) def _get_voice_client(self, guild_id: Optional[int]) -> Optional[VoiceProtocol]: @@ -445,7 +440,7 @@ def persistent_views(self) -> Sequence[View]: return self._view_store.persistent_views @property - def guilds(self) -> List[Guild]: + def guilds(self) -> list[Guild]: return list(self._guilds.values()) def _get_guild(self, guild_id: Optional[int]) -> Optional[Guild]: @@ -539,15 +534,15 @@ def _get_guild_command_named( return cmd @property - def emojis(self) -> List[Emoji]: + def emojis(self) -> list[Emoji]: return list(self._emojis.values()) @property - def stickers(self) -> List[GuildSticker]: + def stickers(self) -> list[GuildSticker]: return list(self._stickers.values()) @property - def soundboard_sounds(self) -> List[GuildSoundboardSound]: + def soundboard_sounds(self) -> list[GuildSoundboardSound]: return list(self._soundboard_sounds.values()) def get_emoji(self, emoji_id: Optional[int]) -> Optional[Emoji]: @@ -563,7 +558,7 @@ def get_soundboard_sound(self, sound_id: Optional[int]) -> Optional[GuildSoundbo return self._soundboard_sounds.get(sound_id) # type: ignore @property - def private_channels(self) -> List[PrivateChannel]: + def private_channels(self) -> list[PrivateChannel]: return list(self._private_channels.values()) def _get_private_channel(self, channel_id: Optional[int]) -> Optional[PrivateChannel]: @@ -631,7 +626,7 @@ def _guild_needs_chunking(self, guild: Guild) -> bool: def _get_guild_channel( self, data: Union[MessagePayload, gateway.TypingStartEvent], - ) -> Tuple[Union[PartialChannel, Thread], Optional[Guild]]: + ) -> tuple[Union[PartialChannel, Thread], Optional[Guild]]: channel_id = int(data["channel_id"]) guild_id = utils._get_as_snowflake(data, "guild_id") @@ -672,10 +667,10 @@ async def query_members( guild: Guild, query: Optional[str], limit: int, - user_ids: Optional[List[int]], + user_ids: Optional[list[int]], cache: bool, presences: bool, - ) -> List[Member]: + ) -> list[Member]: guild_id = guild.id ws = self._get_websocket(guild_id) @@ -1448,16 +1443,16 @@ def is_guild_evicted(self, guild) -> bool: @overload async def chunk_guild( self, guild: Guild, *, wait: Literal[False], cache: Optional[bool] = None - ) -> asyncio.Future[List[Member]]: ... + ) -> asyncio.Future[list[Member]]: ... @overload async def chunk_guild( self, guild: Guild, *, wait: Literal[True] = True, cache: Optional[bool] = None - ) -> List[Member]: ... + ) -> list[Member]: ... async def chunk_guild( self, guild: Guild, *, wait: bool = True, cache: Optional[bool] = None - ) -> Union[List[Member], asyncio.Future[List[Member]]]: + ) -> Union[list[Member], asyncio.Future[list[Member]]]: cache = cache or self.member_cache_flags.joined request = self._chunk_requests.get(guild.id) if request is None: @@ -1533,7 +1528,7 @@ def parse_guild_delete(self, data: gateway.GuildDeleteEvent) -> None: # do a cleanup of the messages cache if self._messages is not None: - self._messages: Optional[Deque[Message]] = deque( + self._messages: Optional[deque[Message]] = deque( (msg for msg in self._messages if msg.guild != guild), maxlen=self.max_messages ) @@ -2112,7 +2107,7 @@ def parse_guild_soundboard_sounds_update( ) def _handle_soundboard_update( - self, guild: Guild, new_sounds: Tuple[GuildSoundboardSound, ...] + self, guild: Guild, new_sounds: tuple[GuildSoundboardSound, ...] ) -> None: before_sounds = guild.soundboard_sounds guild.soundboard_sounds = new_sounds @@ -2281,7 +2276,7 @@ async def fetch_global_commands( self, *, with_localizations: bool = True, - ) -> List[APIApplicationCommand]: + ) -> list[APIApplicationCommand]: results = await self.http.get_global_commands( self.application_id, # type: ignore with_localizations=with_localizations, @@ -2320,8 +2315,8 @@ async def delete_global_command(self, command_id: int) -> None: self._remove_global_application_command(command_id) async def bulk_overwrite_global_commands( - self, application_commands: List[ApplicationCommand] - ) -> List[APIApplicationCommand]: + self, application_commands: list[ApplicationCommand] + ) -> list[APIApplicationCommand]: payload = [cmd.to_dict() for cmd in application_commands] results = await self.http.bulk_upsert_global_commands(self.application_id, payload) # type: ignore commands = [application_command_factory(data) for data in results] @@ -2335,7 +2330,7 @@ async def fetch_guild_commands( guild_id: int, *, with_localizations: bool = True, - ) -> List[APIApplicationCommand]: + ) -> list[APIApplicationCommand]: results = await self.http.get_guild_commands( self.application_id, # type: ignore guild_id, @@ -2381,8 +2376,8 @@ async def delete_guild_command(self, guild_id: int, command_id: int) -> None: self._remove_guild_application_command(guild_id, command_id) async def bulk_overwrite_guild_commands( - self, guild_id: int, application_commands: List[ApplicationCommand] - ) -> List[APIApplicationCommand]: + self, guild_id: int, application_commands: list[ApplicationCommand] + ) -> list[APIApplicationCommand]: payload = [cmd.to_dict() for cmd in application_commands] results = await self.http.bulk_upsert_guild_commands( self.application_id, # type: ignore @@ -2397,7 +2392,7 @@ async def bulk_overwrite_guild_commands( async def bulk_fetch_command_permissions( self, guild_id: int - ) -> List[GuildApplicationCommandPermissions]: + ) -> list[GuildApplicationCommandPermissions]: array = await self.http.get_guild_application_command_permissions( self.application_id, # type: ignore guild_id, @@ -2418,7 +2413,7 @@ async def fetch_command_permissions( class AutoShardedConnectionState(ConnectionState): def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.shard_ids: Union[List[int], range] = [] + self.shard_ids: Union[list[int], range] = [] self.shards_launched: asyncio.Event = asyncio.Event() def _update_guild_channel_references(self) -> None: @@ -2486,7 +2481,7 @@ async def chunker( async def _delay_ready(self) -> None: await self.shards_launched.wait() - processed: List[Tuple[Guild, asyncio.Future[List[Member]]]] = [] + processed: list[tuple[Guild, asyncio.Future[list[Member]]]] = [] max_concurrency = len(self.shard_ids) * 2 current_bucket = [] while True: @@ -2499,7 +2494,7 @@ async def _delay_ready(self) -> None: except asyncio.TimeoutError: break else: - future: asyncio.Future[List[Member]] + future: asyncio.Future[list[Member]] if self._guild_needs_chunking(guild): _log.debug( "Guild ID %d requires chunking, will be done in the background.", guild.id @@ -2530,8 +2525,8 @@ async def _delay_ready(self) -> None: guilds = sorted(processed, key=lambda g: g[0].shard_id) for shard_id, info in itertools.groupby(guilds, key=lambda g: g[0].shard_id): # this is equivalent to `children, futures = zip(*info)`, but typed properly - children: List[Guild] = [] - futures: List[asyncio.Future[List[Member]]] = [] + children: list[Guild] = [] + futures: list[asyncio.Future[list[Member]]] = [] for c, f in info: children.append(c) futures.append(f) diff --git a/disnake/sticker.py b/disnake/sticker.py index 6eb914ae8c..ef5e9d599f 100644 --- a/disnake/sticker.py +++ b/disnake/sticker.py @@ -3,7 +3,7 @@ from __future__ import annotations import unicodedata -from typing import TYPE_CHECKING, List, Literal, Optional, Tuple, Type, Union +from typing import TYPE_CHECKING, Literal, Optional, Union from .asset import Asset, AssetMixin from .enums import StickerFormatType, StickerType, try_enum @@ -95,7 +95,7 @@ def __init__(self, *, state: ConnectionState, data: StickerPackPayload) -> None: def _from_data(self, data: StickerPackPayload) -> None: self.id: int = int(data["id"]) stickers = data["stickers"] - self.stickers: List[StandardSticker] = [ + self.stickers: list[StandardSticker] = [ StandardSticker(state=self._state, data=sticker) for sticker in stickers ] self.name: str = data["name"] @@ -327,7 +327,7 @@ def _from_data(self, data: StandardStickerPayload) -> None: self.type: StickerType = StickerType.standard try: - self.tags: List[str] = [tag.strip() for tag in data["tags"].split(",")] + self.tags: list[str] = [tag.strip() for tag in data["tags"].split(",")] except KeyError: self.tags = [] @@ -511,7 +511,7 @@ async def delete(self, *, reason: Optional[str] = None) -> None: def _sticker_factory( sticker_type: Literal[1, 2], -) -> Tuple[Type[Union[StandardSticker, GuildSticker, Sticker]], StickerType]: +) -> tuple[type[Union[StandardSticker, GuildSticker, Sticker]], StickerType]: value = try_enum(StickerType, sticker_type) if value == StickerType.standard: return StandardSticker, value diff --git a/disnake/subscription.py b/disnake/subscription.py index 8bee0ebf76..fe64616c65 100644 --- a/disnake/subscription.py +++ b/disnake/subscription.py @@ -3,7 +3,7 @@ from __future__ import annotations import datetime -from typing import TYPE_CHECKING, List, Optional +from typing import TYPE_CHECKING, Optional from .enums import SubscriptionStatus, try_enum from .mixins import Hashable @@ -89,9 +89,9 @@ def __init__(self, *, data: SubscriptionPayload, state: ConnectionState) -> None self.id: int = int(data["id"]) self.user_id: int = int(data["user_id"]) - self.sku_ids: List[int] = list(map(int, data["sku_ids"])) - self.entitlement_ids: List[int] = list(map(int, data["entitlement_ids"])) - self.renewal_sku_ids: Optional[List[int]] = ( + self.sku_ids: list[int] = list(map(int, data["sku_ids"])) + self.entitlement_ids: list[int] = list(map(int, data["entitlement_ids"])) + self.renewal_sku_ids: Optional[list[int]] = ( list(map(int, renewal_sku_ids)) if (renewal_sku_ids := data.get("renewal_sku_ids")) is not None else None diff --git a/disnake/team.py b/disnake/team.py index 9541358c12..529c34f987 100644 --- a/disnake/team.py +++ b/disnake/team.py @@ -3,7 +3,7 @@ from __future__ import annotations import datetime -from typing import TYPE_CHECKING, List, Optional +from typing import TYPE_CHECKING, Optional from . import utils from .asset import Asset @@ -47,7 +47,7 @@ def __init__(self, state: ConnectionState, data: TeamPayload) -> None: self.name: str = data["name"] self._icon: Optional[str] = data.get("icon") self.owner_id: Optional[int] = utils._get_as_snowflake(data, "owner_user_id") - self.members: List[TeamMember] = [ + self.members: list[TeamMember] = [ TeamMember(self, self._state, member) for member in data["members"] ] diff --git a/disnake/template.py b/disnake/template.py index 921c4c8d96..744c090d6a 100644 --- a/disnake/template.py +++ b/disnake/template.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, List, NoReturn, Optional +from typing import TYPE_CHECKING, Any, NoReturn, Optional from .guild import Guild, Member from .utils import MISSING, _assetbytes_to_base64_data, parse_time @@ -61,7 +61,7 @@ def _get_message(self, id: int) -> None: def _get_guild(self, id) -> Optional[Guild]: return self.__state._get_guild(id) - async def query_members(self, **kwargs: Any) -> List[Member]: + async def query_members(self, **kwargs: Any) -> list[Member]: return [] def __getattr__(self, attr) -> NoReturn: diff --git a/disnake/threads.py b/disnake/threads.py index 0ff06073a8..3f4ff630ab 100644 --- a/disnake/threads.py +++ b/disnake/threads.py @@ -4,7 +4,8 @@ import asyncio import time -from typing import TYPE_CHECKING, Callable, Dict, Iterable, List, Literal, Optional, Sequence, Union +from collections.abc import Iterable, Sequence +from typing import TYPE_CHECKING, Callable, Literal, Optional, Union from .abc import GuildChannel, Messageable from .enums import ChannelType, ThreadArchiveDuration, try_enum, try_enum_to_int @@ -167,7 +168,7 @@ class Thread(Messageable, Hashable): def __init__(self, *, guild: Guild, state: ConnectionState, data: ThreadPayload) -> None: self._state: ConnectionState = state self.guild: Guild = guild - self._members: Dict[int, ThreadMember] = {} + self._members: dict[int, ThreadMember] = {} self._from_data(data) async def _get_channel(self) -> Self: @@ -198,7 +199,7 @@ def _from_data(self, data: ThreadPayload) -> None: data.get("last_pin_timestamp") ) self._flags: int = data.get("flags", 0) - self._applied_tags: List[int] = list(map(int, data.get("applied_tags", []))) + self._applied_tags: list[int] = list(map(int, data.get("applied_tags", []))) self._unroll_metadata(data["thread_metadata"]) if "member" in data: @@ -260,7 +261,7 @@ def mention(self) -> str: return f"<#{self.id}>" @property - def members(self) -> List[ThreadMember]: + def members(self) -> list[ThreadMember]: """:class:`list`\\[:class:`ThreadMember`]: A list of thread members in this thread. This requires :attr:`Intents.members` to be properly filled. Most of the time however, @@ -400,7 +401,7 @@ def is_pinned(self) -> bool: return self.flags.pinned @property - def applied_tags(self) -> List[ForumTag]: + def applied_tags(self) -> list[ForumTag]: """:class:`list`\\[:class:`ForumTag`]: The tags currently applied to this thread. Only applicable to threads in channels of type :class:`ForumChannel` or :class:`MediaChannel`. @@ -560,7 +561,7 @@ async def purge( around: Optional[SnowflakeTime] = None, oldest_first: Optional[bool] = False, bulk: bool = True, - ) -> List[Message]: + ) -> list[Message]: """|coro| Purges a list of messages that meet the criteria given by the predicate @@ -621,7 +622,7 @@ def is_me(m): iterator = self.history( limit=limit, before=before, after=after, oldest_first=oldest_first, around=around ) - ret: List[Message] = [] + ret: list[Message] = [] count = 0 minimum_time = int((time.time() - 14 * 24 * 60 * 60) * 1000.0 - 1420070400000) << 22 @@ -881,7 +882,7 @@ async def fetch_member(self, member_id: int, /) -> ThreadMember: member_data = await self._state.http.get_thread_member(self.id, member_id) return ThreadMember(parent=self, data=member_data) - async def fetch_members(self) -> List[ThreadMember]: + async def fetch_members(self) -> list[ThreadMember]: """|coro| Retrieves all :class:`ThreadMember` that are in this thread. @@ -958,7 +959,7 @@ async def add_tags(self, *tags: Snowflake, reason: Optional[str] = None) -> None if not tags: return - new_tags: List[int] = self._applied_tags.copy() + new_tags: list[int] = self._applied_tags.copy() new_tags.extend(t.id for t in tags) new_tags = _unique(new_tags) @@ -996,7 +997,7 @@ async def remove_tags(self, *tags: Snowflake, reason: Optional[str] = None) -> N return to_remove = {t.id for t in tags} - new_tags: List[int] = [tag_id for tag_id in self._applied_tags if tag_id not in to_remove] + new_tags: list[int] = [tag_id for tag_id in self._applied_tags if tag_id not in to_remove] await self._state.http.edit_channel(self.id, applied_tags=new_tags, reason=reason) diff --git a/disnake/types/activity.py b/disnake/types/activity.py index 749f015bdc..d9ad7a6a0a 100644 --- a/disnake/types/activity.py +++ b/disnake/types/activity.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Literal, Optional, TypedDict +from typing import Literal, Optional, TypedDict from typing_extensions import NotRequired @@ -16,7 +16,7 @@ class PresenceData(TypedDict): user: User status: StatusType - activities: List[Activity] + activities: list[Activity] client_status: ClientStatus @@ -37,7 +37,7 @@ class ActivityTimestamps(TypedDict, total=False): class ActivityParty(TypedDict, total=False): id: str - size: List[int] # (current size, max size) + size: list[int] # (current size, max size) class ActivityAssets(TypedDict, total=False): @@ -89,7 +89,7 @@ class Activity(SendableActivity, total=False): flags: int # `buttons` is a list of strings when received over gw, # bots cannot access the full button data (like urls) - buttons: List[str] + buttons: list[str] # all of these are undocumented, but still useful in some cases: id: Optional[str] platform: Optional[str] diff --git a/disnake/types/appinfo.py b/disnake/types/appinfo.py index 940462dfa3..ca813b175c 100644 --- a/disnake/types/appinfo.py +++ b/disnake/types/appinfo.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, List, Literal, Optional, TypedDict +from typing import Literal, Optional, TypedDict from typing_extensions import NotRequired @@ -29,7 +29,7 @@ class BaseAppInfo(TypedDict): class InstallParams(TypedDict): - scopes: List[str] + scopes: list[str] permissions: str @@ -38,7 +38,7 @@ class ApplicationIntegrationTypeConfiguration(TypedDict, total=False): class AppInfo(BaseAppInfo): - rpc_origins: NotRequired[List[str]] + rpc_origins: NotRequired[list[str]] bot_public: bool bot_require_code_grant: bool bot: NotRequired[User] @@ -48,24 +48,24 @@ class AppInfo(BaseAppInfo): guild_id: NotRequired[Snowflake] primary_sku_id: NotRequired[Snowflake] slug: NotRequired[str] - tags: NotRequired[List[str]] + tags: NotRequired[list[str]] install_params: NotRequired[InstallParams] custom_install_url: NotRequired[str] role_connections_verification_url: NotRequired[str] approximate_guild_count: NotRequired[int] approximate_user_install_count: NotRequired[int] approximate_user_authorization_count: NotRequired[int] - redirect_uris: NotRequired[List[str]] + redirect_uris: NotRequired[list[str]] interactions_endpoint_url: NotRequired[Optional[str]] event_webhooks_url: NotRequired[Optional[str]] event_webhooks_status: NotRequired[ApplicationEventWebhookStatus] - event_webhooks_type: NotRequired[List[str]] + event_webhooks_type: NotRequired[list[str]] # values in this dict generally shouldn't be null, but they can be empty dicts - integration_types_config: NotRequired[Dict[str, ApplicationIntegrationTypeConfiguration]] + integration_types_config: NotRequired[dict[str, ApplicationIntegrationTypeConfiguration]] class PartialAppInfo(BaseAppInfo, total=False): - rpc_origins: List[str] + rpc_origins: list[str] cover_image: str flags: int @@ -81,12 +81,12 @@ class EditAppInfo(TypedDict, total=False): description: str role_connections_verification_url: Optional[str] install_params: Optional[InstallParams] - integration_types_config: Dict[str, ApplicationIntegrationTypeConfiguration] + integration_types_config: dict[str, ApplicationIntegrationTypeConfiguration] flags: int icon: Optional[str] cover_image: Optional[str] interactions_endpoint_url: Optional[str] - tags: Optional[List[str]] + tags: Optional[list[str]] event_webhooks_url: Optional[str] event_webhooks_status: ApplicationEventWebhookStatus - event_webhooks_types: Optional[List[str]] + event_webhooks_types: Optional[list[str]] diff --git a/disnake/types/audit_log.py b/disnake/types/audit_log.py index cad5b52f4e..d2ff07f9db 100644 --- a/disnake/types/audit_log.py +++ b/disnake/types/audit_log.py @@ -3,7 +3,7 @@ from __future__ import annotations import datetime -from typing import List, Literal, Optional, TypedDict, Union +from typing import Literal, Optional, TypedDict, Union from typing_extensions import NotRequired @@ -185,14 +185,14 @@ class _AuditLogChange_Int(TypedDict): class _AuditLogChange_ListSnowflake(TypedDict): key: Literal["exempt_roles", "exempt_channels"] - new_value: NotRequired[List[Snowflake]] - old_value: NotRequired[List[Snowflake]] + new_value: NotRequired[list[Snowflake]] + old_value: NotRequired[list[Snowflake]] class _AuditLogChange_ListRole(TypedDict): key: Literal["$add", "$remove"] - new_value: NotRequired[List[Role]] - old_value: NotRequired[List[Role]] + new_value: NotRequired[list[Role]] + old_value: NotRequired[list[Role]] class _AuditLogChange_MFALevel(TypedDict): @@ -239,8 +239,8 @@ class _AuditLogChange_VideoQualityMode(TypedDict): class _AuditLogChange_Overwrites(TypedDict): key: Literal["permission_overwrites"] - new_value: NotRequired[List[PermissionOverwrite]] - old_value: NotRequired[List[PermissionOverwrite]] + new_value: NotRequired[list[PermissionOverwrite]] + old_value: NotRequired[list[PermissionOverwrite]] class _AuditLogChange_Datetime(TypedDict): @@ -269,8 +269,8 @@ class _AuditLogChange_AutoModEventType(TypedDict): class _AuditLogChange_AutoModActions(TypedDict): key: Literal["actions"] - new_value: NotRequired[List[AutoModAction]] - old_value: NotRequired[List[AutoModAction]] + new_value: NotRequired[list[AutoModAction]] + old_value: NotRequired[list[AutoModAction]] class _AuditLogChange_AutoModTriggerMetadata(TypedDict): @@ -323,7 +323,7 @@ class AuditEntryInfo(TypedDict): class AuditLogEntry(TypedDict): target_id: Optional[str] - changes: NotRequired[List[AuditLogChange]] + changes: NotRequired[list[AuditLogChange]] user_id: Optional[Snowflake] id: Snowflake action_type: AuditLogEvent @@ -332,11 +332,11 @@ class AuditLogEntry(TypedDict): class AuditLog(TypedDict): - audit_log_entries: List[AuditLogEntry] - application_commands: List[ApplicationCommand] - auto_moderation_rules: List[AutoModRule] - guild_scheduled_events: List[GuildScheduledEvent] - integrations: List[PartialIntegration] - threads: List[Thread] - users: List[User] - webhooks: List[Webhook] + audit_log_entries: list[AuditLogEntry] + application_commands: list[ApplicationCommand] + auto_moderation_rules: list[AutoModRule] + guild_scheduled_events: list[GuildScheduledEvent] + integrations: list[PartialIntegration] + threads: list[Thread] + users: list[User] + webhooks: list[Webhook] diff --git a/disnake/types/automod.py b/disnake/types/automod.py index f7ac372e5e..d596418142 100644 --- a/disnake/types/automod.py +++ b/disnake/types/automod.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Literal, TypedDict, Union +from typing import Literal, TypedDict, Union from typing_extensions import NotRequired @@ -39,10 +39,10 @@ class AutoModAction(TypedDict): class AutoModTriggerMetadata(TypedDict, total=False): - keyword_filter: List[str] - regex_patterns: List[str] - presets: List[AutoModPresetType] - allow_list: List[str] + keyword_filter: list[str] + regex_patterns: list[str] + presets: list[AutoModPresetType] + allow_list: list[str] mention_total_limit: int mention_raid_protection_enabled: bool @@ -55,7 +55,7 @@ class AutoModRule(TypedDict): event_type: AutoModEventType trigger_type: AutoModTriggerType trigger_metadata: AutoModTriggerMetadata - actions: List[AutoModAction] + actions: list[AutoModAction] enabled: bool exempt_roles: SnowflakeList exempt_channels: SnowflakeList @@ -65,7 +65,7 @@ class EditAutoModRule(TypedDict, total=False): name: str event_type: AutoModEventType trigger_metadata: AutoModTriggerMetadata - actions: List[AutoModAction] + actions: list[AutoModAction] enabled: bool exempt_roles: SnowflakeList exempt_channels: SnowflakeList @@ -76,7 +76,7 @@ class CreateAutoModRule(TypedDict): event_type: AutoModEventType trigger_type: AutoModTriggerType trigger_metadata: NotRequired[AutoModTriggerMetadata] - actions: List[AutoModAction] + actions: list[AutoModAction] enabled: NotRequired[bool] exempt_roles: NotRequired[SnowflakeList] exempt_channels: NotRequired[SnowflakeList] diff --git a/disnake/types/channel.py b/disnake/types/channel.py index d10a688caa..adca9c962b 100644 --- a/disnake/types/channel.py +++ b/disnake/types/channel.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import List, Literal, Optional, TypedDict, Union +from typing import Literal, Optional, TypedDict, Union from typing_extensions import NotRequired @@ -29,7 +29,7 @@ class _BaseChannel(TypedDict): class _BaseGuildChannel(_BaseChannel): guild_id: Snowflake position: int - permission_overwrites: List[PermissionOverwrite] + permission_overwrites: list[PermissionOverwrite] # In theory, this will never be None and will always be present. In practice... name: NotRequired[Optional[str]] nsfw: bool @@ -47,7 +47,7 @@ class GroupInviteRecipient(TypedDict): class InviteChannel(PartialChannel, total=False): name: Optional[str] - recipients: List[GroupInviteRecipient] + recipients: list[GroupInviteRecipient] icon: Optional[str] @@ -123,7 +123,7 @@ class _BaseThreadOnlyGuildChannel(_BaseGuildChannel): topic: NotRequired[Optional[str]] last_message_id: NotRequired[Optional[Snowflake]] default_auto_archive_duration: NotRequired[ThreadArchiveDurationLiteral] - available_tags: NotRequired[List[ForumTag]] + available_tags: NotRequired[list[ForumTag]] default_reaction_emoji: NotRequired[Optional[DefaultReaction]] default_thread_rate_limit_per_user: NotRequired[int] default_sort_order: NotRequired[Optional[ThreadSortOrder]] @@ -153,7 +153,7 @@ class MediaChannel(_BaseThreadOnlyGuildChannel): class DMChannel(_BaseChannel): type: Literal[1] last_message_id: Optional[Snowflake] - recipients: List[PartialUser] + recipients: list[PartialUser] class GroupDMChannel(_BaseChannel): @@ -191,7 +191,7 @@ class CreateGuildChannel(TypedDict): user_limit: NotRequired[Optional[int]] rate_limit_per_user: NotRequired[Optional[int]] position: NotRequired[Optional[int]] - permission_overwrites: NotRequired[List[PermissionOverwrite]] + permission_overwrites: NotRequired[list[PermissionOverwrite]] parent_id: NotRequired[Optional[Snowflake]] nsfw: NotRequired[Optional[bool]] rtc_region: NotRequired[Optional[str]] @@ -200,5 +200,5 @@ class CreateGuildChannel(TypedDict): class ChannelPins(TypedDict): - items: List[MessagePin] + items: list[MessagePin] has_more: bool diff --git a/disnake/types/components.py b/disnake/types/components.py index fa13f7d3be..d78753d0af 100644 --- a/disnake/types/components.py +++ b/disnake/types/components.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Literal, Optional, TypedDict, Union +from typing import Literal, Optional, TypedDict, Union from typing_extensions import NotRequired, Required, TypeAlias @@ -78,7 +78,7 @@ class _BaseComponent(TypedDict): class ActionRow(_BaseComponent): type: Literal[1] - components: List[ActionRowChildComponent] + components: list[ActionRowChildComponent] # button @@ -118,7 +118,7 @@ class _SelectMenu(_BaseComponent): max_values: NotRequired[int] disabled: NotRequired[bool] # This is technically not applicable to string selects, but for simplicity we'll just have it here - default_values: NotRequired[List[SelectDefaultValue]] + default_values: NotRequired[list[SelectDefaultValue]] required: NotRequired[bool] @@ -128,7 +128,7 @@ class BaseSelectMenu(_SelectMenu): class StringSelectMenu(_SelectMenu): type: Literal[3] - options: List[SelectOption] + options: list[SelectOption] class UserSelectMenu(_SelectMenu): @@ -145,7 +145,7 @@ class MentionableSelectMenu(_SelectMenu): class ChannelSelectMenu(_SelectMenu): type: Literal[8] - channel_types: NotRequired[List[ChannelType]] + channel_types: NotRequired[list[ChannelType]] AnySelectMenu = Union[ @@ -163,7 +163,7 @@ class ChannelSelectMenu(_SelectMenu): class Modal(TypedDict): title: str custom_id: str - components: List[ModalTopLevelComponent] + components: list[ModalTopLevelComponent] class TextInput(_BaseComponent): @@ -203,7 +203,7 @@ class UnfurledMediaItem(TypedDict, total=False): class SectionComponent(_BaseComponent): type: Literal[9] # note: this may be expanded to more component types in the future - components: List[TextDisplayComponent] + components: list[TextDisplayComponent] # note: same as above accessory: Union[ThumbnailComponent, ButtonComponent] @@ -229,7 +229,7 @@ class MediaGalleryItem(TypedDict): class MediaGalleryComponent(_BaseComponent): type: Literal[12] - items: List[MediaGalleryItem] + items: list[MediaGalleryItem] class FileComponent(_BaseComponent): @@ -250,7 +250,7 @@ class ContainerComponent(_BaseComponent): type: Literal[17] accent_color: NotRequired[int] spoiler: NotRequired[bool] - components: List[ + components: list[ Union[ ActionRow, SectionComponent, diff --git a/disnake/types/embed.py b/disnake/types/embed.py index a066b084d3..ef33d1a5a2 100644 --- a/disnake/types/embed.py +++ b/disnake/types/embed.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import List, Literal, TypedDict +from typing import Literal, TypedDict from typing_extensions import NotRequired @@ -66,4 +66,4 @@ class Embed(TypedDict, total=False): video: EmbedVideo provider: EmbedProvider author: EmbedAuthor - fields: List[EmbedField] + fields: list[EmbedField] diff --git a/disnake/types/emoji.py b/disnake/types/emoji.py index 76ac0f423b..c19ac3e184 100644 --- a/disnake/types/emoji.py +++ b/disnake/types/emoji.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import List, Optional, TypedDict +from typing import Optional, TypedDict from .snowflake import Snowflake, SnowflakeList from .user import User @@ -26,4 +26,4 @@ class EditEmoji(TypedDict): class ListAppEmoji(TypedDict): - items: List[Emoji] + items: list[Emoji] diff --git a/disnake/types/gateway.py b/disnake/types/gateway.py index 31797bbf15..a1bbce8a43 100644 --- a/disnake/types/gateway.py +++ b/disnake/types/gateway.py @@ -2,7 +2,8 @@ from __future__ import annotations -from typing import Any, List, Literal, Optional, Sequence, Tuple, TypedDict, Union +from collections.abc import Sequence +from typing import Any, Literal, Optional, TypedDict, Union from typing_extensions import NotRequired @@ -84,7 +85,7 @@ class IdentifyData(TypedDict): properties: IdentifyProperties compress: NotRequired[bool] large_threshold: NotRequired[int] - shard: NotRequired[Tuple[int, int]] + shard: NotRequired[tuple[int, int]] presence: NotRequired[PresenceUpdateData] intents: int @@ -169,12 +170,12 @@ class VoiceReadyPayload(TypedDict): ssrc: int ip: str port: int - modes: List[str] + modes: list[str] class VoiceSessionDescriptionPayload(TypedDict): mode: SupportedModes - secret_key: List[int] + secret_key: list[int] ##### @@ -252,10 +253,10 @@ class VoiceResumeCommand(TypedDict): class ReadyEvent(TypedDict): v: int user: User - guilds: List[UnavailableGuild] + guilds: list[UnavailableGuild] session_id: str resume_gateway_url: str - shard: NotRequired[Tuple[int, int]] + shard: NotRequired[tuple[int, int]] application: PartialGatewayAppInfo @@ -285,7 +286,7 @@ class MessageDeleteEvent(TypedDict): # https://discord.com/developers/docs/topics/gateway-events#message-delete-bulk class MessageDeleteBulkEvent(TypedDict): - ids: List[Snowflake] + ids: list[Snowflake] channel_id: Snowflake guild_id: NotRequired[Snowflake] @@ -416,9 +417,9 @@ class ThreadDeleteEvent(TypedDict): # https://discord.com/developers/docs/topics/gateway-events#thread-list-sync class ThreadListSyncEvent(TypedDict): guild_id: Snowflake - channel_ids: NotRequired[List[Snowflake]] - threads: List[Thread] - members: List[ThreadMember] + channel_ids: NotRequired[list[Snowflake]] + threads: list[Thread] + members: list[ThreadMember] # https://discord.com/developers/docs/topics/gateway-events#thread-member-update @@ -431,8 +432,8 @@ class ThreadMembersUpdateEvent(TypedDict): id: Snowflake guild_id: Snowflake member_count: int - added_members: NotRequired[List[ThreadMemberWithPresence]] - removed_member_ids: NotRequired[List[Snowflake]] + added_members: NotRequired[list[ThreadMemberWithPresence]] + removed_member_ids: NotRequired[list[Snowflake]] # https://discord.com/developers/docs/topics/gateway-events#guild-member-add @@ -449,7 +450,7 @@ class GuildMemberRemoveEvent(TypedDict): # https://discord.com/developers/docs/topics/gateway-events#guild-member-update class GuildMemberUpdateEvent(TypedDict): guild_id: Snowflake - roles: List[Snowflake] + roles: list[Snowflake] user: User nick: NotRequired[Optional[str]] avatar: Optional[str] @@ -467,13 +468,13 @@ class GuildMemberUpdateEvent(TypedDict): # https://discord.com/developers/docs/topics/gateway-events#guild-emojis-update class GuildEmojisUpdateEvent(TypedDict): guild_id: Snowflake - emojis: List[Emoji] + emojis: list[Emoji] # https://discord.com/developers/docs/topics/gateway-events#guild-stickers-update class GuildStickersUpdateEvent(TypedDict): guild_id: Snowflake - stickers: List[GuildSticker] + stickers: list[GuildSticker] # https://discord.com/developers/docs/topics/gateway-events#guild-create @@ -553,11 +554,11 @@ class _GuildScheduledEventUserEvent(TypedDict): # https://discord.com/developers/docs/topics/gateway-events#guild-members-chunk class GuildMembersChunkEvent(TypedDict): guild_id: Snowflake - members: List[MemberWithUser] + members: list[MemberWithUser] chunk_index: int chunk_count: int - not_found: NotRequired[List[Snowflake]] - presences: NotRequired[List[PresenceData]] + not_found: NotRequired[list[Snowflake]] + presences: NotRequired[list[PresenceData]] nonce: NotRequired[str] @@ -697,4 +698,4 @@ class GuildSoundboardSoundDelete(TypedDict): # https://discord.com/developers/docs/topics/gateway-events#guild-soundboard-sounds-update class GuildSoundboardSoundsUpdate(TypedDict): guild_id: Snowflake - soundboard_sounds: List[GuildSoundboardSound] + soundboard_sounds: list[GuildSoundboardSound] diff --git a/disnake/types/guild.py b/disnake/types/guild.py index d76907940d..7d4ce6776d 100644 --- a/disnake/types/guild.py +++ b/disnake/types/guild.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import List, Literal, Optional, TypedDict +from typing import Literal, Optional, TypedDict from typing_extensions import NotRequired @@ -25,8 +25,8 @@ class Ban(TypedDict): class BulkBanResult(TypedDict): - banned_users: List[Snowflake] - failed_users: List[Snowflake] + banned_users: list[Snowflake] + failed_users: list[Snowflake] class UnavailableGuild(TypedDict): @@ -99,10 +99,10 @@ class _BaseGuildPreview(UnavailableGuild): icon: Optional[str] splash: Optional[str] discovery_splash: Optional[str] - emojis: List[Emoji] - features: List[GuildFeature] + emojis: list[Emoji] + features: list[GuildFeature] description: Optional[str] - stickers: List[GuildSticker] + stickers: list[GuildSticker] class GuildPreview(_BaseGuildPreview): @@ -123,7 +123,7 @@ class Guild(_BaseGuildPreview): verification_level: VerificationLevel default_message_notifications: DefaultMessageNotificationLevel explicit_content_filter: ExplicitContentFilterLevel - roles: List[Role] + roles: list[Role] mfa_level: MFALevel application_id: Optional[Snowflake] system_channel_id: Optional[Snowflake] @@ -142,7 +142,7 @@ class Guild(_BaseGuildPreview): approximate_member_count: NotRequired[int] approximate_presence_count: NotRequired[int] nsfw_level: NSFWLevel - stickers: NotRequired[List[GuildSticker]] + stickers: NotRequired[list[GuildSticker]] premium_progress_bar_enabled: bool safety_alerts_channel_id: Optional[Snowflake] incidents_data: Optional[IncidentsData] @@ -151,14 +151,14 @@ class Guild(_BaseGuildPreview): joined_at: NotRequired[Optional[str]] large: NotRequired[bool] member_count: NotRequired[int] - voice_states: NotRequired[List[GuildVoiceState]] - members: NotRequired[List[Member]] - channels: NotRequired[List[GuildChannel]] - threads: NotRequired[List[Thread]] - presences: NotRequired[List[PartialPresenceUpdate]] - stage_instances: NotRequired[List[StageInstance]] - guild_scheduled_events: NotRequired[List[GuildScheduledEvent]] - soundboard_sounds: NotRequired[List[GuildSoundboardSound]] + voice_states: NotRequired[list[GuildVoiceState]] + members: NotRequired[list[Member]] + channels: NotRequired[list[GuildChannel]] + threads: NotRequired[list[Thread]] + presences: NotRequired[list[PartialPresenceUpdate]] + stage_instances: NotRequired[list[StageInstance]] + guild_scheduled_events: NotRequired[list[GuildScheduledEvent]] + soundboard_sounds: NotRequired[list[GuildSoundboardSound]] class InviteGuild(Guild, total=False): @@ -199,8 +199,8 @@ class CreateGuild(TypedDict): verification_level: NotRequired[VerificationLevel] default_message_notifications: NotRequired[DefaultMessageNotificationLevel] explicit_content_filter: NotRequired[ExplicitContentFilterLevel] - roles: NotRequired[List[CreateGuildPlaceholderRole]] - channels: NotRequired[List[CreateGuildPlaceholderChannel]] + roles: NotRequired[list[CreateGuildPlaceholderRole]] + channels: NotRequired[list[CreateGuildPlaceholderChannel]] afk_channel_id: NotRequired[Snowflake] afk_timeout: NotRequired[int] system_channel_id: NotRequired[Snowflake] diff --git a/disnake/types/i18n.py b/disnake/types/i18n.py index e8aa30eb23..3518c4cd69 100644 --- a/disnake/types/i18n.py +++ b/disnake/types/i18n.py @@ -1,5 +1,4 @@ # SPDX-License-Identifier: MIT -from typing import Dict -LocalizationDict = Dict[str, str] +LocalizationDict = dict[str, str] diff --git a/disnake/types/integration.py b/disnake/types/integration.py index d12ff6f958..127de48627 100644 --- a/disnake/types/integration.py +++ b/disnake/types/integration.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Literal, Optional, TypedDict, Union +from typing import Literal, Optional, TypedDict, Union from typing_extensions import NotRequired @@ -57,7 +57,7 @@ class StreamIntegration(BaseIntegration): class BotIntegration(BaseIntegration): application: IntegrationApplication - scopes: List[str] + scopes: list[str] Integration = Union[BaseIntegration, StreamIntegration, BotIntegration] diff --git a/disnake/types/interactions.py b/disnake/types/interactions.py index c24af62299..9ec318ce17 100644 --- a/disnake/types/interactions.py +++ b/disnake/types/interactions.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Dict, List, Literal, Optional, TypedDict, Union +from typing import TYPE_CHECKING, Literal, Optional, TypedDict, Union from .appinfo import ApplicationIntegrationType from .channel import ChannelType @@ -36,13 +36,13 @@ class ApplicationCommand(TypedDict): name_localizations: NotRequired[Optional[LocalizationDict]] description: str description_localizations: NotRequired[Optional[LocalizationDict]] - options: NotRequired[List[ApplicationCommandOption]] + options: NotRequired[list[ApplicationCommandOption]] default_member_permissions: NotRequired[Optional[str]] dm_permission: NotRequired[Optional[bool]] # deprecated default_permission: NotRequired[bool] # deprecated nsfw: NotRequired[bool] - integration_types: NotRequired[List[ApplicationIntegrationType]] - contexts: NotRequired[Optional[List[InteractionContextType]]] + integration_types: NotRequired[list[ApplicationIntegrationType]] + contexts: NotRequired[Optional[list[InteractionContextType]]] version: Snowflake @@ -56,9 +56,9 @@ class ApplicationCommandOption(TypedDict): description: str description_localizations: NotRequired[Optional[LocalizationDict]] required: NotRequired[bool] - choices: NotRequired[List[ApplicationCommandOptionChoice]] - options: NotRequired[List[ApplicationCommandOption]] - channel_types: NotRequired[List[ChannelType]] + choices: NotRequired[list[ApplicationCommandOptionChoice]] + options: NotRequired[list[ApplicationCommandOption]] + channel_types: NotRequired[list[ChannelType]] min_value: NotRequired[float] max_value: NotRequired[float] min_length: NotRequired[int] @@ -88,7 +88,7 @@ class GuildApplicationCommandPermissions(TypedDict): id: Snowflake application_id: Snowflake guild_id: Snowflake - permissions: List[ApplicationCommandPermissions] + permissions: list[ApplicationCommandPermissions] InteractionType = Literal[1, 2, 3, 4, 5] @@ -106,15 +106,15 @@ class InteractionChannel(TypedDict): class InteractionDataResolved(TypedDict, total=False): - users: Dict[Snowflake, User] - members: Dict[Snowflake, Member] - roles: Dict[Snowflake, Role] - channels: Dict[Snowflake, InteractionChannel] + users: dict[Snowflake, User] + members: dict[Snowflake, Member] + roles: dict[Snowflake, Role] + channels: dict[Snowflake, InteractionChannel] class ApplicationCommandInteractionDataResolved(InteractionDataResolved, total=False): - messages: Dict[Snowflake, Message] - attachments: Dict[Snowflake, Attachment] + messages: dict[Snowflake, Message] + attachments: dict[Snowflake, Attachment] class _ApplicationCommandInteractionDataOption(TypedDict): @@ -123,7 +123,7 @@ class _ApplicationCommandInteractionDataOption(TypedDict): class _ApplicationCommandInteractionDataOptionSubcommand(_ApplicationCommandInteractionDataOption): type: Literal[1, 2] - options: List[ApplicationCommandInteractionDataOption] + options: list[ApplicationCommandInteractionDataOption] class _ApplicationCommandInteractionDataOptionString(_ApplicationCommandInteractionDataOption): @@ -166,7 +166,7 @@ class ApplicationCommandInteractionData(TypedDict): name: str type: ApplicationCommandType resolved: NotRequired[ApplicationCommandInteractionDataResolved] - options: NotRequired[List[ApplicationCommandInteractionDataOption]] + options: NotRequired[list[ApplicationCommandInteractionDataOption]] # this is the guild the command is registered to, not the guild the command was invoked in (see interaction.guild_id) guild_id: NotRequired[Snowflake] target_id: NotRequired[Snowflake] @@ -187,7 +187,7 @@ class _BaseCustomIdComponentInteractionData(_BaseComponentInteractionData): class _BaseSnowflakeMessageComponentInteractionData(_BaseCustomIdComponentInteractionData): - values: List[Snowflake] + values: list[Snowflake] resolved: NotRequired[InteractionDataResolved] @@ -197,7 +197,7 @@ class MessageComponentInteractionButtonData(_BaseCustomIdComponentInteractionDat class MessageComponentInteractionStringSelectData(_BaseCustomIdComponentInteractionData): component_type: Literal[3] - values: List[str] + values: list[str] class MessageComponentInteractionUserSelectData(_BaseSnowflakeMessageComponentInteractionData): @@ -232,12 +232,12 @@ class MessageComponentInteractionChannelSelectData(_BaseSnowflakeMessageComponen class _BaseSnowflakeModalComponentInteractionData(_BaseCustomIdComponentInteractionData): - values: List[Snowflake] + values: list[Snowflake] class ModalInteractionStringSelectData(_BaseCustomIdComponentInteractionData): type: Literal[3] - values: List[str] + values: list[str] class ModalInteractionTextInputData(_BaseCustomIdComponentInteractionData): @@ -268,7 +268,7 @@ class ModalInteractionChannelSelectData(_BaseSnowflakeModalComponentInteractionD class ModalInteractionActionRowData(_BaseComponentInteractionData): type: Literal[1] - components: List[ModalInteractionActionRowChildData] + components: list[ModalInteractionActionRowChildData] class ModalInteractionTextDisplayData(_BaseComponentInteractionData): @@ -306,7 +306,7 @@ class ModalInteractionLabelData(_BaseComponentInteractionData): class ModalInteractionData(TypedDict): custom_id: str - components: List[ModalInteractionComponentData] + components: list[ModalInteractionComponentData] # resolved: NotRequired[InteractionDataResolved] # undocumented @@ -314,7 +314,7 @@ class ModalInteractionData(TypedDict): # keys are stringified ApplicationInstallType's -AuthorizingIntegrationOwners = Dict[str, Snowflake] +AuthorizingIntegrationOwners = dict[str, Snowflake] # base type for *all* interactions @@ -336,7 +336,7 @@ class _BaseUserInteraction(_BaseInteraction): locale: str guild_id: NotRequired[Snowflake] guild_locale: NotRequired[str] - entitlements: NotRequired[List[Entitlement]] + entitlements: NotRequired[list[Entitlement]] authorizing_integration_owners: NotRequired[AuthorizingIntegrationOwners] context: NotRequired[InteractionContextType] # one of these two will always exist, according to docs @@ -377,15 +377,15 @@ class ModalInteraction(_BaseUserInteraction): class InteractionApplicationCommandCallbackData(TypedDict, total=False): tts: bool content: str - embeds: List[Embed] + embeds: list[Embed] allowed_mentions: AllowedMentions flags: int - components: List[MessageTopLevelComponent] - attachments: List[Attachment] + components: list[MessageTopLevelComponent] + attachments: list[Attachment] class InteractionAutocompleteCallbackData(TypedDict): - choices: List[ApplicationCommandOptionChoice] + choices: list[ApplicationCommandOptionChoice] InteractionResponseType = Literal[1, 4, 5, 6, 7, 10] @@ -446,12 +446,12 @@ class EditApplicationCommand(TypedDict): name_localizations: NotRequired[Optional[LocalizationDict]] description: NotRequired[str] description_localizations: NotRequired[Optional[LocalizationDict]] - options: NotRequired[Optional[List[ApplicationCommandOption]]] + options: NotRequired[Optional[list[ApplicationCommandOption]]] default_member_permissions: NotRequired[Optional[str]] dm_permission: NotRequired[bool] # deprecated default_permission: NotRequired[bool] # deprecated nsfw: NotRequired[bool] - integration_types: NotRequired[Optional[List[ApplicationIntegrationType]]] - contexts: NotRequired[Optional[List[InteractionContextType]]] + integration_types: NotRequired[Optional[list[ApplicationIntegrationType]]] + contexts: NotRequired[Optional[list[InteractionContextType]]] # n.b. this cannot be changed type: NotRequired[ApplicationCommandType] diff --git a/disnake/types/message.py b/disnake/types/message.py index 993b9de79e..dde1a9ba11 100644 --- a/disnake/types/message.py +++ b/disnake/types/message.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Literal, Optional, TypedDict, Union +from typing import Literal, Optional, TypedDict, Union from typing_extensions import NotRequired @@ -79,17 +79,17 @@ class MessageReference(TypedDict): class ForwardedMessage(TypedDict): type: MessageType content: str - embeds: List[Embed] - attachments: List[Attachment] + embeds: list[Embed] + attachments: list[Attachment] timestamp: str edited_timestamp: Optional[str] flags: NotRequired[int] - mentions: Union[List[User], List[UserWithMember]] + mentions: Union[list[User], list[UserWithMember]] # apparently mention_roles list is not sent if the msg # is not forwarded in the same guild mention_roles: NotRequired[SnowflakeList] - sticker_items: NotRequired[List[StickerItem]] - components: NotRequired[List[MessageTopLevelComponent]] + sticker_items: NotRequired[list[StickerItem]] + components: NotRequired[list[MessageTopLevelComponent]] class MessageSnapshot(TypedDict): @@ -118,12 +118,12 @@ class Message(TypedDict): tts: bool mention_everyone: bool # this only contains (partial) member data in gateway events - mentions: Union[List[User], List[UserWithMember]] + mentions: Union[list[User], list[UserWithMember]] mention_roles: SnowflakeList - mention_channels: NotRequired[List[ChannelMention]] - attachments: List[Attachment] - embeds: List[Embed] - reactions: NotRequired[List[Reaction]] + mention_channels: NotRequired[list[ChannelMention]] + attachments: list[Attachment] + embeds: list[Embed] + reactions: NotRequired[list[Reaction]] nonce: NotRequired[Union[int, str]] pinned: bool webhook_id: NotRequired[Snowflake] @@ -132,14 +132,14 @@ class Message(TypedDict): application: NotRequired[MessageApplication] application_id: NotRequired[Snowflake] message_reference: NotRequired[MessageReference] - message_snapshots: NotRequired[List[MessageSnapshot]] + message_snapshots: NotRequired[list[MessageSnapshot]] flags: NotRequired[int] referenced_message: NotRequired[Optional[Message]] interaction: NotRequired[InteractionMessageReference] # deprecated interaction_metadata: NotRequired[InteractionMetadata] thread: NotRequired[Thread] - components: NotRequired[List[MessageTopLevelComponent]] - sticker_items: NotRequired[List[StickerItem]] + components: NotRequired[list[MessageTopLevelComponent]] + sticker_items: NotRequired[list[StickerItem]] position: NotRequired[int] role_subscription_data: NotRequired[RoleSubscriptionData] poll: NotRequired[Poll] @@ -155,7 +155,7 @@ class Message(TypedDict): class AllowedMentions(TypedDict): - parse: List[AllowedMentionType] + parse: list[AllowedMentionType] roles: SnowflakeList users: SnowflakeList replied_user: bool diff --git a/disnake/types/onboarding.py b/disnake/types/onboarding.py index 79d1bb86a2..8b255e68b9 100644 --- a/disnake/types/onboarding.py +++ b/disnake/types/onboarding.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import List, Literal, Optional, TypedDict +from typing import Literal, Optional, TypedDict from .emoji import Emoji from .snowflake import Snowflake, SnowflakeList @@ -20,7 +20,7 @@ class OnboardingPromptOption(TypedDict): class OnboardingPrompt(TypedDict): id: Snowflake title: str - options: List[OnboardingPromptOption] + options: list[OnboardingPromptOption] single_select: bool required: bool in_onboarding: bool @@ -29,6 +29,6 @@ class OnboardingPrompt(TypedDict): class Onboarding(TypedDict): guild_id: Snowflake - prompts: List[OnboardingPrompt] + prompts: list[OnboardingPrompt] default_channel_ids: SnowflakeList enabled: bool diff --git a/disnake/types/poll.py b/disnake/types/poll.py index 37d33e2206..a9a601d955 100644 --- a/disnake/types/poll.py +++ b/disnake/types/poll.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Literal, Optional, TypedDict +from typing import Literal, Optional, TypedDict from typing_extensions import NotRequired @@ -33,16 +33,16 @@ class PollAnswerCount(TypedDict): class PollResult(TypedDict): is_finalized: bool - answer_counts: List[PollAnswerCount] + answer_counts: list[PollAnswerCount] class PollVoters(TypedDict): - users: List[User] + users: list[User] class Poll(TypedDict): question: PollMedia - answers: List[PollAnswer] + answers: list[PollAnswer] expiry: Optional[str] allow_multiselect: bool layout_type: PollLayoutType @@ -66,7 +66,7 @@ class PollCreateAnswerPayload(TypedDict): class PollCreatePayload(TypedDict): question: PollCreateMediaPayload - answers: List[PollCreateAnswerPayload] + answers: list[PollCreateAnswerPayload] duration: int allow_multiselect: bool layout_type: NotRequired[int] diff --git a/disnake/types/snowflake.py b/disnake/types/snowflake.py index 96b088524d..49741159e4 100644 --- a/disnake/types/snowflake.py +++ b/disnake/types/snowflake.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import List, Union +from typing import Union Snowflake = Union[str, int] -SnowflakeList = Union[List[str], List[int]] # keep separate for variance +SnowflakeList = Union[list[str], list[int]] # keep separate for variance diff --git a/disnake/types/soundboard.py b/disnake/types/soundboard.py index 333d7033b3..c1825effe1 100644 --- a/disnake/types/soundboard.py +++ b/disnake/types/soundboard.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Optional, TypedDict +from typing import Optional, TypedDict from typing_extensions import NotRequired @@ -28,4 +28,4 @@ class GuildSoundboardSound(SoundboardSound): class ListGuildSoundboardSounds(TypedDict): - items: List[GuildSoundboardSound] + items: list[GuildSoundboardSound] diff --git a/disnake/types/sticker.py b/disnake/types/sticker.py index 06bc58aa05..60c3c17966 100644 --- a/disnake/types/sticker.py +++ b/disnake/types/sticker.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Literal, Optional, TypedDict, Union +from typing import Literal, Optional, TypedDict, Union from typing_extensions import NotRequired @@ -44,7 +44,7 @@ class GuildSticker(BaseSticker): class StickerPack(TypedDict): id: Snowflake - stickers: List[StandardSticker] + stickers: list[StandardSticker] name: str sku_id: Snowflake cover_sticker_id: NotRequired[Snowflake] @@ -65,4 +65,4 @@ class EditGuildSticker(TypedDict, total=False): class ListStickerPacks(TypedDict): - sticker_packs: List[StickerPack] + sticker_packs: list[StickerPack] diff --git a/disnake/types/subscription.py b/disnake/types/subscription.py index 1cfaaf8684..e5ae691111 100644 --- a/disnake/types/subscription.py +++ b/disnake/types/subscription.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import List, Literal, Optional, TypedDict +from typing import Literal, Optional, TypedDict from typing_extensions import NotRequired @@ -12,9 +12,9 @@ class Subscription(TypedDict): id: Snowflake user_id: Snowflake - sku_ids: List[Snowflake] - entitlement_ids: List[Snowflake] - renewal_sku_ids: Optional[List[Snowflake]] + sku_ids: list[Snowflake] + entitlement_ids: list[Snowflake] + renewal_sku_ids: Optional[list[Snowflake]] current_period_start: str current_period_end: str status: SubscriptionStatus diff --git a/disnake/types/team.py b/disnake/types/team.py index 0829c18b5c..bb80992b2f 100644 --- a/disnake/types/team.py +++ b/disnake/types/team.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Literal, Optional, TypedDict +from typing import Literal, Optional, TypedDict from .snowflake import Snowflake from .user import PartialUser @@ -22,5 +22,5 @@ class Team(TypedDict): id: Snowflake name: str owner_user_id: Snowflake - members: List[TeamMember] + members: list[TeamMember] icon: Optional[str] diff --git a/disnake/types/threads.py b/disnake/types/threads.py index 30f630d916..9be72c3a6a 100644 --- a/disnake/types/threads.py +++ b/disnake/types/threads.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Literal, Optional, TypedDict +from typing import Literal, Optional, TypedDict from typing_extensions import NotRequired @@ -61,8 +61,8 @@ class ForumThread(Thread): class ThreadPaginationPayload(TypedDict): - threads: List[Thread] - members: List[ThreadMember] + threads: list[Thread] + members: list[ThreadMember] has_more: bool diff --git a/disnake/types/voice.py b/disnake/types/voice.py index 3b59312ddf..d4382b7a8f 100644 --- a/disnake/types/voice.py +++ b/disnake/types/voice.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import List, Literal, Optional, TypedDict +from typing import Literal, Optional, TypedDict from typing_extensions import NotRequired @@ -58,7 +58,7 @@ class VoiceReady(TypedDict): ssrc: int ip: str port: int - modes: List[SupportedModes] + modes: list[SupportedModes] heartbeat_interval: int diff --git a/disnake/types/welcome_screen.py b/disnake/types/welcome_screen.py index e98b7c3668..425799cd8e 100644 --- a/disnake/types/welcome_screen.py +++ b/disnake/types/welcome_screen.py @@ -2,14 +2,14 @@ from __future__ import annotations -from typing import List, Optional, TypedDict +from typing import Optional, TypedDict from .snowflake import Snowflake class WelcomeScreen(TypedDict): description: Optional[str] - welcome_channels: List[WelcomeScreenChannel] + welcome_channels: list[WelcomeScreenChannel] class WelcomeScreenChannel(TypedDict): diff --git a/disnake/types/widget.py b/disnake/types/widget.py index df011ac1a5..9f638cd152 100644 --- a/disnake/types/widget.py +++ b/disnake/types/widget.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import List, Optional, TypedDict +from typing import Optional, TypedDict from .snowflake import Snowflake from .user import User @@ -35,8 +35,8 @@ class Widget(TypedDict): id: Snowflake name: str instant_invite: Optional[str] - channels: List[WidgetChannel] - members: List[WidgetMember] + channels: list[WidgetChannel] + members: list[WidgetMember] presence_count: int diff --git a/disnake/ui/_types.py b/disnake/ui/_types.py index de7afa2735..6e762e4a29 100644 --- a/disnake/ui/_types.py +++ b/disnake/ui/_types.py @@ -2,7 +2,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Optional, Sequence, TypeVar, Union +from collections.abc import Sequence +from typing import TYPE_CHECKING, Any, Optional, TypeVar, Union if TYPE_CHECKING: from typing_extensions import TypeAlias diff --git a/disnake/ui/action_row.py b/disnake/ui/action_row.py index 062297dde4..cb51879929 100644 --- a/disnake/ui/action_row.py +++ b/disnake/ui/action_row.py @@ -2,21 +2,14 @@ from __future__ import annotations +from collections.abc import Generator, Iterator, Mapping, Sequence from typing import ( TYPE_CHECKING, Any, ClassVar, - Generator, Generic, - Iterator, - List, - Mapping, NoReturn, Optional, - Sequence, - Set, - Tuple, - Type, TypeVar, Union, cast, @@ -170,7 +163,7 @@ class ActionRow(UIComponent, Generic[ActionRowChildT]): .. versionadded:: 2.11 """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ("_children",) + __repr_attributes__: ClassVar[tuple[str, ...]] = ("_children",) # When unspecified and called empty, default to an ActionRow that takes any kind of component. @@ -202,7 +195,7 @@ def __init__(self, *components: ActionRowChildT, id: int = 0) -> None: ... # n.b. this should be `*components: ActionRowChildT`, but pyright does not like it def __init__(self, *components: WrappedComponent, id: int = 0) -> None: self._id: int = id - self._children: List[ActionRowChildT] = [] + self._children: list[ActionRowChildT] = [] for component in components: if not isinstance(component, WrappedComponent): @@ -638,7 +631,7 @@ def add_channel_select( min_values: int = 1, max_values: int = 1, disabled: bool = False, - channel_types: Optional[List[ChannelType]] = None, + channel_types: Optional[list[ChannelType]] = None, default_values: Optional[Sequence[SelectDefaultValueInputType[AnyChannel]]] = None, id: int = 0, ) -> SelectCompatibleActionRowT: @@ -839,7 +832,7 @@ def to_component_dict(self) -> ActionRowPayload: def from_component(cls, action_row: ActionRowComponent) -> Self: return cls( *cast( - "List[ActionRowChildT]", + "list[ActionRowChildT]", [_to_ui_component(c) for c in action_row.children], ), id=action_row.id, @@ -903,7 +896,7 @@ def rows_from_message( message: Message, *, strict: bool = True, - ) -> List[ActionRow[ActionRowMessageComponent]]: + ) -> list[ActionRow[ActionRowMessageComponent]]: """Create a list of up to 5 action rows from the components on an existing message. This will abide by existing component format on the message, including component @@ -934,7 +927,7 @@ def rows_from_message( :class:`list`\\[:class:`ActionRow`]: The action rows parsed from the components on the message. """ - rows: List[ActionRow[ActionRowMessageComponent]] = [] + rows: list[ActionRow[ActionRowMessageComponent]] = [] for row in message.components: if not isinstance(row, ActionRowComponent): # can happen if message uses components v2 @@ -956,7 +949,7 @@ def rows_from_message( @staticmethod def walk_components( action_rows: Sequence[ActionRow[ActionRowChildT]], - ) -> Generator[Tuple[ActionRow[ActionRowChildT], ActionRowChildT], None, None]: + ) -> Generator[tuple[ActionRow[ActionRowChildT], ActionRowChildT], None, None]: """Iterate over the components in a sequence of action rows, yielding each individual component together with the action row of which it is a child. @@ -1012,7 +1005,7 @@ def normalize_components( if not isinstance(components, Sequence): components = [components] - result: List[Union[ActionRow[ActionRowChildT], NonActionRowChildT]] = [] + result: list[Union[ActionRow[ActionRowChildT], NonActionRowChildT]] = [] auto_row: ActionRow[ActionRowChildT] = ActionRow[ActionRowChildT]() wrap_types = TextInput if modal else WrappedComponent @@ -1056,24 +1049,24 @@ def normalize_components( def normalize_components_to_dict( components: ComponentInput[ActionRowChildT, NonActionRowChildT], -) -> Tuple[List[MessageTopLevelComponentPayload], bool]: +) -> tuple[list[MessageTopLevelComponentPayload], bool]: """`normalize_components`, but also turns components into dicts. Returns ([d1, d2, ...], has_v2_component). """ - component_payloads: List[Mapping[str, Any]] = [] + component_payloads: list[Mapping[str, Any]] = [] is_v2 = False for c in normalize_components(components): component_payloads.append(c.to_component_dict()) is_v2 |= c.is_v2 - return cast("List[MessageTopLevelComponentPayload]", component_payloads), is_v2 + return cast("list[MessageTopLevelComponentPayload]", component_payloads), is_v2 ComponentT = TypeVar("ComponentT", Component, UIComponent) -def _walk_internal(component: ComponentT, seen: Set[ComponentT]) -> Iterator[ComponentT]: +def _walk_internal(component: ComponentT, seen: set[ComponentT]) -> Iterator[ComponentT]: if component in seen: # prevent infinite recursion in case anyone manages to nest a component in itself return @@ -1114,12 +1107,12 @@ def walk_components(components: Sequence[ComponentT]) -> Iterator[ComponentT]: :class:`~disnake.Component` | :class:`UIComponent` A component from the given sequence or child component thereof. """ - seen: Set[ComponentT] = set() + seen: set[ComponentT] = set() for item in components: yield from _walk_internal(item, seen) -def components_from_message(message: Message) -> List[MessageTopLevelComponent]: +def components_from_message(message: Message) -> list[MessageTopLevelComponent]: """Create a list of :class:`UIComponent`\\s from the components of an existing message. This will abide by existing component format on the message, including component @@ -1143,11 +1136,11 @@ def components_from_message(message: Message) -> List[MessageTopLevelComponent]: :class:`list`\\[:class:`UIComponent`]: The ui components parsed from the components on the message. """ - components: List[UIComponent] = [_to_ui_component(c) for c in message.components] - return cast("List[MessageTopLevelComponent]", components) + components: list[UIComponent] = [_to_ui_component(c) for c in message.components] + return cast("list[MessageTopLevelComponent]", components) -UI_COMPONENT_LOOKUP: Mapping[Type[Component], Type[UIComponent]] = { +UI_COMPONENT_LOOKUP: Mapping[type[Component], type[UIComponent]] = { ActionRowComponent: ActionRow, ButtonComponent: Button, StringSelectComponent: StringSelect, diff --git a/disnake/ui/button.py b/disnake/ui/button.py index 313bd1f065..3e580dbdcb 100644 --- a/disnake/ui/button.py +++ b/disnake/ui/button.py @@ -3,7 +3,7 @@ from __future__ import annotations import os -from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, Tuple, TypeVar, Union, overload +from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, TypeVar, Union, overload from ..components import Button as ButtonComponent from ..enums import ButtonStyle, ComponentType @@ -71,7 +71,7 @@ class Button(Item[V_co]): ordering. The row number must be between 0 and 4 (i.e. zero indexed). """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( "style", "url", "disabled", diff --git a/disnake/ui/container.py b/disnake/ui/container.py index 25ab124c40..6ef4fbb065 100644 --- a/disnake/ui/container.py +++ b/disnake/ui/container.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, ClassVar, List, Optional, Tuple, Union, cast +from typing import TYPE_CHECKING, ClassVar, Optional, Union, cast from ..colour import Colour from ..components import Container as ContainerComponent @@ -63,7 +63,7 @@ class Container(UIComponent): Whether the container is marked as a spoiler. """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( "children", "accent_colour", "spoiler", @@ -79,7 +79,7 @@ def __init__( self._id: int = id # this list can be modified without any runtime checks later on, # just assume the user knows what they're doing at that point - self.children: List[ContainerChildUIComponent] = [ + self.children: list[ContainerChildUIComponent] = [ ensure_ui_component(c, "components") for c in components ] self._accent_colour: Optional[Colour] = accent_colour @@ -128,7 +128,7 @@ def from_component(cls, container: ContainerComponent) -> Self: return cls( *cast( - "List[ContainerChildUIComponent]", + "list[ContainerChildUIComponent]", [_to_ui_component(c) for c in container.children], ), accent_colour=container.accent_colour, diff --git a/disnake/ui/file.py b/disnake/ui/file.py index cade201337..24b56db3f0 100644 --- a/disnake/ui/file.py +++ b/disnake/ui/file.py @@ -3,7 +3,7 @@ from __future__ import annotations import copy -from typing import TYPE_CHECKING, ClassVar, Optional, Tuple +from typing import TYPE_CHECKING, ClassVar, Optional from ..components import FileComponent, UnfurledMediaItem, handle_media_item_input from ..enums import ComponentType @@ -36,7 +36,7 @@ class File(UIComponent): sequential identifiers to the components in the message. """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( "file", "spoiler", ) diff --git a/disnake/ui/item.py b/disnake/ui/item.py index 23d48ea0e3..3f45900a95 100644 --- a/disnake/ui/item.py +++ b/disnake/ui/item.py @@ -3,18 +3,15 @@ from __future__ import annotations from abc import ABC, abstractmethod +from collections.abc import Coroutine from typing import ( TYPE_CHECKING, Any, Callable, ClassVar, - Coroutine, - Dict, Generic, Optional, Protocol, - Tuple, - Type, TypeVar, overload, ) @@ -72,7 +69,7 @@ class UIComponent(ABC): .. versionadded:: 2.11 """ - __repr_attributes__: ClassVar[Tuple[str, ...]] + __repr_attributes__: ClassVar[tuple[str, ...]] @property @abstractmethod @@ -106,7 +103,7 @@ def id(self) -> int: def id(self, value: int) -> None: self._underlying.id = value - def to_component_dict(self) -> Dict[str, Any]: + def to_component_dict(self) -> dict[str, Any]: return self._underlying.to_dict() @classmethod @@ -159,7 +156,7 @@ class Item(WrappedComponent, Generic[V_co]): .. versionadded:: 2.0 """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ("row",) + __repr_attributes__: ClassVar[tuple[str, ...]] = ("row",) @overload def __init__(self: Item[None]) -> None: ... @@ -233,7 +230,7 @@ async def callback(self, interaction: MessageInteraction[ClientT], /) -> None: # which work as `View.__init__` replaces the handler with the item. class DecoratedItem(Protocol[I]): @overload - def __get__(self, obj: None, objtype: Type[SelfViewT]) -> ItemCallbackType[SelfViewT, I]: ... + def __get__(self, obj: None, objtype: type[SelfViewT]) -> ItemCallbackType[SelfViewT, I]: ... @overload def __get__(self, obj: Any, objtype: Any) -> I: ... diff --git a/disnake/ui/label.py b/disnake/ui/label.py index c3668d6187..56bbdad021 100644 --- a/disnake/ui/label.py +++ b/disnake/ui/label.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, ClassVar, Optional, Tuple, Union, cast +from typing import TYPE_CHECKING, Any, ClassVar, Optional, Union, cast from ..components import Label as LabelComponent from ..enums import ComponentType @@ -53,7 +53,7 @@ class Label(UIComponent): The description text for the label. """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( "text", "description", "component", diff --git a/disnake/ui/media_gallery.py b/disnake/ui/media_gallery.py index b05b9073dc..1da911284d 100644 --- a/disnake/ui/media_gallery.py +++ b/disnake/ui/media_gallery.py @@ -2,7 +2,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, ClassVar, List, Sequence, Tuple +from collections.abc import Sequence +from typing import TYPE_CHECKING, ClassVar from ..components import MediaGallery as MediaGalleryComponent, MediaGalleryItem from ..enums import ComponentType @@ -32,7 +33,7 @@ class MediaGallery(UIComponent): sequential identifiers to the components in the message. """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ("items",) + __repr_attributes__: ClassVar[tuple[str, ...]] = ("items",) # We have to set this to MISSING in order to overwrite the abstract property from UIComponent _underlying: MediaGalleryComponent = MISSING @@ -44,7 +45,7 @@ def __init__(self, *items: MediaGalleryItem, id: int = 0) -> None: ) @property - def items(self) -> List[MediaGalleryItem]: + def items(self) -> list[MediaGalleryItem]: """:class:`list`\\[:class:`.MediaGalleryItem`]: The images in this gallery.""" return self._underlying.items diff --git a/disnake/ui/modal.py b/disnake/ui/modal.py index bbb1c57cbd..fa1f88f3dd 100644 --- a/disnake/ui/modal.py +++ b/disnake/ui/modal.py @@ -7,7 +7,7 @@ import sys import traceback from functools import partial -from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Tuple, TypeVar, Union, cast +from typing import TYPE_CHECKING, Callable, Optional, TypeVar, Union, cast from ..enums import TextInputStyle from ..utils import MISSING @@ -104,7 +104,7 @@ def __init__( self.title: str = title self.custom_id: str = os.urandom(16).hex() if custom_id is MISSING else custom_id - self.components: List[ModalTopLevelComponent] = list(items) + self.components: list[ModalTopLevelComponent] = list(items) self.timeout: float = timeout # function for the modal to remove itself from the store, if any @@ -119,7 +119,7 @@ def __repr__(self) -> str: ) def append_component( - self, component: Union[ModalTopLevelComponentInput, List[ModalTopLevelComponentInput]] + self, component: Union[ModalTopLevelComponentInput, list[ModalTopLevelComponentInput]] ) -> None: """Adds one or multiple component(s) to the modal. @@ -258,7 +258,7 @@ def to_components(self) -> ModalPayload: "title": self.title, "custom_id": self.custom_id, "components": cast( - "List[ModalTopLevelComponentPayload]", + "list[ModalTopLevelComponentPayload]", [component.to_component_dict() for component in self.components], ), } @@ -318,7 +318,7 @@ class ModalStore: def __init__(self, state: ConnectionState) -> None: self._state = state # (user_id, Modal.custom_id): Modal - self._modals: Dict[Tuple[int, str], Modal] = {} + self._modals: dict[tuple[int, str], Modal] = {} def add_modal(self, user_id: int, modal: Modal) -> None: key = (user_id, modal.custom_id) diff --git a/disnake/ui/section.py b/disnake/ui/section.py index b9f3c9462c..a3b6008975 100644 --- a/disnake/ui/section.py +++ b/disnake/ui/section.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, ClassVar, List, Tuple, Union, cast +from typing import TYPE_CHECKING, Any, ClassVar, Union, cast from ..components import Section as SectionComponent from ..enums import ComponentType @@ -47,7 +47,7 @@ class Section(UIComponent): The accessory component displayed next to the section text. """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( "children", "accessory", ) @@ -61,7 +61,7 @@ def __init__( self._id: int = id # this list can be modified without any runtime checks later on, # just assume the user knows what they're doing at that point - self.children: List[TextDisplay] = [ + self.children: list[TextDisplay] = [ TextDisplay(c) if isinstance(c, str) else ensure_ui_component(c, "components") for c in components ] @@ -93,7 +93,7 @@ def from_component(cls, section: SectionComponent) -> Self: return cls( *cast( - "List[TextDisplay]", + "list[TextDisplay]", [_to_ui_component(c) for c in section.children], ), accessory=cast("SectionAccessoryUIComponent", _to_ui_component(section.accessory)), diff --git a/disnake/ui/select/base.py b/disnake/ui/select/base.py index 832cab3c0b..1feafea457 100644 --- a/disnake/ui/select/base.py +++ b/disnake/ui/select/base.py @@ -4,17 +4,13 @@ import os from abc import ABC, abstractmethod +from collections.abc import Mapping, Sequence from typing import ( TYPE_CHECKING, Callable, ClassVar, Generic, - List, - Mapping, Optional, - Sequence, - Tuple, - Type, TypeVar, Union, ) @@ -66,7 +62,7 @@ class BaseSelect(Generic[SelectMenuT, SelectValueT, V_co], Item[V_co], ABC): .. versionadded:: 2.7 """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( "placeholder", "min_values", "max_values", @@ -77,11 +73,11 @@ class BaseSelect(Generic[SelectMenuT, SelectValueT, V_co], Item[V_co], ABC): _underlying: SelectMenuT = MISSING # Subclasses are expected to set this - _default_value_type_map: ClassVar[Mapping[SelectDefaultValueType, Tuple[Type[Snowflake], ...]]] + _default_value_type_map: ClassVar[Mapping[SelectDefaultValueType, tuple[type[Snowflake], ...]]] def __init__( self, - underlying_type: Type[SelectMenuT], + underlying_type: type[SelectMenuT], component_type: ComponentType, *, custom_id: str, @@ -95,7 +91,7 @@ def __init__( row: Optional[int], ) -> None: super().__init__() - self._selected_values: List[SelectValueT] = [] + self._selected_values: list[SelectValueT] = [] self._provided_custom_id = custom_id is not MISSING custom_id = os.urandom(16).hex() if custom_id is MISSING else custom_id self._underlying = underlying_type._raw_construct( @@ -165,7 +161,7 @@ def disabled(self, value: bool) -> None: self._underlying.disabled = bool(value) @property - def default_values(self) -> List[SelectDefaultValue]: + def default_values(self) -> list[SelectDefaultValue]: """:class:`list`\\[:class:`.SelectDefaultValue`]: The list of values that are selected by default. Only available for auto-populated select menus. """ @@ -191,7 +187,7 @@ def required(self, value: bool) -> None: self._underlying.required = bool(value) @property - def values(self) -> List[SelectValueT]: + def values(self) -> list[SelectValueT]: return self._selected_values @property @@ -219,8 +215,8 @@ def is_dispatchable(self) -> bool: @classmethod def _transform_default_values( cls, values: Sequence[SelectDefaultValueInputType[SelectValueT]] - ) -> List[SelectDefaultValue]: - result: List[SelectDefaultValue] = [] + ) -> list[SelectDefaultValue]: + result: list[SelectDefaultValue] = [] for value in values: # If we have a SelectDefaultValue, just use it as-is diff --git a/disnake/ui/select/channel.py b/disnake/ui/select/channel.py index 15e8f0580b..d5a9bca2a1 100644 --- a/disnake/ui/select/channel.py +++ b/disnake/ui/select/channel.py @@ -2,17 +2,13 @@ from __future__ import annotations +from collections.abc import Mapping, Sequence from typing import ( TYPE_CHECKING, Any, Callable, ClassVar, - List, - Mapping, Optional, - Sequence, - Tuple, - Type, TypeVar, overload, ) @@ -95,13 +91,13 @@ class ChannelSelect(BaseSelect[ChannelSelectMenu, "AnyChannel", V_co]): A list of channels that have been selected by the user. """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( *BaseSelect.__repr_attributes__, "channel_types", ) _default_value_type_map: ClassVar[ - Mapping[SelectDefaultValueType, Tuple[Type[Snowflake], ...]] + Mapping[SelectDefaultValueType, tuple[type[Snowflake], ...]] ] = { SelectDefaultValueType.channel: ( GuildChannel, @@ -122,7 +118,7 @@ def __init__( min_values: int = 1, max_values: int = 1, disabled: bool = False, - channel_types: Optional[List[ChannelType]] = None, + channel_types: Optional[list[ChannelType]] = None, default_values: Optional[Sequence[SelectDefaultValueInputType[AnyChannel]]] = None, required: bool = True, id: int = 0, @@ -138,7 +134,7 @@ def __init__( min_values: int = 1, max_values: int = 1, disabled: bool = False, - channel_types: Optional[List[ChannelType]] = None, + channel_types: Optional[list[ChannelType]] = None, default_values: Optional[Sequence[SelectDefaultValueInputType[AnyChannel]]] = None, required: bool = True, id: int = 0, @@ -153,7 +149,7 @@ def __init__( min_values: int = 1, max_values: int = 1, disabled: bool = False, - channel_types: Optional[List[ChannelType]] = None, + channel_types: Optional[list[ChannelType]] = None, default_values: Optional[Sequence[SelectDefaultValueInputType[AnyChannel]]] = None, required: bool = True, id: int = 0, @@ -190,12 +186,12 @@ def from_component(cls, component: ChannelSelectMenu) -> Self: ) @property - def channel_types(self) -> Optional[List[ChannelType]]: + def channel_types(self) -> Optional[list[ChannelType]]: """:class:`list`\\[:class:`disnake.ChannelType`] | :data:`None`: A list of channel types that can be selected in this select menu.""" return self._underlying.channel_types @channel_types.setter - def channel_types(self, value: Optional[List[ChannelType]]) -> None: + def channel_types(self, value: Optional[list[ChannelType]]) -> None: if value is not None: if not isinstance(value, list): msg = "channel_types must be a list of ChannelType" @@ -218,7 +214,7 @@ def channel_select( min_values: int = 1, max_values: int = 1, disabled: bool = False, - channel_types: Optional[List[ChannelType]] = None, + channel_types: Optional[list[ChannelType]] = None, default_values: Optional[Sequence[SelectDefaultValueInputType[AnyChannel]]] = None, id: int = 0, row: Optional[int] = None, diff --git a/disnake/ui/select/mentionable.py b/disnake/ui/select/mentionable.py index 8c258f4b5d..784fc72edb 100644 --- a/disnake/ui/select/mentionable.py +++ b/disnake/ui/select/mentionable.py @@ -2,16 +2,13 @@ from __future__ import annotations +from collections.abc import Mapping, Sequence from typing import ( TYPE_CHECKING, Any, Callable, ClassVar, - Mapping, Optional, - Sequence, - Tuple, - Type, TypeVar, Union, overload, @@ -94,7 +91,7 @@ class MentionableSelect(BaseSelect[MentionableSelectMenu, "Union[User, Member, R """ _default_value_type_map: ClassVar[ - Mapping[SelectDefaultValueType, Tuple[Type[Snowflake], ...]] + Mapping[SelectDefaultValueType, tuple[type[Snowflake], ...]] ] = { SelectDefaultValueType.user: (Member, User, ClientUser), SelectDefaultValueType.role: (Role,), diff --git a/disnake/ui/select/role.py b/disnake/ui/select/role.py index 99c06086bf..b9105868ea 100644 --- a/disnake/ui/select/role.py +++ b/disnake/ui/select/role.py @@ -2,16 +2,13 @@ from __future__ import annotations +from collections.abc import Mapping, Sequence from typing import ( TYPE_CHECKING, Any, Callable, ClassVar, - Mapping, Optional, - Sequence, - Tuple, - Type, TypeVar, overload, ) @@ -90,7 +87,7 @@ class RoleSelect(BaseSelect[RoleSelectMenu, "Role", V_co]): """ _default_value_type_map: ClassVar[ - Mapping[SelectDefaultValueType, Tuple[Type[Snowflake], ...]] + Mapping[SelectDefaultValueType, tuple[type[Snowflake], ...]] ] = { SelectDefaultValueType.role: (Role, Object), } diff --git a/disnake/ui/select/string.py b/disnake/ui/select/string.py index 54c257e49f..387c2ae290 100644 --- a/disnake/ui/select/string.py +++ b/disnake/ui/select/string.py @@ -2,17 +2,13 @@ from __future__ import annotations +from collections.abc import Mapping from typing import ( TYPE_CHECKING, Any, Callable, ClassVar, - Dict, - List, - Mapping, Optional, - Tuple, - Type, TypeVar, Union, overload, @@ -40,10 +36,10 @@ ) -SelectOptionInput = Union[List[SelectOption], List[str], Dict[str, str]] +SelectOptionInput = Union[list[SelectOption], list[str], dict[str, str]] -def _parse_select_options(options: SelectOptionInput) -> List[SelectOption]: +def _parse_select_options(options: SelectOptionInput) -> list[SelectOption]: if isinstance(options, dict): return [SelectOption(label=key, value=val) for key, val in options.items()] @@ -110,11 +106,11 @@ class StringSelect(BaseSelect[StringSelectMenu, str, V_co]): A list of values that have been selected by the user. """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = (*BaseSelect.__repr_attributes__, "options") + __repr_attributes__: ClassVar[tuple[str, ...]] = (*BaseSelect.__repr_attributes__, "options") # In practice this should never be used by anything, might as well have it anyway though. _default_value_type_map: ClassVar[ - Mapping[SelectDefaultValueType, Tuple[Type[Snowflake], ...]] + Mapping[SelectDefaultValueType, tuple[type[Snowflake], ...]] ] = {} @overload @@ -190,12 +186,12 @@ def from_component(cls, component: StringSelectMenu) -> Self: ) @property - def options(self) -> List[SelectOption]: + def options(self) -> list[SelectOption]: """:class:`list`\\[:class:`disnake.SelectOption`]: A list of options that can be selected in this select menu.""" return self._underlying.options @options.setter - def options(self, value: List[SelectOption]) -> None: + def options(self, value: list[SelectOption]) -> None: if not isinstance(value, list): msg = "options must be a list of SelectOption" raise TypeError(msg) diff --git a/disnake/ui/select/user.py b/disnake/ui/select/user.py index 858a3770ba..a8c2f85e0c 100644 --- a/disnake/ui/select/user.py +++ b/disnake/ui/select/user.py @@ -2,16 +2,13 @@ from __future__ import annotations +from collections.abc import Mapping, Sequence from typing import ( TYPE_CHECKING, Any, Callable, ClassVar, - Mapping, Optional, - Sequence, - Tuple, - Type, TypeVar, Union, overload, @@ -92,7 +89,7 @@ class UserSelect(BaseSelect[UserSelectMenu, "Union[User, Member]", V_co]): """ _default_value_type_map: ClassVar[ - Mapping[SelectDefaultValueType, Tuple[Type[Snowflake], ...]] + Mapping[SelectDefaultValueType, tuple[type[Snowflake], ...]] ] = { SelectDefaultValueType.user: (Member, User, ClientUser, Object), } diff --git a/disnake/ui/separator.py b/disnake/ui/separator.py index 1f62b686b4..622ac69652 100644 --- a/disnake/ui/separator.py +++ b/disnake/ui/separator.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, ClassVar, Tuple +from typing import TYPE_CHECKING, ClassVar from ..components import Separator as SeparatorComponent from ..enums import ComponentType, SeparatorSpacing @@ -34,7 +34,7 @@ class Separator(UIComponent): sequential identifiers to the components in the message. """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( "divider", "spacing", ) diff --git a/disnake/ui/text_display.py b/disnake/ui/text_display.py index 05cd4e1533..9dffecba0e 100644 --- a/disnake/ui/text_display.py +++ b/disnake/ui/text_display.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, ClassVar, Tuple +from typing import TYPE_CHECKING, ClassVar from ..components import TextDisplay as TextDisplayComponent from ..enums import ComponentType @@ -30,7 +30,7 @@ class TextDisplay(UIComponent): sequential identifiers to the components in the message. """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ("content",) + __repr_attributes__: ClassVar[tuple[str, ...]] = ("content",) # We have to set this to MISSING in order to overwrite the abstract property from UIComponent _underlying: TextDisplayComponent = MISSING diff --git a/disnake/ui/text_input.py b/disnake/ui/text_input.py index aadb35d5f2..a08c26c453 100644 --- a/disnake/ui/text_input.py +++ b/disnake/ui/text_input.py @@ -3,7 +3,7 @@ from __future__ import annotations import os -from typing import TYPE_CHECKING, ClassVar, Optional, Tuple +from typing import TYPE_CHECKING, ClassVar, Optional from ..components import TextInput as TextInputComponent from ..enums import ComponentType, TextInputStyle @@ -55,7 +55,7 @@ class TextInput(WrappedComponent): .. versionadded:: 2.11 """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( "style", "custom_id", "placeholder", diff --git a/disnake/ui/thumbnail.py b/disnake/ui/thumbnail.py index 2b15fc6b92..9cc2fea4de 100644 --- a/disnake/ui/thumbnail.py +++ b/disnake/ui/thumbnail.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, ClassVar, Optional, Tuple +from typing import TYPE_CHECKING, ClassVar, Optional from ..components import Thumbnail as ThumbnailComponent, UnfurledMediaItem, handle_media_item_input from ..enums import ComponentType @@ -39,7 +39,7 @@ class Thumbnail(UIComponent): sequential identifiers to the components in the message. """ - __repr_attributes__: ClassVar[Tuple[str, ...]] = ( + __repr_attributes__: ClassVar[tuple[str, ...]] = ( "media", "description", "spoiler", diff --git a/disnake/ui/view.py b/disnake/ui/view.py index d97f526308..c94fe02e7c 100644 --- a/disnake/ui/view.py +++ b/disnake/ui/view.py @@ -8,9 +8,10 @@ import sys import time import traceback +from collections.abc import Sequence from functools import partial from itertools import groupby -from typing import TYPE_CHECKING, Callable, ClassVar, Dict, List, Optional, Sequence, Tuple +from typing import TYPE_CHECKING, Callable, ClassVar, Optional from ..components import ( VALID_ACTION_ROW_MESSAGE_COMPONENT_TYPES, @@ -50,8 +51,8 @@ def _component_to_item(component: ActionRowMessageComponent) -> Item: class _ViewWeights: __slots__ = ("weights",) - def __init__(self, children: List[Item]) -> None: - self.weights: List[int] = [0, 0, 0, 0, 0] + def __init__(self, children: list[Item]) -> None: + self.weights: list[int] = [0, 0, 0, 0, 0] key: Callable[[Item[View]], int] = lambda i: sys.maxsize if i.row is None else i.row children = sorted(children, key=key) @@ -116,10 +117,10 @@ class View: """ __discord_ui_view__: ClassVar[bool] = True - __view_children_items__: ClassVar[List[ItemCallbackType[Self, Item[Self]]]] = [] + __view_children_items__: ClassVar[list[ItemCallbackType[Self, Item[Self]]]] = [] def __init_subclass__(cls) -> None: - children: List[ItemCallbackType[Self, Item[Self]]] = [] + children: list[ItemCallbackType[Self, Item[Self]]] = [] for base in reversed(cls.__mro__): for member in base.__dict__.values(): if hasattr(member, "__discord_ui_model_type__"): @@ -133,7 +134,7 @@ def __init_subclass__(cls) -> None: def __init__(self, *, timeout: Optional[float] = 180.0) -> None: self.timeout = timeout - self.children: List[Item[Self]] = [] + self.children: list[Item[Self]] = [] for func in self.__view_children_items__: item: Item[Self] = func.__discord_ui_model_type__(**func.__discord_ui_model_kwargs__) item.callback = partial(func, self, item) # type: ignore @@ -169,12 +170,12 @@ async def __timeout_task_impl(self) -> None: # Wait N seconds to see if timeout data has been refreshed await asyncio.sleep(self.__timeout_expiry - now) - def to_components(self) -> List[ActionRowPayload]: + def to_components(self) -> list[ActionRowPayload]: def key(item: Item) -> int: return item._rendered_row or 0 children = sorted(self.children, key=key) - components: List[ActionRowPayload] = [] + components: list[ActionRowPayload] = [] for _, group in groupby(children, key=key): children = [item.to_component_dict() for item in group] if not children: @@ -391,15 +392,15 @@ def _dispatch_item(self, item: Item, interaction: MessageInteraction) -> None: self._scheduled_task(item, interaction), name=f"disnake-ui-view-dispatch-{self.id}" ) - def refresh(self, components: List[ActionRowComponent[ActionRowMessageComponent]]) -> None: + def refresh(self, components: list[ActionRowComponent[ActionRowMessageComponent]]) -> None: # TODO: this is pretty hacky at the moment, see https://github.com/DisnakeDev/disnake/commit/9384a72acb8c515b13a600592121357e165368da - old_state: Dict[Tuple[int, str], Item] = { + old_state: dict[tuple[int, str], Item] = { (item.type.value, item.custom_id): item # type: ignore for item in self.children if item.is_dispatchable() } - children: List[Item] = [] + children: list[Item] = [] for component in (c for row in components for c in row.children): older: Optional[Item] = None try: @@ -487,9 +488,9 @@ async def wait(self) -> bool: class ViewStore: def __init__(self, state: ConnectionState) -> None: # (component_type, message_id, custom_id): (View, Item) - self._views: Dict[Tuple[int, Optional[int], str], Tuple[View, Item]] = {} + self._views: dict[tuple[int, Optional[int], str], tuple[View, Item]] = {} # message_id: View - self._synced_message_views: Dict[int, View] = {} + self._synced_message_views: dict[int, View] = {} self._state: ConnectionState = state @property @@ -498,7 +499,7 @@ def persistent_views(self) -> Sequence[View]: return list(views.values()) def __verify_integrity(self) -> None: - to_remove: List[Tuple[int, Optional[int], str]] = [] + to_remove: list[tuple[int, Optional[int], str]] = [] for k, (view, _) in self._views.items(): if view.is_finished(): to_remove.append(k) diff --git a/disnake/user.py b/disnake/user.py index 807c6e5803..88372d3358 100644 --- a/disnake/user.py +++ b/disnake/user.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union +from typing import TYPE_CHECKING, Any, Optional, Union import disnake.abc @@ -468,7 +468,7 @@ async def edit( :class:`ClientUser` The newly edited client user. """ - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} if username is not MISSING: payload["username"] = username @@ -639,7 +639,7 @@ def dm_channel(self) -> Optional[DMChannel]: return self._state._get_private_channel_by_user(self.id) @property - def mutual_guilds(self) -> List[Guild]: + def mutual_guilds(self) -> list[Guild]: """:class:`list`\\[:class:`Guild`]: The guilds that the user shares with the client. .. note:: diff --git a/disnake/utils.py b/disnake/utils.py index 003f1f7ed0..cf34df9141 100644 --- a/disnake/utils.py +++ b/disnake/utils.py @@ -17,29 +17,19 @@ import warnings from base64 import b64encode from bisect import bisect_left +from collections.abc import AsyncIterator, Awaitable, Iterable, Iterator, Mapping, Sequence from inspect import getdoc as _getdoc, isawaitable as _isawaitable, signature as _signature from operator import attrgetter from typing import ( TYPE_CHECKING, Any, - AsyncIterator, - Awaitable, Callable, - Dict, ForwardRef, Generic, - Iterable, - Iterator, - List, Literal, - Mapping, NoReturn, Optional, Protocol, - Sequence, - Set, - Tuple, - Type, TypedDict, TypeVar, Union, @@ -173,12 +163,12 @@ def __init__(self, name: str, function: Callable[[T], T_co]) -> None: self.__doc__ = function.__doc__ @overload - def __get__(self, instance: None, owner: Type[Any]) -> Self: ... + def __get__(self, instance: None, owner: type[Any]) -> Self: ... @overload - def __get__(self, instance: T, owner: Type[Any]) -> T_co: ... + def __get__(self, instance: T, owner: type[Any]) -> T_co: ... - def __get__(self, instance: Optional[T], owner: Type[Any]) -> Any: + def __get__(self, instance: Optional[T], owner: type[Any]) -> Any: if instance is None: return self @@ -194,7 +184,7 @@ class classproperty(Generic[T_co]): def __init__(self, fget: Callable[[Any], T_co]) -> None: self.fget = fget - def __get__(self, instance: Optional[Any], owner: Type[Any]) -> T_co: + def __get__(self, instance: Optional[Any], owner: type[Any]) -> T_co: return self.fget(owner) def __set__(self, instance, value) -> NoReturn: @@ -505,7 +495,7 @@ def get(iterable: Iterable[T], **attrs: Any) -> Optional[T]: return None -def _unique(iterable: Iterable[T]) -> List[T]: +def _unique(iterable: Iterable[T]) -> list[T]: return list(dict.fromkeys(iterable)) @@ -633,7 +623,7 @@ async def async_all(gen: Iterable[Union[Awaitable[bool], bool]]) -> bool: return True -async def sane_wait_for(futures: Iterable[Awaitable[T]], *, timeout: float) -> Set[asyncio.Task[T]]: +async def sane_wait_for(futures: Iterable[Awaitable[T]], *, timeout: float) -> set[asyncio.Task[T]]: ensured = [asyncio.ensure_future(fut) for fut in futures] done, pending = await asyncio.wait(ensured, timeout=timeout, return_when=asyncio.ALL_COMPLETED) @@ -643,7 +633,7 @@ async def sane_wait_for(futures: Iterable[Awaitable[T]], *, timeout: float) -> S return done -def get_slots(cls: Type[Any]) -> Iterator[str]: +def get_slots(cls: type[Any]) -> Iterator[str]: for mro in reversed(cls.__mro__): slots = getattr(mro, "__slots__", []) if isinstance(slots, str): @@ -756,12 +746,12 @@ def resolve_invite(invite: Union[Invite, str], *, with_params: Literal[False] = @overload def resolve_invite( invite: Union[Invite, str], *, with_params: Literal[True] -) -> Tuple[str, Dict[str, str]]: ... +) -> tuple[str, dict[str, str]]: ... def resolve_invite( invite: Union[Invite, str], *, with_params: bool = False -) -> Union[str, Tuple[str, Dict[str, str]]]: +) -> Union[str, tuple[str, dict[str, str]]]: """Resolves an invite from a :class:`~disnake.Invite`, URL or code. Parameters @@ -957,7 +947,7 @@ class _DocstringParam(_DocstringLocalizationsMixin): class _ParsedDocstring(_DocstringLocalizationsMixin): description: str - params: Dict[str, _DocstringParam] + params: dict[str, _DocstringParam] def _count_left_spaces(string: str) -> int: @@ -969,7 +959,7 @@ def _count_left_spaces(string: str) -> int: return res -def _get_header_line(lines: List[str], header: str, underline: str) -> int: +def _get_header_line(lines: list[str], header: str, underline: str) -> int: underlining = len(header) * underline for i, line in enumerate(lines): if line.rstrip() == header and i + 1 < len(lines) and lines[i + 1].startswith(underlining): @@ -977,7 +967,7 @@ def _get_header_line(lines: List[str], header: str, underline: str) -> int: return len(lines) -def _get_next_header_line(lines: List[str], underline: str, start: int = 0) -> int: +def _get_next_header_line(lines: list[str], underline: str, start: int = 0) -> int: for idx, line in enumerate(lines[start:]): i = start + idx clean_line = line.rstrip() @@ -992,12 +982,12 @@ def _get_next_header_line(lines: List[str], underline: str, start: int = 0) -> i return len(lines) -def _get_description(lines: List[str]) -> str: +def _get_description(lines: list[str]) -> str: end = _get_next_header_line(lines, "-") return "\n".join(lines[:end]).strip() -def _extract_localization_key(desc: str) -> Tuple[str, Tuple[Optional[str], Optional[str]]]: +def _extract_localization_key(desc: str) -> tuple[str, tuple[Optional[str], Optional[str]]]: match = re.search(r"\{\{(.*?)\}\}", desc) if match: desc = desc.replace(match.group(0), "").strip() @@ -1006,15 +996,15 @@ def _extract_localization_key(desc: str) -> Tuple[str, Tuple[Optional[str], Opti return desc, (None, None) -def _get_option_desc(lines: List[str]) -> Dict[str, _DocstringParam]: +def _get_option_desc(lines: list[str]) -> dict[str, _DocstringParam]: start = _get_header_line(lines, "Parameters", "-") + 2 end = _get_next_header_line(lines, "-", start) if start >= len(lines): return {} # Read option descriptions - options: Dict[str, _DocstringParam] = {} + options: dict[str, _DocstringParam] = {} - def add_param(param: Optional[str], desc_lines: List[str], maybe_type: Optional[str]) -> None: + def add_param(param: Optional[str], desc_lines: list[str], maybe_type: Optional[str]) -> None: if param is None: return desc: Optional[str] = None @@ -1033,7 +1023,7 @@ def add_param(param: Optional[str], desc_lines: List[str], maybe_type: Optional[ "localization_key_desc": loc_key_desc, } - desc_lines: List[str] = [] + desc_lines: list[str] = [] param: Optional[str] = None maybe_type: Optional[str] = None for line in lines[start:end]: @@ -1079,7 +1069,7 @@ def parse_docstring(func: Callable[..., Any]) -> _ParsedDocstring: # Chunkers -def _chunk(iterator: Iterator[T], max_size: int) -> Iterator[List[T]]: +def _chunk(iterator: Iterator[T], max_size: int) -> Iterator[list[T]]: ret = [] n = 0 for item in iterator: @@ -1093,7 +1083,7 @@ def _chunk(iterator: Iterator[T], max_size: int) -> Iterator[List[T]]: yield ret -async def _achunk(iterator: AsyncIterator[T], max_size: int) -> AsyncIterator[List[T]]: +async def _achunk(iterator: AsyncIterator[T], max_size: int) -> AsyncIterator[list[T]]: ret = [] n = 0 async for item in iterator: @@ -1108,14 +1098,14 @@ async def _achunk(iterator: AsyncIterator[T], max_size: int) -> AsyncIterator[Li @overload -def as_chunks(iterator: Iterator[T], max_size: int) -> Iterator[List[T]]: ... +def as_chunks(iterator: Iterator[T], max_size: int) -> Iterator[list[T]]: ... @overload -def as_chunks(iterator: AsyncIterator[T], max_size: int) -> AsyncIterator[List[T]]: ... +def as_chunks(iterator: AsyncIterator[T], max_size: int) -> AsyncIterator[list[T]]: ... -def as_chunks(iterator: _Iter[T], max_size: int) -> _Iter[List[T]]: +def as_chunks(iterator: _Iter[T], max_size: int) -> _Iter[list[T]]: """A helper function that collects an iterator into chunks of a given size. .. versionadded:: 2.0 @@ -1154,7 +1144,7 @@ def as_chunks(iterator: _Iter[T], max_size: int) -> _Iter[List[T]]: UnionType = object() -def flatten_literal_params(parameters: Iterable[Any]) -> Tuple[Any, ...]: +def flatten_literal_params(parameters: Iterable[Any]) -> tuple[Any, ...]: params = [] for p in parameters: if get_origin(p) is Literal: @@ -1164,13 +1154,13 @@ def flatten_literal_params(parameters: Iterable[Any]) -> Tuple[Any, ...]: return tuple(params) -def normalise_optional_params(parameters: Iterable[Any]) -> Tuple[Any, ...]: +def normalise_optional_params(parameters: Iterable[Any]) -> tuple[Any, ...]: none_cls = type(None) return (*tuple(p for p in parameters if p is not none_cls), none_cls) def _resolve_typealiastype( - tp: Any, globals: Dict[str, Any], locals: Dict[str, Any], cache: Dict[str, Any] + tp: Any, globals: dict[str, Any], locals: dict[str, Any], cache: dict[str, Any] ) -> Any: # Use __module__ to get the (global) namespace in which the type alias was defined. if mod := sys.modules.get(tp.__module__): @@ -1189,9 +1179,9 @@ def _resolve_typealiastype( # FIXME: this should be split up into smaller functions for clarity and easier maintenance def evaluate_annotation( tp: Any, - globals: Dict[str, Any], - locals: Dict[str, Any], - cache: Dict[str, Any], + globals: dict[str, Any], + locals: dict[str, Any], + cache: dict[str, Any], *, implicit_str: bool = True, ) -> Any: @@ -1274,9 +1264,9 @@ def evaluate_annotation( def resolve_annotation( annotation: Any, - globalns: Dict[str, Any], - localns: Optional[Dict[str, Any]], - cache: Optional[Dict[str, Any]], + globalns: dict[str, Any], + localns: Optional[dict[str, Any]], + cache: Optional[dict[str, Any]], ) -> Any: if annotation is None: return type(None) @@ -1300,7 +1290,7 @@ def unwrap_function(function: Callable[..., Any]) -> Callable[..., Any]: return function -def _get_function_globals(function: Callable[..., Any]) -> Dict[str, Any]: +def _get_function_globals(function: Callable[..., Any]) -> dict[str, Any]: unwrap = unwrap_function(function) try: return unwrap.__globals__ @@ -1313,16 +1303,16 @@ def _get_function_globals(function: Callable[..., Any]) -> Dict[str, Any]: def get_signature_parameters( function: Callable[..., Any], - globalns: Optional[Dict[str, Any]] = None, + globalns: Optional[dict[str, Any]] = None, *, skip_standard_params: bool = False, -) -> Dict[str, inspect.Parameter]: +) -> dict[str, inspect.Parameter]: # if no globalns provided, unwrap (where needed) and get global namespace from there if globalns is None: globalns = _get_function_globals(function) - params: Dict[str, inspect.Parameter] = {} - cache: Dict[str, Any] = {} + params: dict[str, inspect.Parameter] = {} + cache: dict[str, Any] = {} signature = inspect.signature(function) iterator = iter(signature.parameters.items()) @@ -1538,7 +1528,7 @@ def as_valid_locale(locale: str) -> Optional[str]: return None -def humanize_list(values: List[str], combine: str) -> str: +def humanize_list(values: list[str], combine: str) -> str: if len(values) > 2: return f"{', '.join(values[:-1])}, {combine} {values[-1]}" elif len(values) == 0: diff --git a/disnake/voice_client.py b/disnake/voice_client.py index 2a63c457a2..d815625daf 100644 --- a/disnake/voice_client.py +++ b/disnake/voice_client.py @@ -22,7 +22,7 @@ import socket import struct import threading -from typing import TYPE_CHECKING, Any, Callable, List, Optional, Tuple +from typing import TYPE_CHECKING, Any, Callable, Optional from . import opus, utils from .backoff import ExponentialBackoff @@ -193,7 +193,7 @@ class VoiceClient(VoiceProtocol): endpoint_ip: str voice_port: int - secret_key: List[int] + secret_key: list[int] ssrc: int ip: str port: int @@ -229,7 +229,7 @@ def __init__(self, client: Client, channel: abc.Connectable) -> None: self.ws: DiscordVoiceWebSocket = MISSING warn_nacl = not has_nacl - supported_modes: Tuple[SupportedModes, ...] = ("aead_xchacha20_poly1305_rtpsize",) + supported_modes: tuple[SupportedModes, ...] = ("aead_xchacha20_poly1305_rtpsize",) @property def guild(self) -> Guild: @@ -283,10 +283,7 @@ async def on_voice_server_update(self, data: VoiceServerUpdateEvent) -> None: ) return - self.endpoint = endpoint - if self.endpoint.startswith("wss://"): - # Just in case, strip it off since we're going to add it later - self.endpoint = self.endpoint[6:] + self.endpoint = endpoint.removeprefix("wss://") # This gets set later self.endpoint_ip = MISSING @@ -518,7 +515,7 @@ def _get_voice_packet(self, data: bytes) -> bytes: encrypt_packet = getattr(self, f"_encrypt_{self.mode}") return encrypt_packet(header, data) - def _get_nonce(self, pad: int) -> Tuple[bytes, bytes]: + def _get_nonce(self, pad: int) -> tuple[bytes, bytes]: # returns (nonce, padded_nonce). # n.b. all currently implemented modes use the same nonce size (192 bits / 24 bytes) nonce = struct.pack(">I", self._lite_nonce) diff --git a/disnake/webhook/async_.py b/disnake/webhook/async_.py index c407554d6c..9f346f6403 100644 --- a/disnake/webhook/async_.py +++ b/disnake/webhook/async_.py @@ -5,21 +5,17 @@ import asyncio import logging import re +from collections.abc import Sequence from contextvars import ContextVar from errno import ECONNRESET from typing import ( TYPE_CHECKING, Any, - Dict, Generic, - List, Literal, NamedTuple, NoReturn, Optional, - Sequence, - Tuple, - Type, TypeVar, Union, overload, @@ -90,7 +86,7 @@ def delay_by(self, delta: float) -> None: async def __aexit__( self, - type: Optional[Type[BaseException]], + type: Optional[type[BaseException]], value: Optional[BaseException], traceback: Optional[TracebackType], ) -> None: @@ -101,21 +97,21 @@ async def __aexit__( class AsyncWebhookAdapter: def __init__(self) -> None: - self._locks: Dict[Any, asyncio.Lock] = {} + self._locks: dict[Any, asyncio.Lock] = {} async def request( self, route: Route, session: aiohttp.ClientSession, *, - payload: Optional[Dict[str, Any]] = None, - multipart: Optional[List[Dict[str, Any]]] = None, - files: Optional[List[File]] = None, + payload: Optional[dict[str, Any]] = None, + multipart: Optional[list[dict[str, Any]]] = None, + files: Optional[list[File]] = None, reason: Optional[str] = None, auth_token: Optional[str] = None, - params: Optional[Dict[str, Any]] = None, + params: Optional[dict[str, Any]] = None, ) -> Any: - headers: Dict[str, str] = {} + headers: dict[str, str] = {} files = files or [] to_send: Optional[Union[str, aiohttp.FormData]] = None bucket = (route.webhook_id, route.webhook_token) @@ -136,7 +132,7 @@ async def request( headers["X-Audit-Log-Reason"] = urlquote(reason, safe="/ ") response: Optional[aiohttp.ClientResponse] = None - data: Optional[Union[Dict[str, Any], str]] = None + data: Optional[Union[dict[str, Any], str]] = None method = route.method url = route.url webhook_id = route.webhook_id @@ -258,7 +254,7 @@ def edit_webhook( self, webhook_id: int, token: str, - payload: Dict[str, Any], + payload: dict[str, Any], *, session: aiohttp.ClientSession, reason: Optional[str] = None, @@ -270,7 +266,7 @@ def edit_webhook_with_token( self, webhook_id: int, token: str, - payload: Dict[str, Any], + payload: dict[str, Any], *, session: aiohttp.ClientSession, reason: Optional[str] = None, @@ -289,9 +285,9 @@ def execute_webhook( token: str, *, session: aiohttp.ClientSession, - payload: Optional[Dict[str, Any]] = None, - multipart: Optional[List[Dict[str, Any]]] = None, - files: Optional[List[File]] = None, + payload: Optional[dict[str, Any]] = None, + multipart: Optional[list[dict[str, Any]]] = None, + files: Optional[list[File]] = None, thread_id: Optional[int] = None, wait: bool = False, with_components: bool = True, @@ -319,7 +315,7 @@ def get_webhook_message( session: aiohttp.ClientSession, thread_id: Optional[int] = None, ) -> Response[MessagePayload]: - params: Dict[str, Any] = {} + params: dict[str, Any] = {} if thread_id is not None: params["thread_id"] = thread_id @@ -339,12 +335,12 @@ def edit_webhook_message( message_id: int, *, session: aiohttp.ClientSession, - payload: Optional[Dict[str, Any]] = None, - multipart: Optional[List[Dict[str, Any]]] = None, - files: Optional[List[File]] = None, + payload: Optional[dict[str, Any]] = None, + multipart: Optional[list[dict[str, Any]]] = None, + files: Optional[list[File]] = None, thread_id: Optional[int] = None, ) -> Response[MessagePayload]: - params: Dict[str, Any] = {} + params: dict[str, Any] = {} if thread_id is not None: params["thread_id"] = thread_id @@ -368,7 +364,7 @@ def delete_webhook_message( session: aiohttp.ClientSession, thread_id: Optional[int] = None, ) -> Response[None]: - params: Dict[str, Any] = {} + params: dict[str, Any] = {} if thread_id is not None: params["thread_id"] = thread_id @@ -413,8 +409,8 @@ def create_interaction_response( *, session: aiohttp.ClientSession, type: int, - data: Optional[Dict[str, Any]] = None, - files: Optional[List[File]] = None, + data: Optional[dict[str, Any]] = None, + files: Optional[list[File]] = None, ) -> Response[None]: route = Route( "POST", @@ -423,7 +419,7 @@ def create_interaction_response( webhook_token=token, ) - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "type": type, } @@ -458,9 +454,9 @@ def edit_original_interaction_response( token: str, *, session: aiohttp.ClientSession, - payload: Optional[Dict[str, Any]] = None, - multipart: Optional[List[Dict[str, Any]]] = None, - files: Optional[List[File]] = None, + payload: Optional[dict[str, Any]] = None, + multipart: Optional[list[dict[str, Any]]] = None, + files: Optional[list[File]] = None, ) -> Response[MessagePayload]: r = Route( "PATCH", @@ -487,14 +483,14 @@ def delete_original_interaction_response( class DictPayloadParameters(NamedTuple): - payload: Dict[str, Any] - files: Optional[List[File]] + payload: dict[str, Any] + files: Optional[list[File]] class PayloadParameters(NamedTuple): - payload: Optional[Dict[str, Any]] - multipart: Optional[List[Dict[str, Any]]] - files: Optional[List[File]] + payload: Optional[dict[str, Any]] + multipart: Optional[list[dict[str, Any]]] + files: Optional[list[File]] def handle_message_parameters_dict( @@ -507,10 +503,10 @@ def handle_message_parameters_dict( suppress_embeds: Optional[bool] = MISSING, flags: MessageFlags = MISSING, file: File = MISSING, - files: List[File] = MISSING, - attachments: Optional[List[Attachment]] = MISSING, + files: list[File] = MISSING, + attachments: Optional[list[Attachment]] = MISSING, embed: Optional[Embed] = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, view: Optional[View] = MISSING, components: Optional[MessageComponents] = MISSING, allowed_mentions: Optional[AllowedMentions] = MISSING, @@ -619,10 +615,10 @@ def handle_message_parameters( suppress_embeds: Optional[bool] = MISSING, flags: MessageFlags = MISSING, file: File = MISSING, - files: List[File] = MISSING, - attachments: Optional[List[Attachment]] = MISSING, + files: list[File] = MISSING, + attachments: Optional[list[Attachment]] = MISSING, embed: Optional[Embed] = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, view: Optional[View] = MISSING, components: Optional[MessageComponents] = MISSING, allowed_mentions: Optional[AllowedMentions] = MISSING, @@ -808,10 +804,10 @@ async def edit( self, content: Optional[str] = MISSING, embed: Optional[Embed] = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, file: File = MISSING, - files: List[File] = MISSING, - attachments: Optional[List[Attachment]] = MISSING, + files: list[File] = MISSING, + attachments: Optional[list[Attachment]] = MISSING, view: Optional[View] = MISSING, components: Optional[MessageComponents] = MISSING, flags: MessageFlags = MISSING, @@ -970,7 +966,7 @@ async def inner_call(delay: float = delay) -> None: class BaseWebhook(Hashable): - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "id", "type", "guild_id", @@ -1171,7 +1167,7 @@ async def foo(): .. versionadded:: 2.6 """ - __slots__: Tuple[str, ...] = ("session",) + __slots__: tuple[str, ...] = ("session",) def __init__( self, @@ -1275,7 +1271,7 @@ def from_url( msg = "Invalid webhook URL given." raise ValueError(msg) - data: Dict[str, Any] = m.groupdict() + data: dict[str, Any] = m.groupdict() data["type"] = 1 return cls(data, session, token=bot_token) # type: ignore @@ -1466,7 +1462,7 @@ async def edit( msg = "This webhook does not have a token associated with it" raise WebhookTokenMissing(msg) - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} if name is not MISSING: payload["name"] = str(name) if name is not None else None @@ -1545,9 +1541,9 @@ async def send( suppress_embeds: bool = ..., flags: MessageFlags = ..., file: File = ..., - files: List[File] = ..., + files: list[File] = ..., embed: Embed = ..., - embeds: List[Embed] = ..., + embeds: list[Embed] = ..., allowed_mentions: AllowedMentions = ..., view: View = ..., components: MessageComponents = ..., @@ -1571,9 +1567,9 @@ async def send( suppress_embeds: bool = ..., flags: MessageFlags = ..., file: File = ..., - files: List[File] = ..., + files: list[File] = ..., embed: Embed = ..., - embeds: List[Embed] = ..., + embeds: list[Embed] = ..., allowed_mentions: AllowedMentions = ..., view: View = ..., components: MessageComponents = ..., @@ -1596,9 +1592,9 @@ async def send( suppress_embeds: bool = MISSING, flags: MessageFlags = MISSING, file: File = MISSING, - files: List[File] = MISSING, + files: list[File] = MISSING, embed: Embed = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, allowed_mentions: AllowedMentions = MISSING, view: View = MISSING, components: MessageComponents = MISSING, @@ -1916,10 +1912,10 @@ async def edit_message( *, content: Optional[str] = MISSING, embed: Optional[Embed] = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, file: File = MISSING, - files: List[File] = MISSING, - attachments: Optional[List[Attachment]] = MISSING, + files: list[File] = MISSING, + attachments: Optional[list[Attachment]] = MISSING, view: Optional[View] = MISSING, components: Optional[MessageComponents] = MISSING, flags: MessageFlags = MISSING, diff --git a/disnake/webhook/sync.py b/disnake/webhook/sync.py index d5753f0aa9..53ee5b1166 100644 --- a/disnake/webhook/sync.py +++ b/disnake/webhook/sync.py @@ -12,17 +12,13 @@ import re import threading import time +from collections.abc import Sequence from errno import ECONNRESET from typing import ( TYPE_CHECKING, Any, - Dict, - List, Literal, Optional, - Sequence, - Tuple, - Type, Union, overload, ) @@ -79,7 +75,7 @@ def delay_by(self, delta: float) -> None: def __exit__( self, - type: Optional[Type[BaseException]], + type: Optional[type[BaseException]], value: Optional[BaseException], traceback: Optional[TracebackType], ) -> None: @@ -90,23 +86,23 @@ def __exit__( class WebhookAdapter: def __init__(self) -> None: - self._locks: Dict[Any, threading.Lock] = {} + self._locks: dict[Any, threading.Lock] = {} def request( self, route: Route, session: Session, *, - payload: Optional[Dict[str, Any]] = None, - multipart: Optional[List[Dict[str, Any]]] = None, - files: Optional[List[File]] = None, + payload: Optional[dict[str, Any]] = None, + multipart: Optional[list[dict[str, Any]]] = None, + files: Optional[list[File]] = None, reason: Optional[str] = None, auth_token: Optional[str] = None, - params: Optional[Dict[str, Any]] = None, + params: Optional[dict[str, Any]] = None, ) -> Any: - headers: Dict[str, str] = {} + headers: dict[str, str] = {} files = files or [] - to_send: Optional[Union[str, Dict[str, Any]]] = None + to_send: Optional[Union[str, dict[str, Any]]] = None bucket = (route.webhook_id, route.webhook_token) try: @@ -125,8 +121,8 @@ def request( headers["X-Audit-Log-Reason"] = urlquote(reason, safe="/ ") response: Optional[Response] = None - data: Optional[Union[Dict[str, Any], str]] = None - file_data: Optional[Dict[str, Any]] = None + data: Optional[Union[dict[str, Any], str]] = None + file_data: Optional[dict[str, Any]] = None method = route.method url = route.url webhook_id = route.webhook_id @@ -248,7 +244,7 @@ def edit_webhook( self, webhook_id: int, token: str, - payload: Dict[str, Any], + payload: dict[str, Any], *, session: Session, reason: Optional[str] = None, @@ -260,7 +256,7 @@ def edit_webhook_with_token( self, webhook_id: int, token: str, - payload: Dict[str, Any], + payload: dict[str, Any], *, session: Session, reason: Optional[str] = None, @@ -280,9 +276,9 @@ def execute_webhook( token: str, *, session: Session, - payload: Optional[Dict[str, Any]] = None, - multipart: Optional[List[Dict[str, Any]]] = None, - files: Optional[List[File]] = None, + payload: Optional[dict[str, Any]] = None, + multipart: Optional[list[dict[str, Any]]] = None, + files: Optional[list[File]] = None, thread_id: Optional[int] = None, wait: bool = False, ) -> MessagePayload: ... @@ -294,9 +290,9 @@ def execute_webhook( token: str, *, session: Session, - payload: Optional[Dict[str, Any]] = None, - multipart: Optional[List[Dict[str, Any]]] = None, - files: Optional[List[File]] = None, + payload: Optional[dict[str, Any]] = None, + multipart: Optional[list[dict[str, Any]]] = None, + files: Optional[list[File]] = None, thread_id: Optional[int] = None, wait: bool = False, ) -> None: ... @@ -307,9 +303,9 @@ def execute_webhook( token: str, *, session: Session, - payload: Optional[Dict[str, Any]] = None, - multipart: Optional[List[Dict[str, Any]]] = None, - files: Optional[List[File]] = None, + payload: Optional[dict[str, Any]] = None, + multipart: Optional[list[dict[str, Any]]] = None, + files: Optional[list[File]] = None, thread_id: Optional[int] = None, wait: bool = False, ) -> Optional[MessagePayload]: @@ -336,7 +332,7 @@ def get_webhook_message( session: Session, thread_id: Optional[int] = None, ) -> MessagePayload: - params: Dict[str, Any] = {} + params: dict[str, Any] = {} if thread_id is not None: params["thread_id"] = thread_id @@ -356,12 +352,12 @@ def edit_webhook_message( message_id: int, *, session: Session, - payload: Optional[Dict[str, Any]] = None, - multipart: Optional[List[Dict[str, Any]]] = None, - files: Optional[List[File]] = None, + payload: Optional[dict[str, Any]] = None, + multipart: Optional[list[dict[str, Any]]] = None, + files: Optional[list[File]] = None, thread_id: Optional[int] = None, ) -> MessagePayload: - params: Dict[str, Any] = {} + params: dict[str, Any] = {} if thread_id is not None: params["thread_id"] = thread_id @@ -385,7 +381,7 @@ def delete_webhook_message( session: Session, thread_id: Optional[int] = None, ) -> None: - params: Dict[str, Any] = {} + params: dict[str, Any] = {} if thread_id is not None: params["thread_id"] = thread_id @@ -455,10 +451,10 @@ def edit( self, content: Optional[str] = MISSING, embed: Optional[Embed] = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, file: File = MISSING, - files: List[File] = MISSING, - attachments: Optional[List[Attachment]] = MISSING, + files: list[File] = MISSING, + attachments: Optional[list[Attachment]] = MISSING, allowed_mentions: Optional[AllowedMentions] = None, ) -> SyncWebhookMessage: """Edits the message. @@ -630,7 +626,7 @@ class SyncWebhook(BaseWebhook): .. versionadded:: 2.6 """ - __slots__: Tuple[str, ...] = ("session",) + __slots__: tuple[str, ...] = ("session",) def __init__( self, data: WebhookPayload, session: Session, token: Optional[str] = None, state=None @@ -729,7 +725,7 @@ def from_url( msg = "Invalid webhook URL given." raise ValueError(msg) - data: Dict[str, Any] = m.groupdict() + data: dict[str, Any] = m.groupdict() data["type"] = 1 import requests @@ -879,7 +875,7 @@ def edit( msg = "This webhook does not have a token associated with it" raise WebhookTokenMissing(msg) - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} if name is not MISSING: payload["name"] = str(name) if name is not None else None @@ -941,9 +937,9 @@ def send( avatar_url: Any = ..., tts: bool = ..., file: File = ..., - files: List[File] = ..., + files: list[File] = ..., embed: Embed = ..., - embeds: List[Embed] = ..., + embeds: list[Embed] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., allowed_mentions: AllowedMentions = ..., @@ -962,9 +958,9 @@ def send( avatar_url: Any = ..., tts: bool = ..., file: File = ..., - files: List[File] = ..., + files: list[File] = ..., embed: Embed = ..., - embeds: List[Embed] = ..., + embeds: list[Embed] = ..., suppress_embeds: bool = ..., flags: MessageFlags = ..., allowed_mentions: AllowedMentions = ..., @@ -982,9 +978,9 @@ def send( avatar_url: Any = MISSING, tts: bool = False, file: File = MISSING, - files: List[File] = MISSING, + files: list[File] = MISSING, embed: Embed = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, suppress_embeds: bool = MISSING, flags: MessageFlags = MISSING, allowed_mentions: AllowedMentions = MISSING, @@ -1208,10 +1204,10 @@ def edit_message( *, content: Optional[str] = MISSING, embed: Optional[Embed] = MISSING, - embeds: List[Embed] = MISSING, + embeds: list[Embed] = MISSING, file: File = MISSING, - files: List[File] = MISSING, - attachments: Optional[List[Attachment]] = MISSING, + files: list[File] = MISSING, + attachments: Optional[list[Attachment]] = MISSING, allowed_mentions: Optional[AllowedMentions] = None, thread: Optional[Snowflake] = None, ) -> SyncWebhookMessage: diff --git a/disnake/welcome_screen.py b/disnake/welcome_screen.py index a212b6a860..295f94b94a 100644 --- a/disnake/welcome_screen.py +++ b/disnake/welcome_screen.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, List, Optional, Union +from typing import TYPE_CHECKING, Optional, Union from . import utils from .partial_emoji import PartialEmoji, _EmojiTag @@ -126,7 +126,7 @@ def __init__( self._state = state self._guild = guild self.description: Optional[str] = data.get("description") - self.channels: List[WelcomeScreenChannel] = [ + self.channels: list[WelcomeScreenChannel] = [ WelcomeScreenChannel._from_data(data=channel, state=state) for channel in data["welcome_channels"] ] @@ -146,7 +146,7 @@ async def edit( *, enabled: bool = MISSING, description: Optional[str] = MISSING, - channels: Optional[List[WelcomeScreenChannel]] = MISSING, + channels: Optional[list[WelcomeScreenChannel]] = MISSING, reason: Optional[str] = None, ) -> WelcomeScreen: """|coro| diff --git a/disnake/widget.py b/disnake/widget.py index b6041991b4..89ed6a1e2c 100644 --- a/disnake/widget.py +++ b/disnake/widget.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union +from typing import TYPE_CHECKING, Any, Optional, Union from .activity import BaseActivity, Spotify, create_activity from .asset import Asset @@ -309,14 +309,14 @@ def __init__(self, *, state: ConnectionState, data: WidgetPayload) -> None: self.id: int = int(data["id"]) self.presence_count: int = data["presence_count"] - self.channels: List[WidgetChannel] = [] + self.channels: list[WidgetChannel] = [] for channel in data.get("channels", []): _id = int(channel["id"]) self.channels.append( WidgetChannel(id=_id, name=channel["name"], position=channel["position"]) ) - self.members: List[WidgetMember] = [] + self.members: list[WidgetMember] = [] channels = {channel.id: channel for channel in self.channels} for member in data.get("members", []): connected_channel = _get_as_snowflake(member, "channel_id") @@ -420,7 +420,7 @@ async def edit( HTTPException Editing the widget failed. """ - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} if enabled is not MISSING: payload["enabled"] = enabled if channel is not MISSING: diff --git a/docs/conf.py b/docs/conf.py index 44074457ec..a3f14ff974 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -18,7 +18,7 @@ import re import subprocess # noqa: TID251 import sys -from typing import Any, Dict, Optional +from typing import Any, Optional from sphinx.application import Sphinx @@ -208,7 +208,7 @@ def git(*args: str) -> str: _disnake_module_path = os.path.dirname(_spec.origin) -def linkcode_resolve(domain: str, info: Dict[str, Any]) -> Optional[str]: +def linkcode_resolve(domain: str, info: dict[str, Any]) -> Optional[str]: if domain != "py": return None diff --git a/docs/extensions/attributetable.py b/docs/extensions/attributetable.py index 030343ea2d..8ccde997ba 100644 --- a/docs/extensions/attributetable.py +++ b/docs/extensions/attributetable.py @@ -5,7 +5,7 @@ import inspect import re from collections import defaultdict -from typing import TYPE_CHECKING, ClassVar, DefaultDict, Dict, List, NamedTuple, Optional, Tuple +from typing import TYPE_CHECKING, ClassVar, NamedTuple, Optional from docutils import nodes from sphinx import addnodes @@ -104,7 +104,7 @@ class PyAttributeTable(SphinxDirective): final_argument_whitespace = False option_spec: ClassVar[OptionSpec] = {} - def parse_name(self, content: str) -> Tuple[str, Optional[str]]: + def parse_name(self, content: str) -> tuple[str, Optional[str]]: match = _name_parser_regex.match(content) path, name = match.groups() if match else (None, None) if path: @@ -119,7 +119,7 @@ def parse_name(self, content: str) -> Tuple[str, Optional[str]]: return modulename, name - def run(self) -> List[nodes.Node]: + def run(self) -> list[nodes.Node]: """If you're curious on the HTML this is meant to generate:
@@ -156,10 +156,10 @@ def run(self) -> List[nodes.Node]: return [node] -def build_lookup_table(env: BuildEnvironment) -> Dict[str, List[str]]: +def build_lookup_table(env: BuildEnvironment) -> dict[str, list[str]]: # Given an environment, load up a lookup table of # full-class-name: objects - result: DefaultDict[str, List[str]] = defaultdict(list) + result: defaultdict[str, list[str]] = defaultdict(list) domain = env.domains["py"] ignored = { @@ -211,12 +211,12 @@ def process_attributetable(app: Sphinx, doctree: nodes.document, docname: str) - def get_class_results( - lookup: Dict[str, List[str]], modulename: str, name: str, fullname: str -) -> Dict[str, List[TableElement]]: + lookup: dict[str, list[str]], modulename: str, name: str, fullname: str +) -> dict[str, list[TableElement]]: module = importlib.import_module(modulename) cls = getattr(module, name) - groups: Dict[str, List[TableElement]] = { + groups: dict[str, list[TableElement]] = { _("Attributes"): [], _("Methods"): [], } @@ -265,7 +265,7 @@ def get_class_results( return groups -def class_results_to_node(key: str, elements: List[TableElement]) -> attributetablecolumn: +def class_results_to_node(key: str, elements: list[TableElement]) -> attributetablecolumn: title = attributetabletitle(key, key) ul = nodes.bullet_list("") ul["classes"].append("py-attribute-table-list") diff --git a/docs/extensions/collapse.py b/docs/extensions/collapse.py index a37bdd3780..037d0b7e2b 100644 --- a/docs/extensions/collapse.py +++ b/docs/extensions/collapse.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT from __future__ import annotations -from typing import TYPE_CHECKING, ClassVar, List +from typing import TYPE_CHECKING, ClassVar from docutils import nodes from docutils.parsers.rst import Directive, directives @@ -36,7 +36,7 @@ class CollapseDirective(Directive): option_spec: ClassVar[OptionSpec] = {"open": directives.flag} - def run(self) -> List[collapse]: + def run(self) -> list[collapse]: self.assert_has_content() node = collapse( "\n".join(self.content), diff --git a/docs/extensions/exception_hierarchy.py b/docs/extensions/exception_hierarchy.py index 49ed16f539..586059e9be 100644 --- a/docs/extensions/exception_hierarchy.py +++ b/docs/extensions/exception_hierarchy.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT from __future__ import annotations -from typing import TYPE_CHECKING, List +from typing import TYPE_CHECKING from docutils import nodes from docutils.parsers.rst import Directive @@ -28,7 +28,7 @@ def depart_exception_hierarchy_node(self: HTMLTranslator, node: nodes.Element) - class ExceptionHierarchyDirective(Directive): has_content = True - def run(self) -> List[exception_hierarchy]: + def run(self) -> list[exception_hierarchy]: self.assert_has_content() node = exception_hierarchy("\n".join(self.content)) self.state.nested_parse(self.content, self.content_offset, node) diff --git a/docs/extensions/fulltoc.py b/docs/extensions/fulltoc.py index 62499afd4a..8923f7b424 100644 --- a/docs/extensions/fulltoc.py +++ b/docs/extensions/fulltoc.py @@ -29,7 +29,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, List, cast +from typing import TYPE_CHECKING, cast from docutils import nodes from sphinx import addnodes @@ -112,7 +112,7 @@ def build_full_toctree( """ env: BuildEnvironment = builder.env doctree = env.get_doctree(index) - toctrees: List[nodes.Element] = [] + toctrees: list[nodes.Element] = [] for toctreenode in doctree.traverse(addnodes.toctree): toctree = env.resolve_toctree( docname, diff --git a/docs/extensions/redirects.py b/docs/extensions/redirects.py index 46114dd743..b008b25db2 100644 --- a/docs/extensions/redirects.py +++ b/docs/extensions/redirects.py @@ -3,7 +3,7 @@ import json from pathlib import Path -from typing import TYPE_CHECKING, Dict +from typing import TYPE_CHECKING from sphinx.application import Sphinx from sphinx.util.fileutil import copy_asset_file @@ -14,10 +14,10 @@ SCRIPT_PATH = "_templates/api_redirect.js_t" -def collect_redirects(app: Sphinx) -> Dict[str, str]: +def collect_redirects(app: Sphinx) -> dict[str, str]: # mapping of html node id (i.e., thing after "#" in URLs) to the correct page name # e.g, api.html#disnake.Thread => api/channels.html - mapping: Dict[str, str] = {} + mapping: dict[str, str] = {} # see https://www.sphinx-doc.org/en/master/extdev/domainapi.html#sphinx.domains.Domain.get_objects domain = app.env.domains["py"] diff --git a/docs/extensions/resourcelinks.py b/docs/extensions/resourcelinks.py index d93f6f2715..f78e6d2892 100644 --- a/docs/extensions/resourcelinks.py +++ b/docs/extensions/resourcelinks.py @@ -4,7 +4,7 @@ # Licensed under BSD. from __future__ import annotations -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple +from typing import TYPE_CHECKING, Any, Optional from docutils import nodes, utils from sphinx.util.nodes import split_explicit_title @@ -18,16 +18,16 @@ from ._types import SphinxExtensionMeta -def make_link_role(resource_links: Dict[str, str]) -> RoleFunction: +def make_link_role(resource_links: dict[str, str]) -> RoleFunction: def role( typ: str, rawtext: str, text: str, lineno: int, inliner: Inliner, - options: Optional[Dict[str, Any]] = None, - content: Optional[List[str]] = None, - ) -> Tuple[List[Node], List[system_message]]: + options: Optional[dict[str, Any]] = None, + content: Optional[list[str]] = None, + ) -> tuple[list[Node], list[system_message]]: text = utils.unescape(text) has_explicit_title, title, key = split_explicit_title(text) full_url = resource_links[key] diff --git a/examples/basic_voice.py b/examples/basic_voice.py index 0ff34a7b5f..4664946515 100644 --- a/examples/basic_voice.py +++ b/examples/basic_voice.py @@ -9,7 +9,7 @@ import asyncio import os -from typing import Any, Dict, Optional +from typing import Any, Optional import disnake import youtube_dl # type: ignore @@ -37,7 +37,7 @@ class YTDLSource(disnake.PCMVolumeTransformer): - def __init__(self, source: disnake.AudioSource, *, data: Dict[str, Any], volume: float = 0.5): + def __init__(self, source: disnake.AudioSource, *, data: dict[str, Any], volume: float = 0.5): super().__init__(source, volume) self.title = data.get("title") diff --git a/examples/interactions/autocomplete.py b/examples/interactions/autocomplete.py index 020313bdf5..629321c08c 100644 --- a/examples/interactions/autocomplete.py +++ b/examples/interactions/autocomplete.py @@ -3,7 +3,6 @@ """An example showcasing the two ways of adding autocompletion to slash command options.""" import os -from typing import List import disnake from disnake.ext import commands @@ -22,7 +21,7 @@ # with up to 25 elements. -async def autocomplete_langs(inter, string: str) -> List[str]: +async def autocomplete_langs(inter, string: str) -> list[str]: string = string.lower() return [lang for lang in LANGUAGES if string in lang.lower()] diff --git a/examples/views/button/paginator.py b/examples/views/button/paginator.py index a6c929cc00..31301f26dc 100644 --- a/examples/views/button/paginator.py +++ b/examples/views/button/paginator.py @@ -3,7 +3,6 @@ """A simple paginator example using views and buttons.""" import os -from typing import List import disnake from disnake.ext import commands @@ -11,7 +10,7 @@ # Defines a simple paginator of buttons for the embed. class Menu(disnake.ui.View): - def __init__(self, embeds: List[disnake.Embed]): + def __init__(self, embeds: list[disnake.Embed]): super().__init__(timeout=None) self.embeds = embeds self.index = 0 diff --git a/examples/views/tic_tac_toe.py b/examples/views/tic_tac_toe.py index 32c0c222fb..937234d1a5 100644 --- a/examples/views/tic_tac_toe.py +++ b/examples/views/tic_tac_toe.py @@ -4,7 +4,7 @@ import os from enum import IntEnum -from typing import List, Optional +from typing import Optional import disnake from disnake.ext import commands @@ -76,7 +76,7 @@ async def callback(self, inter: disnake.MessageInteraction): class TicTacToe(disnake.ui.View): # This tells the IDE or linter that all our children will be TicTacToeButtons # (this is not required) - children: List[TicTacToeButton] + children: list[TicTacToeButton] def __init__(self): super().__init__() @@ -84,7 +84,7 @@ def __init__(self): self.current_player: Player = Player.X u = Player.unknown - self.board: List[List[Player]] = [ + self.board: list[list[Player]] = [ [u, u, u], [u, u, u], [u, u, u], diff --git a/noxfile.py b/noxfile.py index 5634a9cd9b..8f29cf6acd 100755 --- a/noxfile.py +++ b/noxfile.py @@ -16,11 +16,8 @@ from typing import ( TYPE_CHECKING, Any, - Dict, Final, - List, Optional, - Tuple, ) import nox @@ -34,9 +31,9 @@ PYPROJECT = nox.project.load_toml() -SUPPORTED_PYTHONS: Final[List[str]] = nox.project.python_versions(PYPROJECT) -EXPERIMENTAL_PYTHON_VERSIONS: Final[List[str]] = ["3.14"] -ALL_PYTHONS: Final[List[str]] = [*SUPPORTED_PYTHONS, *EXPERIMENTAL_PYTHON_VERSIONS] +SUPPORTED_PYTHONS: Final[list[str]] = nox.project.python_versions(PYPROJECT) +EXPERIMENTAL_PYTHON_VERSIONS: Final[list[str]] = ["3.14"] +ALL_PYTHONS: Final[list[str]] = [*SUPPORTED_PYTHONS, *EXPERIMENTAL_PYTHON_VERSIONS] MIN_PYTHON: Final[str] = SUPPORTED_PYTHONS[0] CI: Final[bool] = "CI" in os.environ @@ -46,19 +43,19 @@ if TYPE_CHECKING: ExecutionGroupType = object else: - ExecutionGroupType = Dict[str, Any] + ExecutionGroupType = dict[str, Any] @dataclasses.dataclass class ExecutionGroup(ExecutionGroupType): - sessions: Tuple[str, ...] = () + sessions: tuple[str, ...] = () python: str = MIN_PYTHON project: bool = True - extras: Tuple[str, ...] = () - groups: Tuple[str, ...] = () - dependencies: Tuple[str, ...] = () + extras: tuple[str, ...] = () + groups: tuple[str, ...] = () + dependencies: tuple[str, ...] = () experimental: bool = False - pyright_paths: Tuple[str, ...] = () + pyright_paths: tuple[str, ...] = () def __post_init__(self) -> None: if self.pyright_paths and "pyright" not in self.sessions: @@ -70,7 +67,7 @@ def __post_init__(self) -> None: self[key] = getattr(self, key) # type: ignore -EXECUTION_GROUPS: List[ExecutionGroup] = [ +EXECUTION_GROUPS: list[ExecutionGroup] = [ ## pyright *( ExecutionGroup( @@ -124,7 +121,7 @@ def __post_init__(self) -> None: ] -def get_groups_for_session(name: str) -> List[ExecutionGroup]: +def get_groups_for_session(name: str) -> list[ExecutionGroup]: return [g for g in EXECUTION_GROUPS if name in g.sessions] @@ -152,7 +149,7 @@ def install_deps(session: nox.Session, *, execution_group: Optional[ExecutionGro msg = "Cannot install extras without also installing the project" raise TypeError(msg) - command: List[str] + command: list[str] # If not using uv, install with pip if os.getenv("INSTALL_WITH_PIP") is not None: @@ -179,7 +176,7 @@ def install_deps(session: nox.Session, *, execution_group: Optional[ExecutionGro "sync", "--no-default-groups", ] - env: Dict[str, Any] = {} + env: dict[str, Any] = {} if session.venv_backend != "none": command.append(f"--python={session.virtualenv.location}") @@ -289,7 +286,7 @@ def autotyping(session: nox.Session) -> None: if not session.interactive: base_command += ["--hide-progress"] - dir_options: Dict[Tuple[str, ...], Tuple[str, ...]] = { + dir_options: dict[tuple[str, ...], tuple[str, ...]] = { ( "disnake", "scripts", diff --git a/pyproject.toml b/pyproject.toml index 152c159b37..90b78dd168 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -210,10 +210,6 @@ ignore = [ "TRY003", # as of 0.12.11 still has some false positives "TRY301", # TODO: enable "TRY300", # TODO: enable - # py3.9 bump - "UP006", - "UP035", - "FURB188", ] [tool.ruff.lint.per-file-ignores] diff --git a/scripts/ci/versiontool.py b/scripts/ci/versiontool.py index 36ad3df7c9..803b427819 100644 --- a/scripts/ci/versiontool.py +++ b/scripts/ci/versiontool.py @@ -7,7 +7,7 @@ import sys from enum import Enum from pathlib import Path -from typing import List, NamedTuple, NoReturn +from typing import NamedTuple, NoReturn TARGET_FILE = Path("disnake/__init__.py") ORIG_INIT_CONTENTS = TARGET_FILE.read_text("utf-8") @@ -67,7 +67,7 @@ def get_current_version() -> VersionInfo: def replace_line(text: str, regex: str, repl: str) -> str: - lines: List[str] = [] + lines: list[str] = [] found = False for line in text.split("\n"): diff --git a/scripts/codemods/base.py b/scripts/codemods/base.py index bd532101a6..d0cf37b1a5 100644 --- a/scripts/codemods/base.py +++ b/scripts/codemods/base.py @@ -1,9 +1,10 @@ # SPDX-License-Identifier: MIT from abc import ABC +from collections.abc import Generator from contextlib import contextmanager from contextvars import ContextVar -from typing import TYPE_CHECKING, ClassVar, Generator, Optional +from typing import TYPE_CHECKING, ClassVar, Optional import libcst as cst import libcst.codemod as codemod diff --git a/scripts/codemods/overloads_no_missing.py b/scripts/codemods/overloads_no_missing.py index 6c56a9be07..1e6db4fc68 100644 --- a/scripts/codemods/overloads_no_missing.py +++ b/scripts/codemods/overloads_no_missing.py @@ -1,6 +1,7 @@ # SPDX-License-Identifier: MIT -from typing import List, Optional, Sequence +from collections.abc import Sequence +from typing import Optional import libcst as cst import libcst.matchers as m @@ -31,7 +32,7 @@ def leave_FunctionDef( if not params: continue - new_params: List[cst.Param] = [] + new_params: list[cst.Param] = [] for param in params: if param.default and m.matches(param.default, m.Name("MISSING")): new_param = param.with_changes(default=cst.Ellipsis()) diff --git a/scripts/codemods/typed_flags.py b/scripts/codemods/typed_flags.py index af6c12a386..61b891bcd2 100644 --- a/scripts/codemods/typed_flags.py +++ b/scripts/codemods/typed_flags.py @@ -3,7 +3,7 @@ import importlib import textwrap import types -from typing import List, Optional, cast +from typing import Optional, cast import libcst as cst import libcst.codemod.visitors as codevisitors @@ -27,7 +27,7 @@ class FlagTypings(BaseCodemodCommand): "Types every flag classes's init method, using overloads or if typechecking blocks." ) - flag_classes: List[str] + flag_classes: list[str] imported_module: types.ModuleType def transform_module(self, tree: cst.Module) -> cst.Module: @@ -39,7 +39,7 @@ def transform_module(self, tree: cst.Module) -> cst.Module: # import and load the module module = importlib.import_module(current_module) # we preformulate a list of all flag classes on the imported flags module - all_flag_classes: List[str] = [] + all_flag_classes: list[str] = [] for attr_name in dir(module): obj = getattr(module, attr_name) if ( diff --git a/scripts/codemods/typed_permissions.py b/scripts/codemods/typed_permissions.py index ec900515df..6eb067dce5 100644 --- a/scripts/codemods/typed_permissions.py +++ b/scripts/codemods/typed_permissions.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT import itertools -from typing import List, Optional, Union +from typing import Optional, Union import libcst as cst import libcst.codemod.visitors as codevisitors @@ -16,7 +16,7 @@ PERMISSION_MATCHERS = m.OneOf(*map(m.Name, ALL_PERMISSIONS)) -def get_perm_kwargs(annotation: cst.Annotation) -> List[cst.Param]: +def get_perm_kwargs(annotation: cst.Annotation) -> list[cst.Param]: return [ cst.Param( cst.Name(perm), diff --git a/tests/ext/tasks/test_loops.py b/tests/ext/tasks/test_loops.py index 26070dba54..bac4b60f7c 100644 --- a/tests/ext/tasks/test_loops.py +++ b/tests/ext/tasks/test_loops.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT import datetime -from typing import Any, Tuple +from typing import Any import pytest @@ -37,7 +37,7 @@ async def task() -> None: ... def test_inheritance(self) -> None: class HyperLoop(Loop[LF]): - def __init__(self, coro: LF, time_tup: Tuple[float, float, float]) -> None: + def __init__(self, coro: LF, time_tup: tuple[float, float, float]) -> None: s, m, h = time_tup super().__init__(coro, seconds=s, minutes=m, hours=h) diff --git a/tests/helpers.py b/tests/helpers.py index bcf957d98e..4f88ffa4c6 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -4,7 +4,8 @@ import functools import inspect import types -from typing import TYPE_CHECKING, Callable, ContextManager, Optional, Type, TypeVar +from contextlib import AbstractContextManager +from typing import TYPE_CHECKING, Callable, Optional, TypeVar from unittest import mock if TYPE_CHECKING: @@ -28,7 +29,7 @@ def reveal_type(*args, **kwargs) -> None: CallableT = TypeVar("CallableT", bound=Callable) -class freeze_time(ContextManager): +class freeze_time(AbstractContextManager): """Helper class that freezes time at the given datetime by patching `datetime.now`. If no datetime is provided, defaults to the current time. Can be used as a sync context manager or decorator for sync/async functions. @@ -53,7 +54,7 @@ def __enter__(self) -> mock.MagicMock: def __exit__( self, - typ: Optional[Type[BaseException]], + typ: Optional[type[BaseException]], value: Optional[BaseException], tb: Optional[types.TracebackType], ) -> Optional[bool]: diff --git a/tests/test_colour.py b/tests/test_colour.py index 365edff619..7091874550 100644 --- a/tests/test_colour.py +++ b/tests/test_colour.py @@ -1,7 +1,6 @@ # SPDX-License-Identifier: MIT import math -from typing import Tuple import pytest @@ -28,7 +27,7 @@ def test_compare() -> None: ("value", "parts"), [(0, (0, 0, 0)), (0xA00233, (0xA0, 0x02, 0x33)), (0x123456, (0x12, 0x34, 0x56))], ) -def test_to_rgb(value: int, parts: Tuple[int, int, int]) -> None: +def test_to_rgb(value: int, parts: tuple[int, int, int]) -> None: c = Colour(value) assert c.to_rgb() == parts assert (c.r, c.g, c.b) == parts @@ -38,7 +37,7 @@ def test_to_rgb(value: int, parts: Tuple[int, int, int]) -> None: ("value", "parts"), [(0, (0, 0, 0)), (0xA00233, (0xA0, 0x02, 0x33)), (0x123456, (0x12, 0x34, 0x56))], ) -def test_from_rgb(value: int, parts: Tuple[int, int, int]) -> None: +def test_from_rgb(value: int, parts: tuple[int, int, int]) -> None: assert Colour.from_rgb(*parts).value == value @@ -50,7 +49,7 @@ def test_from_rgb(value: int, parts: Tuple[int, int, int]) -> None: (0x5CCFF9, (196 / 360, 63 / 100, 98 / 100)), ], ) -def test_from_hsv(value: int, parts: Tuple[float, float, float]) -> None: +def test_from_hsv(value: int, parts: tuple[float, float, float]) -> None: expected = Colour(value) col = Colour.from_hsv(*parts) assert all(math.isclose(a, b, abs_tol=1) for a, b in zip(expected.to_rgb(), col.to_rgb())) diff --git a/tests/test_mentions.py b/tests/test_mentions.py index 2aed35df21..b5d2da4dfc 100644 --- a/tests/test_mentions.py +++ b/tests/test_mentions.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import Dict, Union +from typing import Union from unittest import mock import pytest @@ -49,7 +49,7 @@ def test_classmethod_all() -> None: (AllowedMentions.none(), {"parse": []}), ], ) -def test_to_dict(am: AllowedMentions, expected: Dict[str, Union[bool, list]]) -> None: +def test_to_dict(am: AllowedMentions, expected: dict[str, Union[bool, list]]) -> None: assert expected == am.to_dict() diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 93e052cf79..1d3290572f 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import Dict, Literal, Optional +from typing import Literal, Optional import pytest @@ -106,9 +106,9 @@ def test_is_strict_superset(self, perms_int: int, other_int: int, expected: bool ) def test_update( self, - perms_dict: Dict[str, bool], - update: Dict[str, bool], - expected: Dict[str, Literal[True]], + perms_dict: dict[str, bool], + update: dict[str, bool], + expected: dict[str, Literal[True]], ) -> None: perms = Permissions(**perms_dict) perms.update(**update) @@ -126,7 +126,7 @@ def test_update( ({"view_channel": False, "read_messages": True}, 8 + 1024), ], ) - def test_update_aliases(self, update: Dict[str, bool], expected: int) -> None: + def test_update_aliases(self, update: dict[str, bool], expected: int) -> None: perms = Permissions(administrator=True) perms.update(**update) assert perms.value == expected @@ -142,7 +142,7 @@ def test_update_aliases(self, update: Dict[str, bool], expected: int) -> None: ), ], ) - def test_iter(self, parameters: Dict[str, bool], expected: Optional[Dict[str, bool]]) -> None: + def test_iter(self, parameters: dict[str, bool], expected: Optional[dict[str, bool]]) -> None: perms = Permissions(**parameters) if expected is None: expected = parameters @@ -252,8 +252,8 @@ def test_set_invalid_type(self) -> None: ) def test_from_pair( self, - allow: Dict[str, bool], - deny: Dict[str, bool], + allow: dict[str, bool], + deny: dict[str, bool], ) -> None: perm_allow = Permissions(**allow) perm_deny = Permissions(**deny) @@ -331,7 +331,7 @@ def test_update(self) -> None: ) def test_iter( self, - expected: Dict[str, bool], + expected: dict[str, bool], ) -> None: po = PermissionOverwrite(**expected) diff --git a/tests/test_utils.py b/tests/test_utils.py index fcc1ed60e8..fa90bf5d63 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -13,11 +13,8 @@ TYPE_CHECKING, Any, Callable, - Dict, - List, Literal, Optional, - Tuple, TypeVar, Union, ) @@ -781,8 +778,8 @@ def test_normalise_optional_params(params, expected) -> None: (None, NoneType, False), (int, int, False), # complex types - (List[int], List[int], False), - (Dict[float, "List[yarl.URL]"], Dict[float, List[yarl.URL]], True), + (list[int], list[int], False), + (dict[float, "list[yarl.URL]"], dict[float, list[yarl.URL]], True), (Literal[1, Literal[False], "hi"], Literal[1, False, "hi"], False), # noqa: RUF041 # unions (Union[timezone, float], Union[timezone, float], False), @@ -790,7 +787,7 @@ def test_normalise_optional_params(params, expected) -> None: (Union["tuple", None, int], Union[tuple, int, None], True), # forward refs ("bool", bool, True), - ("Tuple[dict, List[Literal[42, 99]]]", Tuple[dict, List[Literal[42, 99]]], True), + ("tuple[dict, list[Literal[42, 99]]]", tuple[dict, list[Literal[42, 99]]], True), # 3.10 union syntax pytest.param( "int | float", @@ -822,43 +819,43 @@ def test_resolve_annotation_literal() -> None: # declared here as `TypeAliasType` is only valid in class/module scopes if TYPE_CHECKING or sys.version_info >= (3, 12): # this is equivalent to `type CoolList = List[int]` - CoolList = TypeAliasType("CoolList", List[int]) + CoolList = TypeAliasType("CoolList", list[int]) # this is equivalent to `type CoolList[T] = List[T]` T = TypeVar("T") - CoolListGeneric = TypeAliasType("CoolListGeneric", List[T], type_params=(T,)) + CoolListGeneric = TypeAliasType("CoolListGeneric", list[T], type_params=(T,)) @pytest.mark.skipif(sys.version_info < (3, 12), reason="syntax requires py3.12") class TestResolveAnnotationTypeAliasType: def test_simple(self) -> None: annotation = CoolList - assert utils.resolve_annotation(annotation, globals(), locals(), {}) == List[int] + assert utils.resolve_annotation(annotation, globals(), locals(), {}) == list[int] def test_generic(self) -> None: annotation = CoolListGeneric[int] - assert utils.resolve_annotation(annotation, globals(), locals(), {}) == List[int] + assert utils.resolve_annotation(annotation, globals(), locals(), {}) == list[int] # alias and arg in local scope def test_forwardref_local(self) -> None: IntOrStr = Union[int, str] annotation = CoolListGeneric["IntOrStr"] - assert utils.resolve_annotation(annotation, globals(), locals(), {}) == List[IntOrStr] + assert utils.resolve_annotation(annotation, globals(), locals(), {}) == list[IntOrStr] # alias and arg in other module scope def test_forwardref_module(self) -> None: resolved = utils.resolve_annotation( utils_helper_module.ListWithForwardRefAlias, globals(), locals(), {} ) - assert resolved == List[Union[int, str]] + assert resolved == list[Union[int, str]] # combination of the previous two, alias in other module scope and arg in local scope def test_forwardref_mixed(self) -> None: LocalIntOrStr = Union[int, str] annotation = utils_helper_module.GenericListAlias["LocalIntOrStr"] - assert utils.resolve_annotation(annotation, globals(), locals(), {}) == List[LocalIntOrStr] + assert utils.resolve_annotation(annotation, globals(), locals(), {}) == list[LocalIntOrStr] # two different forwardrefs with same name def test_forwardref_duplicate(self) -> None: @@ -867,8 +864,8 @@ def test_forwardref_duplicate(self) -> None: # first, resolve an annotation where `DuplicateAlias` resolves to the local int cache = {} assert ( - utils.resolve_annotation(List["DuplicateAlias"], globals(), locals(), cache) - == List[int] + utils.resolve_annotation(list["DuplicateAlias"], globals(), locals(), cache) + == list[int] ) # then, resolve an annotation where the globalns changes and `DuplicateAlias` resolves to something else @@ -877,7 +874,7 @@ def test_forwardref_duplicate(self) -> None: utils.resolve_annotation( utils_helper_module.ListWithDuplicateAlias, globals(), locals(), cache ) - == List[str] + == list[str] ) diff --git a/tests/ui/test_components.py b/tests/ui/test_components.py index 710c3cca33..94ed2f3a73 100644 --- a/tests/ui/test_components.py +++ b/tests/ui/test_components.py @@ -1,19 +1,18 @@ # SPDX-License-Identifier: MIT import inspect -from typing import List, Type import pytest from disnake import ui -all_ui_component_types: List[Type[ui.UIComponent]] = [ +all_ui_component_types: list[type[ui.UIComponent]] = [ c for c in ui.__dict__.values() if isinstance(c, type) and issubclass(c, ui.UIComponent) and not inspect.isabstract(c) ] -all_ui_component_objects: List[ui.UIComponent] = [ +all_ui_component_objects: list[ui.UIComponent] = [ ui.ActionRow(), ui.Button(), ui.ChannelSelect(), diff --git a/tests/ui/test_decorators.py b/tests/ui/test_decorators.py index 2e9f3fec42..623145162e 100644 --- a/tests/ui/test_decorators.py +++ b/tests/ui/test_decorators.py @@ -2,7 +2,8 @@ from __future__ import annotations import contextlib -from typing import Any, Iterator, Type, TypeVar +from collections.abc import Iterator +from typing import Any, TypeVar import pytest from typing_extensions import assert_type @@ -16,7 +17,7 @@ @contextlib.contextmanager def create_callback( - view_type: Type[V], item_type: Type[I] + view_type: type[V], item_type: type[I] ) -> Iterator[ui.item.ItemCallbackType[V, I]]: async def callback(self: V, item: I, inter) -> None: pytest.fail("callback should not be invoked") @@ -55,7 +56,7 @@ def test_default(self) -> None: # as @ui.string_select etc. works identically @pytest.mark.parametrize("cls", [_CustomButton, _CustomButton[Any]]) - def test_cls(self, cls: Type[_CustomButton[ui.View]]) -> None: + def test_cls(self, cls: type[_CustomButton[ui.View]]) -> None: with create_callback(_CustomView, cls) as func: res = ui.button(cls=cls, param=1337)(func) assert_type(res, ui.item.DecoratedItem[_CustomButton[ui.View]]) diff --git a/tests/utils_helper_module.py b/tests/utils_helper_module.py index 7711e861b8..ae74fdbbd0 100644 --- a/tests/utils_helper_module.py +++ b/tests/utils_helper_module.py @@ -3,7 +3,7 @@ """Separate module file for some test_utils.py type annotation tests.""" import sys -from typing import TYPE_CHECKING, List, TypeVar, Union +from typing import TYPE_CHECKING, TypeVar, Union version = sys.version_info # assign to variable to trick pyright @@ -16,11 +16,11 @@ if version >= (3, 12): CoolUniqueIntOrStrAlias = Union[int, str] ListWithForwardRefAlias = TypeAliasType( - "ListWithForwardRefAlias", List["CoolUniqueIntOrStrAlias"] + "ListWithForwardRefAlias", list["CoolUniqueIntOrStrAlias"] ) T = TypeVar("T") - GenericListAlias = TypeAliasType("GenericListAlias", List[T], type_params=(T,)) + GenericListAlias = TypeAliasType("GenericListAlias", list[T], type_params=(T,)) DuplicateAlias = str - ListWithDuplicateAlias = TypeAliasType("ListWithDuplicateAlias", List["DuplicateAlias"]) + ListWithDuplicateAlias = TypeAliasType("ListWithDuplicateAlias", list["DuplicateAlias"])