From 586f5a8c0d9e4ddb68597efb2800bdf28fe5c0d2 Mon Sep 17 00:00:00 2001 From: onerandomusername Date: Mon, 15 Sep 2025 17:18:41 -0400 Subject: [PATCH 1/6] feat: drop python 38 support --- .github/actions/setup-env/action.yml | 2 +- .github/workflows/create-release-pr.yaml | 2 +- .github/workflows/release.yaml | 2 +- .readthedocs.yml | 2 +- README.md | 2 +- docs/intro.rst | 4 ++-- noxfile.py | 2 +- pyproject.toml | 3 +-- 8 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/actions/setup-env/action.yml b/.github/actions/setup-env/action.yml index 73fe11a67b..f92a6b57af 100644 --- a/.github/actions/setup-env/action.yml +++ b/.github/actions/setup-env/action.yml @@ -6,7 +6,7 @@ inputs: python-version: description: The python version to install required: false - default: '3.8' + default: '3.9' use-cached-uv-lock: description: Whether to download the uv lock cache. required: false diff --git a/.github/workflows/create-release-pr.yaml b/.github/workflows/create-release-pr.yaml index d1eeffac46..e3bfe3312e 100644 --- a/.github/workflows/create-release-pr.yaml +++ b/.github/workflows/create-release-pr.yaml @@ -45,7 +45,7 @@ jobs: - name: Set up environment uses: ./.github/actions/setup-env with: - python-version: 3.8 + python-version: 3.9 - name: Install dependencies run: uv sync --no-default-groups --group changelog diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 20a63b7a1b..a5fca778b4 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -23,7 +23,7 @@ jobs: id: setup uses: ./.github/actions/setup-env with: - python-version: 3.8 + python-version: 3.9 - name: Build package run: | diff --git a/.readthedocs.yml b/.readthedocs.yml index aec1ccff3d..1e48672de0 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -6,7 +6,7 @@ formats: build: os: ubuntu-24.04 tools: - python: "3.8" + python: "3.9" jobs: create_environment: - asdf plugin add uv diff --git a/README.md b/README.md index 49d7a80dfc..2afc1836eb 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Key Features Installing ---------- -**Python 3.8 or higher is required.** +**Python 3.9 or higher is required.** To install the library without full voice support, you can just run the following command: diff --git a/docs/intro.rst b/docs/intro.rst index fd835d28e9..58cde9c70a 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -15,8 +15,8 @@ in creating applications that utilise the Discord API. Prerequisites ------------- -disnake works with Python 3.8 or higher. Support for earlier versions of Python -is not provided. Python 2.7 or lower is not supported. Python 3.7 or lower is not supported. +disnake works with Python 3.9 or higher. Support for earlier versions of Python +is not provided. Python 2.7 or lower is not supported. Python 3.8 or lower is not supported. .. _installing: diff --git a/noxfile.py b/noxfile.py index 7dc54e12f7..6d192b58ce 100755 --- a/noxfile.py +++ b/noxfile.py @@ -1,6 +1,6 @@ #!/usr/bin/env -S uv run --script # /// script -# requires-python = ">=3.8" +# requires-python = ">=3.9" # dependencies = [ # "nox==2025.5.1", # ] diff --git a/pyproject.toml b/pyproject.toml index dcb3f7b29e..a6f87d3c95 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ readme = "README.md" authors = [ { name = "Disnake Development" } ] -requires-python = ">=3.8" +requires-python = ">=3.9" keywords = ["disnake", "discord", "discord api"] license = { text = "MIT" } dependencies = [ @@ -25,7 +25,6 @@ classifiers = [ "Natural Language :: English", "Operating System :: OS Independent", # it is important that the python classifiers are sorted in the sequential order - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", From 974b84dec9c6ecf1b38baa91959f5fc11a648622 Mon Sep 17 00:00:00 2001 From: onerandomusername Date: Mon, 15 Sep 2025 17:22:12 -0400 Subject: [PATCH 2/6] typehint update --- disnake/__main__.py | 6 +- disnake/abc.py | 52 ++--- disnake/activity.py | 18 +- disnake/app_commands.py | 49 ++-- disnake/appinfo.py | 14 +- disnake/asset.py | 6 +- disnake/audit_logs.py | 29 +-- disnake/automod.py | 21 +- disnake/bans.py | 3 +- disnake/channel.py | 104 ++++----- disnake/client.py | 82 ++++--- disnake/colour.py | 6 +- disnake/components.py | 100 ++++----- disnake/context_managers.py | 6 +- disnake/embeds.py | 13 +- disnake/emoji.py | 11 +- disnake/enums.py | 27 +-- disnake/errors.py | 11 +- disnake/ext/commands/_types.py | 3 +- disnake/ext/commands/base_core.py | 13 +- disnake/ext/commands/bot.py | 15 +- disnake/ext/commands/bot_base.py | 17 +- disnake/ext/commands/cog.py | 46 ++-- disnake/ext/commands/common_bot_base.py | 15 +- disnake/ext/commands/context.py | 14 +- disnake/ext/commands/converter.py | 32 ++- disnake/ext/commands/cooldowns.py | 8 +- disnake/ext/commands/core.py | 53 ++--- disnake/ext/commands/ctx_menus_core.py | 11 +- disnake/ext/commands/errors.py | 32 +-- disnake/ext/commands/flag_converter.py | 51 ++--- disnake/ext/commands/help.py | 33 ++- disnake/ext/commands/interaction_bot_base.py | 53 ++--- disnake/ext/commands/params.py | 89 ++++---- disnake/ext/commands/slash_core.py | 57 +++-- disnake/ext/mypy_plugin/__init__.py | 4 +- disnake/ext/tasks/__init__.py | 27 +-- disnake/flags.py | 27 +-- disnake/gateway.py | 25 +-- disnake/guild.py | 175 +++++++-------- disnake/guild_preview.py | 10 +- disnake/guild_scheduled_event.py | 4 +- disnake/http.py | 224 +++++++++---------- disnake/i18n.py | 22 +- disnake/integrations.py | 8 +- disnake/interactions/application_command.py | 23 +- disnake/interactions/base.py | 76 +++---- disnake/interactions/message.py | 11 +- disnake/interactions/modal.py | 13 +- disnake/invite.py | 6 +- disnake/iterators.py | 70 +++--- disnake/member.py | 28 +-- disnake/mentions.py | 8 +- disnake/message.py | 113 +++++----- disnake/oggparse.py | 5 +- disnake/onboarding.py | 18 +- disnake/opus.py | 11 +- disnake/partial_emoji.py | 6 +- disnake/permissions.py | 15 +- disnake/player.py | 12 +- disnake/poll.py | 8 +- disnake/raw_models.py | 6 +- disnake/role.py | 10 +- disnake/shard.py | 14 +- disnake/soundboard.py | 4 +- disnake/state.py | 101 ++++----- disnake/sticker.py | 8 +- disnake/subscription.py | 8 +- disnake/team.py | 4 +- disnake/template.py | 4 +- disnake/threads.py | 21 +- disnake/types/activity.py | 8 +- disnake/types/appinfo.py | 16 +- disnake/types/audit_log.py | 36 +-- disnake/types/automod.py | 16 +- disnake/types/channel.py | 14 +- disnake/types/components.py | 18 +- disnake/types/embed.py | 4 +- disnake/types/emoji.py | 4 +- disnake/types/gateway.py | 39 ++-- disnake/types/guild.py | 36 +-- disnake/types/i18n.py | 3 +- disnake/types/integration.py | 4 +- disnake/types/interactions.py | 62 ++--- disnake/types/message.py | 30 +-- disnake/types/onboarding.py | 6 +- disnake/types/poll.py | 10 +- disnake/types/snowflake.py | 4 +- disnake/types/soundboard.py | 4 +- disnake/types/sticker.py | 6 +- disnake/types/subscription.py | 8 +- disnake/types/team.py | 4 +- disnake/types/threads.py | 6 +- disnake/types/voice.py | 4 +- disnake/types/welcome_screen.py | 4 +- disnake/types/widget.py | 6 +- disnake/ui/_types.py | 3 +- disnake/ui/action_row.py | 43 ++-- disnake/ui/button.py | 4 +- disnake/ui/container.py | 8 +- disnake/ui/file.py | 4 +- disnake/ui/item.py | 13 +- disnake/ui/label.py | 4 +- disnake/ui/media_gallery.py | 7 +- disnake/ui/modal.py | 10 +- disnake/ui/section.py | 8 +- disnake/ui/select/base.py | 22 +- disnake/ui/select/channel.py | 22 +- disnake/ui/select/mentionable.py | 7 +- disnake/ui/select/role.py | 7 +- disnake/ui/select/string.py | 18 +- disnake/ui/select/user.py | 7 +- disnake/ui/separator.py | 4 +- disnake/ui/text_display.py | 4 +- disnake/ui/text_input.py | 4 +- disnake/ui/thumbnail.py | 4 +- disnake/ui/view.py | 29 +-- disnake/user.py | 6 +- disnake/utils.py | 88 ++++---- disnake/voice_client.py | 12 +- disnake/webhook/async_.py | 110 +++++---- disnake/webhook/sync.py | 90 ++++---- disnake/welcome_screen.py | 6 +- disnake/widget.py | 8 +- docs/conf.py | 4 +- docs/extensions/attributetable.py | 18 +- docs/extensions/collapse.py | 4 +- docs/extensions/exception_hierarchy.py | 4 +- docs/extensions/fulltoc.py | 4 +- docs/extensions/redirects.py | 6 +- docs/extensions/resourcelinks.py | 10 +- examples/basic_voice.py | 4 +- examples/interactions/autocomplete.py | 3 +- examples/views/button/paginator.py | 3 +- examples/views/tic_tac_toe.py | 6 +- noxfile.py | 31 ++- scripts/ci/versiontool.py | 4 +- scripts/codemods/base.py | 3 +- scripts/codemods/overloads_no_missing.py | 5 +- scripts/codemods/typed_flags.py | 6 +- scripts/codemods/typed_permissions.py | 4 +- tests/ext/tasks/test_loops.py | 4 +- tests/helpers.py | 7 +- tests/test_colour.py | 7 +- tests/test_mentions.py | 4 +- tests/test_permissions.py | 18 +- tests/test_utils.py | 29 ++- tests/ui/test_components.py | 5 +- tests/ui/test_decorators.py | 7 +- tests/utils_helper_module.py | 8 +- 150 files changed, 1581 insertions(+), 1760 deletions(-) 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 1cc6b95d6d..820a64055d 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( @@ -296,7 +292,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) @@ -313,7 +309,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: @@ -379,7 +375,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( @@ -428,7 +424,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] @@ -453,7 +449,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, @@ -505,11 +501,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]: """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) @@ -562,7 +558,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 @@ -1035,7 +1031,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, @@ -1044,7 +1040,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): raise TypeError("overwrites parameter expects a dict.") @@ -1250,7 +1246,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 @@ -1273,7 +1269,7 @@ async def move(self, **kwargs: Any) -> None: raise ValueError("Could not resolve appropriate move position") 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): @@ -1379,7 +1375,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. @@ -1455,7 +1451,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] = ..., @@ -1475,7 +1471,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 = ..., @@ -1496,8 +1492,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] = ..., @@ -1517,9 +1513,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, @@ -2015,10 +2011,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 2bda908a4f..0ce45c02c8 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]: """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 e5fca96792..e475e45b8b 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, @@ -265,8 +266,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, @@ -284,7 +285,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) @@ -300,9 +301,9 @@ def __init__( if channel_types is not None and not all(isinstance(t, ChannelType) for t in channel_types): raise TypeError("channel_types must be a list of `ChannelType`s") - 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: raise TypeError("can not specify both choices and autocomplete args") @@ -395,8 +396,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, @@ -508,7 +509,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", @@ -702,15 +703,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 ) @@ -730,7 +731,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): @@ -780,7 +781,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" ) @@ -846,7 +847,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__, ) @@ -908,7 +909,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" ) @@ -974,7 +975,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__, ) @@ -1046,7 +1047,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", @@ -1056,7 +1057,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, @@ -1078,7 +1079,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 ( @@ -1096,7 +1097,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, @@ -1194,7 +1195,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__, ) @@ -1309,7 +1310,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 f24bbe69c5..e4fc566a8a 100644 --- a/disnake/appinfo.py +++ b/disnake/appinfo.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Dict, List, Optional, cast +from typing import TYPE_CHECKING, Optional, cast from . import utils from .asset import Asset @@ -282,7 +282,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"]) @@ -305,12 +305,12 @@ 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(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" @@ -319,7 +319,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( @@ -327,7 +327,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(): @@ -446,7 +446,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 6a9e1e3f0a..970104e9f1 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| @@ -190,7 +190,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 6e81652792..bd2442469e 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 35b0e82fed..3a9071d8f7 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]: """List[Union[: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]: """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]: """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 ab036d0f58..e5e3a9b74f 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]: """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]: """List[:class:`Thread`]: Returns all the threads that you can see. .. versionadded:: 2.0 @@ -716,7 +710,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 @@ -777,7 +771,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 @@ -818,7 +812,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. @@ -1194,10 +1188,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: @@ -1222,12 +1216,12 @@ def _sorting_bucket(self) -> int: return ChannelType.voice.value @property - def members(self) -> List[Member]: + def members(self) -> list[Member]: """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) @@ -1236,7 +1230,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 @@ -1769,7 +1763,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 @@ -1826,7 +1820,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 @@ -1867,7 +1861,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. @@ -2083,7 +2077,7 @@ async def _get_channel(self) -> Self: return self @property - def requesting_to_speak(self) -> List[Member]: + def requesting_to_speak(self) -> list[Member]: """List[:class:`Member`]: A list of members who are requesting to speak in the stage channel.""" return [ member @@ -2092,7 +2086,7 @@ def requesting_to_speak(self) -> List[Member]: ] @property - def speakers(self) -> List[Member]: + def speakers(self) -> list[Member]: """List[:class:`Member`]: A list of members who have been permitted to speak in the stage channel. .. versionadded:: 2.0 @@ -2106,7 +2100,7 @@ def speakers(self) -> List[Member]: ] @property - def listeners(self) -> List[Member]: + def listeners(self) -> list[Member]: """List[:class:`Member`]: A list of members who are listening in the stage channel. .. versionadded:: 2.0 @@ -2114,7 +2108,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]: """List[:class:`Member`]: A list of members who are moderating the stage channel. .. versionadded:: 2.0 @@ -2351,7 +2345,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, @@ -2624,7 +2618,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 @@ -2681,7 +2675,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 @@ -2722,7 +2716,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. @@ -3100,7 +3094,7 @@ async def move(self, **kwargs: Any) -> None: return await super().move(**kwargs) @property - def channels(self) -> List[GuildChannelType]: + def channels(self) -> list[GuildChannelType]: """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. @@ -3108,7 +3102,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, @@ -3119,7 +3113,7 @@ def comparator(channel: GuildChannelType) -> Tuple[bool, int]: return ret @property - def text_channels(self) -> List[TextChannel]: + def text_channels(self) -> list[TextChannel]: """List[:class:`TextChannel`]: Returns the text channels that are under this category.""" if isinstance(self.guild, Object): return [] @@ -3133,7 +3127,7 @@ def text_channels(self) -> List[TextChannel]: return ret @property - def voice_channels(self) -> List[VoiceChannel]: + def voice_channels(self) -> list[VoiceChannel]: """List[:class:`VoiceChannel`]: Returns the voice channels that are under this category.""" if isinstance(self.guild, Object): return [] @@ -3147,7 +3141,7 @@ def voice_channels(self) -> List[VoiceChannel]: return ret @property - def stage_channels(self) -> List[StageChannel]: + def stage_channels(self) -> list[StageChannel]: """List[:class:`StageChannel`]: Returns the stage channels that are under this category. .. versionadded:: 1.7 @@ -3164,7 +3158,7 @@ def stage_channels(self) -> List[StageChannel]: return ret @property - def forum_channels(self) -> List[ForumChannel]: + def forum_channels(self) -> list[ForumChannel]: """List[:class:`ForumChannel`]: Returns the forum channels that are under this category. .. versionadded:: 2.5 @@ -3181,7 +3175,7 @@ def forum_channels(self) -> List[ForumChannel]: return ret @property - def media_channels(self) -> List[MediaChannel]: + def media_channels(self) -> list[MediaChannel]: """List[:class:`MediaChannel`]: Returns the media channels that are under this category. .. versionadded:: 2.10 @@ -3357,7 +3351,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 @@ -3398,14 +3392,14 @@ def permissions_for( return base @property - def members(self) -> List[Member]: + def members(self) -> list[Member]: """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]: """List[:class:`Thread`]: Returns all the threads that you can see.""" if isinstance(self.guild, Object): return [] @@ -3465,7 +3459,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]: """List[:class:`ForumTag`]: The available tags for threads in this channel. To create/edit/delete tags, use :func:`edit`. @@ -3536,7 +3530,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]] = ..., @@ -3555,7 +3549,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 = ..., @@ -3575,8 +3569,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]] = ..., @@ -3595,9 +3589,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, @@ -3805,7 +3799,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. @@ -4952,7 +4946,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", []) ] @@ -5135,7 +5129,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 @@ -5157,8 +5151,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: @@ -5171,8 +5165,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) @@ -5183,7 +5177,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 @@ -5191,8 +5185,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 5a24514cf4..4631d81bf3 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 } @@ -476,7 +470,7 @@ def __init__( if self.gateway_params.encoding != "json": raise ValueError("Gateway encodings other than `json` are currently not supported.") - self.extra_events: Dict[str, List[CoroFunc]] = {} + self.extra_events: dict[str, list[CoroFunc]] = {} # internals @@ -554,17 +548,17 @@ def user(self) -> ClientUser: return self._connection.user @property - def guilds(self) -> List[Guild]: + def guilds(self) -> list[Guild]: """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]: """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]: """List[:class:`.GuildSticker`]: The stickers that the connected client has. .. versionadded:: 2.0 @@ -572,7 +566,7 @@ def stickers(self) -> List[GuildSticker]: return self._connection.stickers @property - def soundboard_sounds(self) -> List[GuildSoundboardSound]: + def soundboard_sounds(self) -> list[GuildSoundboardSound]: """List[:class:`.GuildSoundboardSound`]: The soundboard sounds that the connected client has. .. versionadded:: 2.10 @@ -588,7 +582,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]: """List[:class:`.abc.PrivateChannel`]: The private channels that the connected client is participating on. .. note:: @@ -599,7 +593,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]: """List[:class:`.VoiceProtocol`]: Represents a list of voice connections. These are usually :class:`.VoiceClient` instances. @@ -627,12 +621,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]: """List[Union[: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]: """List[:class:`.APISlashCommand`]: The client's global slash commands.""" return [ cmd @@ -641,7 +635,7 @@ def global_slash_commands(self) -> List[APISlashCommand]: ] @property - def global_user_commands(self) -> List[APIUserCommand]: + def global_user_commands(self) -> list[APIUserCommand]: """List[:class:`.APIUserCommand`]: The client's global user commands.""" return [ cmd @@ -650,7 +644,7 @@ def global_user_commands(self) -> List[APIUserCommand]: ] @property - def global_message_commands(self) -> List[APIMessageCommand]: + def global_message_commands(self) -> list[APIMessageCommand]: """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]]: """Mapping[:class:`str`, List[Callable]]: A read-only mapping of event names to listeners. .. note:: @@ -1390,7 +1384,7 @@ def intents(self) -> Intents: # helpers/getters @property - def users(self) -> List[User]: + def users(self) -> list[User]: """List[:class:`~disnake.User`]: Returns a list of all the users the bot can see.""" return list(self._connection._users.values()) @@ -1573,7 +1567,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 @@ -1589,7 +1583,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 @@ -1605,7 +1599,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 @@ -1621,7 +1615,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 @@ -2324,7 +2318,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. @@ -2380,7 +2374,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. @@ -2482,7 +2476,7 @@ async def create_application_emoji(self, *, name: str, image: AssetBytes) -> Emo data = await self.http.create_app_emoji(self.application_id, name, 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. @@ -2674,7 +2668,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. @@ -2698,7 +2692,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 @@ -2782,7 +2776,7 @@ async def fetch_global_commands( self, *, with_localizations: bool = True, - ) -> List[APIApplicationCommand]: + ) -> list[APIApplicationCommand]: """|coro| Retrieves a list of global application commands. @@ -2919,8 +2913,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. @@ -2948,7 +2942,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. @@ -3101,8 +3095,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. @@ -3129,7 +3123,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. @@ -3169,7 +3163,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. @@ -3191,7 +3185,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. @@ -3220,7 +3214,7 @@ async def edit_role_connection_metadata( 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()) @@ -3230,7 +3224,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 a203f64063..4d9309152a 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 @@ -94,7 +94,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]: """Tuple[:class:`int`, :class:`int`, :class:`int`]: Returns an (r, g, b) tuple representing the colour.""" return (self.r, self.g, self.b) @@ -320,7 +320,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 d66dc8647d..3b7eb34d62 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", @@ -886,7 +882,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 @@ -946,7 +942,7 @@ class TextInput(Component): .. versionadded:: 2.11 """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "style", "custom_id", "label", @@ -957,7 +953,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 @@ -1024,9 +1020,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 @@ -1034,7 +1030,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", []) ] @@ -1071,9 +1067,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 @@ -1114,7 +1110,7 @@ class UnfurledMediaItem: uploaded as an attachment. """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "url", "proxy_url", "height", @@ -1179,13 +1175,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 @@ -1234,9 +1230,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 @@ -1244,7 +1240,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 { @@ -1270,7 +1266,7 @@ class MediaGalleryItem: Whether the item is marked as a spoiler. Defaults to ``False``. """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "media", "description", "spoiler", @@ -1342,9 +1338,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 @@ -1393,9 +1389,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 @@ -1442,13 +1438,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 @@ -1457,7 +1453,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 @@ -1512,13 +1508,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 35cb714660..7e039d866d 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, @@ -219,9 +216,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: @@ -655,14 +652,14 @@ def remove_author(self) -> Self: return self @property - def fields(self) -> List[_EmbedFieldProxy]: + def fields(self) -> list[_EmbedFieldProxy]: """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 ``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 e474bbbed3..dc0e768807 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 @@ -79,7 +80,7 @@ class Emoji(_EmojiTag, AssetMixin): having the :attr:`~Permissions.manage_guild_expressions` permission. """ - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "require_colons", "animated", "managed", @@ -116,7 +117,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) @@ -157,7 +158,7 @@ def url(self) -> str: return f"{Asset.BASE}/emojis/{self.id}.{fmt}" @property - def roles(self) -> List[Role]: + def roles(self) -> list[Role]: """List[:class:`Role`]: A :class:`list` of roles that are allowed to use this emoji. If roles is empty, the emoji is unrestricted. @@ -258,7 +259,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 7ea1957269..93551ecbe9 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 = {} @@ -774,7 +771,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, @@ -1073,7 +1070,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", @@ -2449,13 +2446,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. @@ -2466,7 +2463,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 1bab2cf8ba..ae3322c9e3 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 b655a1f4c8..913d68d648 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): raise TypeError("Name of a command must be a string.") @@ -175,7 +172,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__ @@ -198,7 +195,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 @@ -257,7 +254,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 0cd80cb628..cd761df926 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 ab5e6b9856..d69f887fc4 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 @@ -150,8 +151,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 @@ -428,7 +429,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 @@ -471,7 +472,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 b7551beed3..beea8dcee9 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", {}) @@ -231,10 +227,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 @@ -247,7 +243,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) @@ -279,7 +275,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 @@ -294,7 +290,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 @@ -309,7 +305,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 @@ -324,7 +320,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 @@ -335,7 +331,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 @@ -376,7 +372,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 38b2da8566..d3390f7fca 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: raise TypeError("Both owner_id and owner_ids are set.") diff --git a/disnake/ext/commands/context.py b/disnake/ext/commands/context.py index 737bb40e08..8f41268a46 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 7f403d348e..8b4dc05cc6 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, @@ -382,7 +378,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/" @@ -476,7 +472,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) @@ -505,7 +501,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 @@ -1003,7 +999,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: @@ -1127,7 +1123,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, @@ -1149,7 +1145,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. @@ -1180,7 +1176,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: @@ -1222,14 +1218,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, @@ -1259,7 +1255,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: @@ -1335,7 +1331,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: @@ -1357,7 +1353,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 971af2bd0f..577da29b2f 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 @@ -192,7 +192,7 @@ def __init__( if not callable(type): raise TypeError("Cooldown type must be a BucketType or callable") - self._cache: Dict[Any, Cooldown] = {} + self._cache: dict[Any, Cooldown] = {} self._cooldown: Optional[Cooldown] = original self._type: Callable[[Message], Any] = type @@ -296,7 +296,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)}>" @@ -342,7 +342,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 f4e4d06c9c..68708124b2 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 @@ -308,8 +303,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)): raise TypeError("Aliases of a command must be a list or a tuple of strings.") @@ -323,7 +318,7 @@ def __init__( except AttributeError: checks = kwargs.get("checks", []) - self.checks: List[Check] = checks + self.checks: list[Check] = checks try: cooldown = func.__commands_cooldown__ @@ -480,7 +475,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__) @@ -606,7 +601,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]: """Dict[:class:`str`, :class:`inspect.Parameter`]: Retrieves the parameter dictionary without the context or self parameters. @@ -631,7 +626,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]]: """List[:class:`Group`]: Retrieves the parents of this command. If the command has no parents then it returns an empty :class:`list`. @@ -994,7 +989,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 @@ -1115,14 +1110,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]]: """Set[:class:`.Command`]: A unique set of commands without aliases that are registered.""" return set(self.all_commands.values()) @@ -1267,7 +1262,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]: ... @@ -1277,7 +1272,7 @@ def command( self, name: str = ..., *args: Any, - cls: Type[CommandT], + cls: type[CommandT], **kwargs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], CommandT]: ... @@ -1292,7 +1287,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: @@ -1317,7 +1312,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]: ... @@ -1327,7 +1322,7 @@ def group( self, name: str = ..., *args: Any, - cls: Type[GroupT], + cls: type[GroupT], **kwargs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], GroupT]: ... @@ -1342,7 +1337,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: @@ -1515,7 +1510,7 @@ def __call__( @overload def command( name: str, - cls: Type[CommandT], + cls: type[CommandT], **attrs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], CommandT]: ... @@ -1524,7 +1519,7 @@ def command( def command( name: str = ..., *, - cls: Type[CommandT], + cls: type[CommandT], **attrs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], CommandT]: ... @@ -1538,7 +1533,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` @@ -1584,7 +1579,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]: ... @@ -1593,7 +1588,7 @@ def group( def group( name: str = ..., *, - cls: Type[GroupT], + cls: type[GroupT], **attrs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], GroupT]: ... @@ -1607,7 +1602,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 b2fb6b2017..0585209c0e 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. @@ -368,7 +369,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 a3e888a03e..11f7c24997 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 fadfd65f6f..cb59438446 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: raise ValueError("flag names should not be empty") @@ -142,13 +137,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): @@ -249,8 +244,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 @@ -259,8 +254,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, @@ -285,8 +280,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__"]) @@ -346,7 +341,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 @@ -373,7 +368,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 @@ -464,7 +459,7 @@ class FlagConverter(metaclass=FlagsMeta): """ @classmethod - def get_flags(cls) -> Dict[str, Flag]: + def get_flags(cls) -> dict[str, Flag]: """Dict[:class:`str`, :class:`Flag`]: A mapping of flag name to flag object this converter has.""" return cls.__commands_flags__.copy() @@ -472,7 +467,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)) @@ -498,8 +493,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 dbad617712..2127223056 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: @@ -181,7 +176,7 @@ def __len__(self) -> int: return total + self._count @property - def pages(self) -> List[str]: + def pages(self) -> list[str]: """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): @@ -243,7 +238,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 @@ -336,7 +331,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) @@ -382,10 +377,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] @@ -551,7 +546,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. @@ -599,7 +594,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: @@ -685,7 +680,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| @@ -1047,7 +1042,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 @@ -1295,7 +1290,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 550b4ba935..7a5ce93dbb 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 @@ -159,7 +154,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]: """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]: """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]: """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]: """Set[:class:`InvokableMessageCommand`]: A set of all message commands the bot has.""" return set(self.all_message_commands.values()) @@ -500,11 +495,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 @@ -621,7 +616,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 @@ -724,7 +719,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 @@ -820,9 +815,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 40d535b493..44f69ff27d 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(Union[int, str], int)`) and generic types (`issubclass(X[T], X)`) in the first argument. @@ -187,23 +182,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 @@ -229,7 +224,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 @@ -272,13 +267,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,) @@ -349,7 +344,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 @@ -365,7 +360,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) @@ -392,7 +387,7 @@ def __post_init__(self) -> None: raise TypeError("Range[int, ...] bounds must be int, not float") @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 @@ -423,7 +418,7 @@ def __post_init__(self) -> None: raise ValueError("String bounds may not be negative") @classmethod - def _infer_type(cls, params: Tuple[Any, ...]) -> Type[Any]: + def _infer_type(cls, params: tuple[Any, ...]) -> type[Any]: return str @@ -432,7 +427,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: @@ -483,7 +478,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, @@ -501,7 +496,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, @@ -514,7 +509,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, @@ -596,8 +591,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 {} @@ -693,7 +688,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 @@ -869,8 +864,8 @@ def safe_call(function: Callable[..., T], /, *possible_args: Any, **possible_kwa ) 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(), @@ -904,8 +899,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, @@ -968,8 +963,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. @@ -980,8 +975,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]: @@ -1020,7 +1015,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) @@ -1038,7 +1033,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 @@ -1060,15 +1055,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())) @@ -1099,7 +1094,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 @@ -1147,7 +1142,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, @@ -1272,7 +1267,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. @@ -1309,7 +1304,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. @@ -1342,8 +1337,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. @@ -1391,7 +1386,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 213af66291..8bf611f0b7 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, ) @@ -105,7 +102,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 [ @@ -171,7 +168,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 @@ -197,7 +194,7 @@ def root_parent(self) -> InvokableSlashCommand: return self.parent @property - def parents(self) -> Tuple[InvokableSlashCommand]: + def parents(self) -> tuple[InvokableSlashCommand]: """Tuple[:class:`InvokableSlashCommand`]: Returns all parents of this group. .. versionadded:: 2.6 @@ -212,9 +209,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. @@ -292,15 +289,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", {}) ) @@ -334,7 +331,7 @@ def root_parent(self) -> InvokableSlashCommand: @property def parents( self, - ) -> Union[Tuple[InvokableSlashCommand], Tuple[SubCommandGroup, InvokableSlashCommand]]: + ) -> Union[tuple[InvokableSlashCommand], tuple[SubCommandGroup, InvokableSlashCommand]]: """Union[Tuple[:class:`InvokableSlashCommand`], Tuple[:class:`SubCommandGroup`, :class:`InvokableSlashCommand`]]: Returns all parents of this subcommand. @@ -449,25 +446,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", {}) ) @@ -514,7 +511,7 @@ def root_parent(self) -> None: return None @property - def parents(self) -> Tuple[()]: + def parents(self) -> tuple[()]: """Tuple[()]: This is mainly for consistency with :class:`SubCommand`, and is equivalent to an empty tuple. .. versionadded:: 2.6 @@ -545,7 +542,7 @@ def description(self) -> str: return self.body.description @property - def options(self) -> List[Option]: + def options(self) -> list[Option]: """List[:class:`.Option`]: The list of options the slash command has. Shorthand for :attr:`self.body.options <.SlashCommand.options>`.""" return self.body.options @@ -553,9 +550,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. @@ -617,7 +614,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. @@ -785,11 +782,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..4e4620bbf2 100644 --- a/disnake/ext/mypy_plugin/__init__.py +++ b/disnake/ext/mypy_plugin/__init__.py @@ -1,7 +1,5 @@ # SPDX-License-Identifier: MIT -import typing as t - from mypy.plugin import Plugin @@ -10,5 +8,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 1026e4e11a..67d18dcb0c 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, @@ -196,7 +193,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() @@ -252,7 +249,7 @@ def hours(self) -> Optional[float]: return self._hours @property - def time(self) -> Optional[List[datetime.time]]: + def time(self) -> Optional[list[datetime.time]]: """Optional[List[:class:`datetime.time`]]: Read-only list for the exact times this loop runs at. ``None`` if relative times were passed instead. @@ -382,7 +379,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 @@ -419,7 +416,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 @@ -604,9 +601,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] @@ -617,7 +614,7 @@ def _get_time_parameter( if not time: raise ValueError("time parameter must not be an empty sequence.") - ret: List[datetime.time] = [] + ret: list[datetime.time] = [] for index, t in enumerate(time): if not isinstance(t, dt): raise TypeError( @@ -679,7 +676,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)): raise TypeError("Cannot mix explicit time with relative time") @@ -724,12 +721,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 @@ -794,6 +791,6 @@ def decorator(func: LF) -> L_co: if not iscoroutinefunction(func): raise TypeError("decorated function must be a coroutine") - 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 b7fe44ee9b..ea8cd8e36c 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): @@ -88,12 +83,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) @@ -109,12 +104,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 @@ -129,7 +124,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 @@ -279,7 +274,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 @@ -321,7 +316,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 @@ -957,7 +952,7 @@ def active_developer(self) -> int: """ return UserFlags.active_developer.value - def all(self) -> List[UserFlags]: + def all(self) -> list[UserFlags]: """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 56ff150fc2..1713c9f84f 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 @@ -809,7 +806,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: @@ -910,7 +907,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 @@ -1051,7 +1048,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 82a683e7b8..5c91de3912 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]: """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]: """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]: """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]: """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]: """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]: """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]: """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]: """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]: List[Tuple[Optional[:class:`CategoryChannel`], 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]: """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]: """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]: """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]: """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]: """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: @@ -1368,7 +1363,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| @@ -1522,7 +1517,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| @@ -1637,7 +1632,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, @@ -1714,7 +1709,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 @@ -1765,7 +1760,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, @@ -1915,7 +1910,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, @@ -2034,7 +2029,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: @@ -2077,7 +2072,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 @@ -2365,7 +2360,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 @@ -2548,7 +2543,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. @@ -2569,7 +2564,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: @@ -2579,7 +2574,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. @@ -2810,7 +2805,7 @@ async def create_scheduled_event( elif not isinstance(privacy_level, GuildScheduledEventPrivacyLevel): raise TypeError("privacy_level must be an instance of GuildScheduledEventPrivacyLevel") - fields: Dict[str, Any] = { + fields: dict[str, Any] = { "name": name, "privacy_level": privacy_level.value, "scheduled_start_time": utils.isoformat_utc(scheduled_start_time), @@ -2873,7 +2868,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: @@ -3167,7 +3162,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| @@ -3236,7 +3231,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. @@ -3261,7 +3256,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. @@ -3284,7 +3279,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 @@ -3331,7 +3326,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. @@ -3359,7 +3354,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"])) @@ -3432,7 +3427,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. @@ -3462,7 +3457,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. @@ -3602,7 +3597,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. @@ -3788,7 +3783,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. @@ -4036,8 +4031,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. @@ -4087,14 +4082,14 @@ async def edit_role_positions( if not isinstance(positions, dict): raise TypeError("positions parameter expects a dict.") - 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) @@ -4622,7 +4617,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. @@ -4660,10 +4655,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 @@ -4738,7 +4733,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 @@ -4777,7 +4772,7 @@ async def search_members( raise ValueError("limit must be at least 1") 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: @@ -4787,11 +4782,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. @@ -4830,8 +4825,8 @@ async def get_or_fetch_members( if presences and not self._state._intents.presences: raise ClientException("Intents.presences must be enabled to use this.") - 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) @@ -4870,7 +4865,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. @@ -4949,7 +4944,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. @@ -5050,7 +5045,7 @@ async def timeout( if not (duration is MISSING) ^ (until is MISSING): raise ValueError("Exactly one of `duration` and `until` must be provided") - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} if duration is not MISSING: if duration is None: @@ -5093,7 +5088,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. @@ -5329,7 +5324,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. @@ -5447,8 +5442,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 @@ -5472,12 +5467,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, @@ -5486,7 +5481,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( @@ -5658,7 +5653,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. @@ -5685,7 +5680,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, @@ -5745,7 +5740,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 e6c7ec81b0..f11689cbbb 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 27bded9ff5..033d534553 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 70e7f549ce..fb2f39835e 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, @@ -107,7 +101,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": @@ -119,7 +113,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 @@ -139,11 +133,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( { @@ -159,8 +153,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`` @@ -211,7 +205,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: @@ -280,7 +274,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 @@ -292,7 +286,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, } @@ -324,7 +318,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): @@ -505,7 +499,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, @@ -534,7 +528,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, @@ -544,7 +538,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 @@ -590,7 +584,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 @@ -631,7 +625,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, @@ -640,7 +634,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: @@ -674,7 +668,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, @@ -726,7 +720,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( @@ -784,7 +778,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}", @@ -793,7 +787,7 @@ def get_reaction_users( emoji=emoji, ) - params: Dict[str, Any] = { + params: dict[str, Any] = { "limit": limit, } if after: @@ -844,8 +838,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, } @@ -905,7 +899,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 @@ -916,7 +910,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}) @@ -953,7 +947,7 @@ def unban( def bulk_ban( self, - user_ids: List[Snowflake], + user_ids: list[Snowflake], guild_id: Snowflake, *, delete_message_seconds: int = 0, @@ -967,7 +961,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( @@ -991,7 +985,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( @@ -1021,12 +1015,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 @@ -1098,7 +1092,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]: @@ -1257,7 +1251,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 @@ -1271,7 +1265,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 @@ -1292,7 +1286,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) @@ -1346,7 +1340,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: @@ -1355,10 +1349,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]: @@ -1387,8 +1381,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), } @@ -1418,8 +1412,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, @@ -1492,7 +1486,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( @@ -1508,7 +1502,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", @@ -1544,8 +1538,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 @@ -1569,7 +1563,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, @@ -1586,13 +1580,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: @@ -1618,11 +1612,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", } @@ -1639,9 +1633,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: @@ -1660,7 +1654,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( @@ -1695,7 +1689,7 @@ def create_guild_sticker( finally: file.reset() - form: List[Dict[str, Any]] = [ + form: list[dict[str, Any]] = [ { "name": "file", "value": file.fp, @@ -1761,7 +1755,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]: @@ -1772,7 +1766,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, } @@ -1783,7 +1777,7 @@ def create_app_emoji(self, app_id: Snowflake, name: str, image: str) -> Response 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, } @@ -1811,7 +1805,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 [], @@ -1837,7 +1831,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( @@ -1845,7 +1839,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) @@ -1905,7 +1899,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: @@ -1925,7 +1919,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), @@ -1956,7 +1950,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, @@ -1991,10 +1985,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]: @@ -2009,7 +2003,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( @@ -2047,7 +2041,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]: @@ -2062,10 +2056,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) @@ -2192,7 +2186,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) @@ -2206,14 +2200,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, @@ -2285,8 +2279,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 @@ -2335,7 +2329,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) ) @@ -2359,7 +2353,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, @@ -2431,7 +2425,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) ) @@ -2449,8 +2443,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), @@ -2491,8 +2485,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: @@ -2531,7 +2525,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, @@ -2578,8 +2572,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) @@ -2632,8 +2626,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) @@ -2645,8 +2639,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) @@ -2723,8 +2717,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", @@ -2740,14 +2734,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: @@ -2776,7 +2770,7 @@ def create_interaction_response( interaction_id=interaction_id, interaction_token=token, ) - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "type": type, } @@ -2804,9 +2798,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", @@ -2838,10 +2832,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( @@ -2868,9 +2862,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", @@ -2904,7 +2898,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", @@ -2930,7 +2924,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( @@ -2967,7 +2961,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, } @@ -3035,7 +3029,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: @@ -3048,7 +3042,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]: @@ -3056,7 +3050,7 @@ def application_info(self) -> 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", @@ -3069,7 +3063,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", @@ -3089,7 +3083,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 5404942371..e291db6f41 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) @@ -138,7 +134,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) @@ -182,7 +178,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 @@ -230,7 +226,7 @@ def _copy(self) -> LocalizationValue: return ins @property - def data(self) -> Optional[Dict[str, str]]: + def data(self) -> Optional[dict[str, str]]: """Optional[Dict[:class:`str`, :class:`str`]]: 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. @@ -263,7 +259,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 @@ -323,10 +319,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 @@ -411,7 +407,7 @@ def _load_file(self, path: Path) -> None: except Exception as e: raise RuntimeError(f"Unable to load '{path}': {e}") 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 0bd92a762c..32a36a0ef9 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): raise TypeError("expire_behaviour field must be of type ExpireBehaviour") @@ -415,13 +415,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 3538c341c8..2d04d924a7 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]: """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]: """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 0f2c2966f9..231dbb6dd0 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: @@ -986,9 +982,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, @@ -1087,7 +1083,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, } @@ -1195,10 +1191,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, @@ -1429,7 +1425,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: @@ -1552,7 +1548,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], ), } @@ -1729,7 +1725,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] = ..., @@ -1744,8 +1740,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] = ..., @@ -1759,9 +1755,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] = ..., @@ -1775,9 +1771,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] = ..., @@ -1791,10 +1787,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, @@ -1982,7 +1978,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 @@ -2020,12 +2016,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 704fd3ae67..d097a48ac1 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]]: """Optional[List[:class:`str`]]: 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) @@ -189,7 +190,7 @@ def component(self) -> ActionRowMessageComponent: raise Exception("MessageInteraction is malformed - no component found") # 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 @@ -220,7 +221,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 220725ed24..f476347ef3 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]: """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 5f7ea64e8a..49495ad892 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 8146380058..d62beda670 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, @@ -118,7 +114,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: @@ -128,13 +124,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: @@ -207,7 +203,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 ) @@ -357,35 +353,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 @@ -474,20 +470,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) @@ -599,7 +595,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) @@ -749,14 +745,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): @@ -765,10 +761,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): @@ -905,7 +901,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: @@ -1006,7 +1002,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, @@ -1023,7 +1019,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, @@ -1052,7 +1048,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, @@ -1070,7 +1066,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 @@ -1121,7 +1117,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, @@ -1139,7 +1135,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, @@ -1225,7 +1221,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, @@ -1241,7 +1237,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, @@ -1348,7 +1344,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 fb05bffbc2..c98bc7c23c 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]: """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( @@ -1045,7 +1041,7 @@ async def edit( if self.voice is None or self.voice.channel is None: raise Exception("Cannot suppress a member which isn't in a vc") # 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 a5d867bc47..1e9070ee98 100644 --- a/disnake/mentions.py +++ b/disnake/mentions.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, List, Union +from typing import TYPE_CHECKING, Any, Union from .enums import MessageType @@ -69,8 +69,8 @@ def __init__( self, *, everyone: bool = default, - users: Union[bool, List[Snowflake]] = default, - roles: Union[bool, List[Snowflake]] = default, + users: Union[bool, list[Snowflake]] = default, + roles: Union[bool, list[Snowflake]] = default, replied_user: bool = default, ) -> None: self.everyone = everyone @@ -119,7 +119,7 @@ def from_message(cls, message: Message) -> Self: ) def to_dict(self) -> AllowedMentionsPayload: - parse: List[AllowedMentionTypePayload] = [] + parse: list[AllowedMentionTypePayload] = [] data: AllowedMentionsPayload = {} # type: ignore if self.everyone: diff --git a/disnake/message.py b/disnake/message.py index ab6d47aaf2..d82d08d860 100644 --- a/disnake/message.py +++ b/disnake/message.py @@ -13,11 +13,7 @@ Any, Callable, ClassVar, - Dict, - List, Optional, - Tuple, - Type, Union, cast, overload, @@ -118,8 +114,7 @@ def convert_emoji_reaction(emoji: Union[EmojiInputType, Reaction]) -> str: 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) @@ -138,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, @@ -165,7 +160,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) @@ -956,7 +951,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) @@ -1157,13 +1152,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, @@ -1176,13 +1171,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 @@ -1200,10 +1195,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", []) ] @@ -1255,7 +1250,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"), @@ -1386,10 +1381,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: @@ -1419,7 +1414,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 @@ -1436,7 +1431,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): @@ -1444,7 +1439,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: @@ -1459,7 +1454,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]: """List[:class:`int`]: A property that returns an array of user IDs matched with the syntax of ``<@user_id>`` in the message content. @@ -1469,21 +1464,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]: """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]: """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]: """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. """ @@ -1794,7 +1789,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 @@ -1883,7 +1878,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] = ..., @@ -1898,8 +1893,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] = ..., @@ -1913,9 +1908,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] = ..., @@ -1929,9 +1924,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] = ..., @@ -1945,10 +1940,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, @@ -2655,7 +2650,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] = ..., @@ -2670,8 +2665,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] = ..., @@ -2685,9 +2680,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] = ..., @@ -2701,9 +2696,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] = ..., @@ -2717,10 +2712,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, @@ -2955,10 +2950,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"]) @@ -2966,15 +2961,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: @@ -2988,7 +2983,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 ae2407d644..cc8026b9a3 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 @@ -53,7 +54,7 @@ def __init__(self, stream: IO[bytes]) -> None: except Exception: raise OggError("bad data stream") 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 069e0fb7fa..e2943dbd2b 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]: """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]: """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]: """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 b68c17ce34..e2f66c5c06 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 167fb6589e..4e657fedae 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), @@ -255,7 +255,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 e0d78cec05..a63c787966 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, ) @@ -1218,8 +1215,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 @@ -1295,7 +1292,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]: """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 5117896e12..e987e0fec8 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 @@ -444,7 +444,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: @@ -511,10 +511,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. @@ -585,7 +585,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, @@ -614,7 +614,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 39f4140945..bae0d8908b 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 @@ -241,7 +241,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__( f"Expected 'str' or 'PollMedia' for 'question', got {question.__class__.__name__!r}." ) - 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 @@ -277,7 +277,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]: """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 92af91b993..1f44254d94 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 461a11abd2..2672731f1d 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 @@ -484,7 +484,7 @@ def mention(self) -> str: return f"<@&{self.id}>" @property - def members(self) -> List[Member]: + def members(self) -> list[Member]: """List[:class:`Member`]: Returns all the members with this role.""" all_members = self.guild.members if self.is_default(): @@ -515,7 +515,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) @@ -625,9 +625,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 c17a05400d..7dc5d50a2b 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]]: """List[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]: """Mapping[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 0d1d701dac..cc594e4c36 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 06c8400d02..72ebba558e 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) @@ -236,7 +231,7 @@ def __init__( raise TypeError("allowed_mentions parameter must be AllowedMentions.") 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): @@ -303,14 +298,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) @@ -318,19 +313,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(): @@ -371,7 +366,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]: @@ -439,7 +434,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]: @@ -531,15 +526,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]: @@ -555,7 +550,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]: @@ -623,7 +618,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") @@ -664,10 +659,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) @@ -1440,16 +1435,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: @@ -1525,7 +1520,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 ) @@ -2104,7 +2099,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 @@ -2273,7 +2268,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, @@ -2312,8 +2307,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] @@ -2327,7 +2322,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, @@ -2373,8 +2368,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 @@ -2389,7 +2384,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, @@ -2410,7 +2405,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: @@ -2478,7 +2473,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: @@ -2491,7 +2486,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 @@ -2522,8 +2517,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 58303c2162..09b17b9cb3 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"] @@ -326,7 +326,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 = [] @@ -509,7 +509,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 bf86e1a35a..1beead048d 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 a1f126304e..e918180b62 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 e0b998d2bb..36c77c5858 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 @@ -60,7 +60,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 d02b5ba06f..a746a7290c 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]: """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, @@ -398,7 +399,7 @@ def is_pinned(self) -> bool: return self.flags.pinned @property - def applied_tags(self) -> List[ForumTag]: + def applied_tags(self) -> list[ForumTag]: """List[:class:`ForumTag`]: The tags currently applied to this thread. Only applicable to threads in channels of type :class:`ForumChannel` or :class:`MediaChannel`. @@ -556,7 +557,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 @@ -617,7 +618,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 @@ -876,7 +877,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. @@ -953,7 +954,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) @@ -991,7 +992,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 639972fab0..f20cac300f 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 @@ -28,7 +28,7 @@ class BaseAppInfo(TypedDict): class InstallParams(TypedDict): - scopes: List[str] + scopes: list[str] permissions: str @@ -37,7 +37,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] @@ -47,24 +47,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[str] - 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 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 6e0347bfeb..d17628d8cb 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 f9f056bcb9..36509590d5 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( 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 @@ -954,7 +947,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. @@ -1010,7 +1003,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 @@ -1053,24 +1046,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 @@ -1111,12 +1104,12 @@ def walk_components(components: Sequence[ComponentT]) -> Iterator[ComponentT]: Union[: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 @@ -1140,11 +1133,11 @@ def components_from_message(message: Message) -> List[MessageTopLevelComponent]: 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 bb16ca9485..20a9580e3c 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 f061d496ea..9ddb5ae019 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 @@ -129,7 +129,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 4ed1e7a476..2c2c8d97f1 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 a529f02693..2328ff8c95 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, ) @@ -71,7 +68,7 @@ class UIComponent(ABC): .. versionadded:: 2.11 """ - __repr_attributes__: ClassVar[Tuple[str, ...]] + __repr_attributes__: ClassVar[tuple[str, ...]] @property @abstractmethod @@ -105,7 +102,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 @@ -158,7 +155,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: ... @@ -231,7 +228,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 ccde945bf1..fa3dc6d1e6 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 a876c06d0d..70d1a1d78f 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]: """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 5a53898a5e..7067c7dea7 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 @@ -102,7 +102,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 @@ -117,7 +117,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. @@ -255,7 +255,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], ), } @@ -315,7 +315,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 fb30771da8..759c32cca8 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 def5bd1e65..4e0c303b4c 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( @@ -163,7 +159,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]: """List[:class:`.SelectDefaultValue`]: The list of values that are selected by default. Only available for auto-populated select menus. """ @@ -189,7 +185,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 @@ -217,8 +213,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 cf21fe393d..5a022b9fa5 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]]: """Optional[List[:class:`disnake.ChannelType`]]: 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): raise TypeError("channel_types must be a list of ChannelType") @@ -216,7 +212,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 a45f9eeff1..0968aac017 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 b77b87dcea..8912b6f7f1 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 7004c59d67..5d73d5655a 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]: """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): raise TypeError("options must be a list of SelectOption") if not all(isinstance(obj, SelectOption) for obj in value): diff --git a/disnake/ui/select/user.py b/disnake/ui/select/user.py index bd5d894352..997bca915a 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 497499dc21..b3da61d41c 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 b7c1b376ea..e80ff4e0b1 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 cac0872a02..c03e8e2245 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) @@ -114,10 +115,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__"): @@ -130,7 +131,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 @@ -166,12 +167,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: @@ -387,15 +388,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: @@ -483,9 +484,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 @@ -494,7 +495,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 e6b4d24a6e..15ea20ca9b 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]: """List[:class:`Guild`]: The guilds that the user shares with the client. .. note:: diff --git a/disnake/utils.py b/disnake/utils.py index 5d7709f813..fd8b130777 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: @@ -504,7 +494,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)) @@ -631,7 +621,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) @@ -641,7 +631,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): @@ -754,12 +744,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 @@ -955,7 +945,7 @@ class _DocstringParam(_DocstringLocalizationsMixin): class _ParsedDocstring(_DocstringLocalizationsMixin): description: str - params: Dict[str, _DocstringParam] + params: dict[str, _DocstringParam] def _count_left_spaces(string: str) -> int: @@ -967,7 +957,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): @@ -975,7 +965,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() @@ -990,12 +980,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() @@ -1004,15 +994,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 @@ -1031,7 +1021,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]: @@ -1077,7 +1067,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: @@ -1091,7 +1081,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: @@ -1106,14 +1096,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 @@ -1151,7 +1141,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: @@ -1161,13 +1151,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__): @@ -1186,9 +1176,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: @@ -1270,9 +1260,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) @@ -1296,7 +1286,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__ @@ -1309,16 +1299,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()) @@ -1532,7 +1522,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 0e12e09fed..53decdb057 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 @@ -228,7 +228,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,9 +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 = self.endpoint.removeprefix("wss://") # This gets set later self.endpoint_ip = MISSING @@ -517,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 432afe025c..1f6585a2c8 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 @@ -257,7 +253,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, @@ -269,7 +265,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, @@ -288,9 +284,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, @@ -318,7 +314,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 @@ -338,12 +334,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 @@ -367,7 +363,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 @@ -412,8 +408,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", @@ -422,7 +418,7 @@ def create_interaction_response( webhook_token=token, ) - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "type": type, } @@ -457,9 +453,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", @@ -486,14 +482,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( @@ -506,10 +502,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, @@ -613,10 +609,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, @@ -800,10 +796,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, @@ -962,7 +958,7 @@ async def inner_call(delay: float = delay) -> None: class BaseWebhook(Hashable): - __slots__: Tuple[str, ...] = ( + __slots__: tuple[str, ...] = ( "id", "type", "guild_id", @@ -1163,7 +1159,7 @@ async def foo(): .. versionadded:: 2.6 """ - __slots__: Tuple[str, ...] = ("session",) + __slots__: tuple[str, ...] = ("session",) def __init__( self, @@ -1266,7 +1262,7 @@ def from_url( if m is None: raise ValueError("Invalid webhook URL given.") - data: Dict[str, Any] = m.groupdict() + data: dict[str, Any] = m.groupdict() data["type"] = 1 return cls(data, session, token=bot_token) # type: ignore @@ -1454,7 +1450,7 @@ async def edit( if self.token is None and self.auth_token is None: raise WebhookTokenMissing("This webhook does not have a token associated with it") - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} if name is not MISSING: payload["name"] = str(name) if name is not None else None @@ -1531,9 +1527,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 = ..., @@ -1557,9 +1553,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 = ..., @@ -1582,9 +1578,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, @@ -1899,10 +1895,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 1da14d4ff0..e5f070b266 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 @@ -247,7 +243,7 @@ def edit_webhook( self, webhook_id: int, token: str, - payload: Dict[str, Any], + payload: dict[str, Any], *, session: Session, reason: Optional[str] = None, @@ -259,7 +255,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, @@ -279,9 +275,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: ... @@ -293,9 +289,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: ... @@ -306,9 +302,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]: @@ -335,7 +331,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 @@ -355,12 +351,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 @@ -384,7 +380,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 @@ -454,10 +450,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. @@ -629,7 +625,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 @@ -726,7 +722,7 @@ def from_url( if m is None: raise ValueError("Invalid webhook URL given.") - data: Dict[str, Any] = m.groupdict() + data: dict[str, Any] = m.groupdict() data["type"] = 1 import requests @@ -872,7 +868,7 @@ def edit( if self.token is None and self.auth_token is None: raise WebhookTokenMissing("This webhook does not have a token associated with it") - payload: Dict[str, Any] = {} + payload: dict[str, Any] = {} if name is not MISSING: payload["name"] = str(name) if name is not None else None @@ -932,9 +928,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 = ..., @@ -953,9 +949,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 = ..., @@ -973,9 +969,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, @@ -1198,10 +1194,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 a2e2fa171c..f56fd37e71 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 @@ -125,7 +125,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"] ] @@ -145,7 +145,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 386b546b0a..c37acd3819 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 40b4b3dc7d..34096eb0c3 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 @@ -207,7 +207,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 4589d73e6d..5ca24f507e 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 @@ -103,7 +103,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: @@ -117,7 +117,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:
@@ -154,10 +154,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 = { @@ -209,12 +209,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"): [], } @@ -263,7 +263,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 d5d4f62ba8..b11aa3a50f 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 6d192b58ce..cc76c12822 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,10 +31,10 @@ PYPROJECT = nox.project.load_toml() -SUPPORTED_PYTHONS: Final[List[str]] = nox.project.python_versions(PYPROJECT) +SUPPORTED_PYTHONS: Final[list[str]] = nox.project.python_versions(PYPROJECT) # TODO(onerandomusername): add 3.14 once CI supports 3.14. -EXPERIMENTAL_PYTHON_VERSIONS: Final[List[str]] = [] -ALL_PYTHONS: Final[List[str]] = [*SUPPORTED_PYTHONS, *EXPERIMENTAL_PYTHON_VERSIONS] +EXPERIMENTAL_PYTHON_VERSIONS: Final[list[str]] = [] +ALL_PYTHONS: Final[list[str]] = [*SUPPORTED_PYTHONS, *EXPERIMENTAL_PYTHON_VERSIONS] MIN_PYTHON: Final[str] = SUPPORTED_PYTHONS[0] CI: Final[bool] = "CI" in os.environ @@ -47,19 +44,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( @@ -125,7 +122,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] @@ -150,7 +147,7 @@ def install_deps(session: nox.Session, *, execution_group: Optional[ExecutionGro if not execution_group.project and execution_group.extras: raise TypeError("Cannot install extras without also installing the project") - command: List[str] + command: list[str] # If not using uv, install with pip if os.getenv("INSTALL_WITH_PIP") is not None: @@ -177,7 +174,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}") @@ -287,7 +284,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/scripts/ci/versiontool.py b/scripts/ci/versiontool.py index 74855911f0..2b17943717 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") @@ -66,7 +66,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 f0c892013d..3f7effd43d 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 827dc1149d..0f3af98c13 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: @@ -38,7 +38,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 4bb389b0c9..bee16fffec 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 28a8dd54ed..6d712c0a81 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 ff5d01b452..9f15271fb7 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 4fcbf5bf01..7b0d37bc33 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..fdbe639f0d 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"]) From 6c0aa526a0f75768450d5d94fbaf24288f1f3e2b Mon Sep 17 00:00:00 2001 From: onerandomusername Date: Sat, 20 Sep 2025 18:50:46 -0400 Subject: [PATCH 3/6] fix: still have to test old annotations --- tests/test_utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index fdbe639f0d..7fa684ba69 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -9,12 +9,14 @@ import warnings from dataclasses import dataclass from datetime import timedelta, timezone -from typing import ( +from typing import ( # noqa: UP035 TYPE_CHECKING, Any, Callable, + List, Literal, Optional, + Tuple, TypeVar, Union, ) @@ -787,7 +789,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), # noqa: UP006 # 3.10 union syntax pytest.param( "int | float", From fc1b782af13d5a609d59bec6415cd88b7971cb1e Mon Sep 17 00:00:00 2001 From: arielle Date: Sun, 21 Sep 2025 03:07:06 -0400 Subject: [PATCH 4/6] chore: add changelog --- changelog/1394.breaking.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/1394.breaking.rst diff --git a/changelog/1394.breaking.rst b/changelog/1394.breaking.rst new file mode 100644 index 0000000000..bab57b3203 --- /dev/null +++ b/changelog/1394.breaking.rst @@ -0,0 +1 @@ +Python 3.8 support has been dropped. From a7a87c1e3c06e8337748ea7afa088f8220bffff4 Mon Sep 17 00:00:00 2001 From: arielle Date: Sun, 21 Sep 2025 16:02:59 -0400 Subject: [PATCH 5/6] revert typing changes --- disnake/__main__.py | 6 +- disnake/abc.py | 52 +++-- disnake/activity.py | 18 +- disnake/app_commands.py | 49 ++-- disnake/appinfo.py | 14 +- disnake/asset.py | 6 +- disnake/audit_logs.py | 29 ++- disnake/automod.py | 21 +- disnake/bans.py | 3 +- disnake/channel.py | 104 +++++---- disnake/client.py | 82 +++---- disnake/colour.py | 6 +- disnake/components.py | 100 +++++---- disnake/context_managers.py | 6 +- disnake/embeds.py | 13 +- disnake/emoji.py | 11 +- disnake/enums.py | 27 ++- disnake/errors.py | 11 +- disnake/ext/commands/_types.py | 3 +- disnake/ext/commands/base_core.py | 13 +- disnake/ext/commands/bot.py | 15 +- disnake/ext/commands/bot_base.py | 17 +- disnake/ext/commands/cog.py | 46 ++-- disnake/ext/commands/common_bot_base.py | 15 +- disnake/ext/commands/context.py | 14 +- disnake/ext/commands/converter.py | 32 +-- disnake/ext/commands/cooldowns.py | 8 +- disnake/ext/commands/core.py | 53 +++-- disnake/ext/commands/ctx_menus_core.py | 11 +- disnake/ext/commands/errors.py | 32 +-- disnake/ext/commands/flag_converter.py | 51 +++-- disnake/ext/commands/help.py | 33 +-- disnake/ext/commands/interaction_bot_base.py | 53 +++-- disnake/ext/commands/params.py | 89 ++++---- disnake/ext/commands/slash_core.py | 57 ++--- disnake/ext/mypy_plugin/__init__.py | 4 +- disnake/ext/tasks/__init__.py | 27 ++- disnake/flags.py | 27 ++- disnake/gateway.py | 25 ++- disnake/guild.py | 175 ++++++++------- disnake/guild_preview.py | 10 +- disnake/guild_scheduled_event.py | 4 +- disnake/http.py | 224 ++++++++++--------- disnake/i18n.py | 22 +- disnake/integrations.py | 8 +- disnake/interactions/application_command.py | 23 +- disnake/interactions/base.py | 76 ++++--- disnake/interactions/message.py | 11 +- disnake/interactions/modal.py | 13 +- disnake/invite.py | 6 +- disnake/iterators.py | 70 +++--- disnake/member.py | 28 ++- disnake/mentions.py | 8 +- disnake/message.py | 113 +++++----- disnake/oggparse.py | 5 +- disnake/onboarding.py | 18 +- disnake/opus.py | 11 +- disnake/partial_emoji.py | 6 +- disnake/permissions.py | 15 +- disnake/player.py | 12 +- disnake/poll.py | 8 +- disnake/raw_models.py | 6 +- disnake/role.py | 10 +- disnake/shard.py | 14 +- disnake/soundboard.py | 4 +- disnake/state.py | 101 +++++---- disnake/sticker.py | 8 +- disnake/subscription.py | 8 +- disnake/team.py | 4 +- disnake/template.py | 4 +- disnake/threads.py | 21 +- disnake/types/activity.py | 8 +- disnake/types/appinfo.py | 16 +- disnake/types/audit_log.py | 36 +-- disnake/types/automod.py | 16 +- disnake/types/channel.py | 14 +- disnake/types/components.py | 18 +- disnake/types/embed.py | 4 +- disnake/types/emoji.py | 4 +- disnake/types/gateway.py | 39 ++-- disnake/types/guild.py | 36 +-- disnake/types/i18n.py | 3 +- disnake/types/integration.py | 4 +- disnake/types/interactions.py | 62 ++--- disnake/types/message.py | 30 +-- disnake/types/onboarding.py | 6 +- disnake/types/poll.py | 10 +- disnake/types/snowflake.py | 4 +- disnake/types/soundboard.py | 4 +- disnake/types/sticker.py | 6 +- disnake/types/subscription.py | 8 +- disnake/types/team.py | 4 +- disnake/types/threads.py | 6 +- disnake/types/voice.py | 4 +- disnake/types/welcome_screen.py | 4 +- disnake/types/widget.py | 6 +- disnake/ui/_types.py | 3 +- disnake/ui/action_row.py | 43 ++-- disnake/ui/button.py | 4 +- disnake/ui/container.py | 8 +- disnake/ui/file.py | 4 +- disnake/ui/item.py | 13 +- disnake/ui/label.py | 4 +- disnake/ui/media_gallery.py | 7 +- disnake/ui/modal.py | 10 +- disnake/ui/section.py | 8 +- disnake/ui/select/base.py | 22 +- disnake/ui/select/channel.py | 22 +- disnake/ui/select/mentionable.py | 7 +- disnake/ui/select/role.py | 7 +- disnake/ui/select/string.py | 18 +- disnake/ui/select/user.py | 7 +- disnake/ui/separator.py | 4 +- disnake/ui/text_display.py | 4 +- disnake/ui/text_input.py | 4 +- disnake/ui/thumbnail.py | 4 +- disnake/ui/view.py | 29 ++- disnake/user.py | 6 +- disnake/utils.py | 88 ++++---- disnake/voice_client.py | 12 +- disnake/webhook/async_.py | 110 ++++----- disnake/webhook/sync.py | 90 ++++---- disnake/welcome_screen.py | 6 +- disnake/widget.py | 8 +- docs/conf.py | 4 +- docs/extensions/attributetable.py | 18 +- docs/extensions/collapse.py | 4 +- docs/extensions/exception_hierarchy.py | 4 +- docs/extensions/fulltoc.py | 4 +- docs/extensions/redirects.py | 6 +- docs/extensions/resourcelinks.py | 10 +- examples/basic_voice.py | 4 +- examples/interactions/autocomplete.py | 3 +- examples/views/button/paginator.py | 3 +- examples/views/tic_tac_toe.py | 6 +- noxfile.py | 33 +-- pyproject.toml | 4 + scripts/ci/versiontool.py | 4 +- scripts/codemods/base.py | 3 +- scripts/codemods/overloads_no_missing.py | 5 +- scripts/codemods/typed_flags.py | 6 +- scripts/codemods/typed_permissions.py | 4 +- tests/ext/tasks/test_loops.py | 4 +- tests/helpers.py | 7 +- tests/test_colour.py | 7 +- tests/test_mentions.py | 4 +- tests/test_permissions.py | 18 +- tests/test_utils.py | 29 +-- tests/ui/test_components.py | 5 +- tests/ui/test_decorators.py | 7 +- tests/utils_helper_module.py | 8 +- 151 files changed, 1764 insertions(+), 1583 deletions(-) diff --git a/disnake/__main__.py b/disnake/__main__.py index 06fac9941f..e1a5d2cdfd 100644 --- a/disnake/__main__.py +++ b/disnake/__main__.py @@ -5,7 +5,7 @@ import platform import sys from pathlib import Path -from typing import Union +from typing import List, Tuple, 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 820a64055d..1cc6b95d6d 100644 --- a/disnake/abc.py +++ b/disnake/abc.py @@ -5,13 +5,17 @@ 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, @@ -260,7 +264,7 @@ class GuildChannel(ABC): category_id: Optional[int] _flags: int _state: ConnectionState - _overwrites: list[_Overwrites] + _overwrites: List[_Overwrites] if TYPE_CHECKING: @@ -275,7 +279,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( @@ -292,7 +296,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) @@ -309,7 +313,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: @@ -375,7 +379,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( @@ -424,7 +428,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] @@ -449,7 +453,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, @@ -501,11 +505,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]: """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) @@ -558,7 +562,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 @@ -1031,7 +1035,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, @@ -1040,7 +1044,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): raise TypeError("overwrites parameter expects a dict.") @@ -1246,7 +1250,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 @@ -1269,7 +1273,7 @@ async def move(self, **kwargs: Any) -> None: raise ValueError("Could not resolve appropriate move position") 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): @@ -1375,7 +1379,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. @@ -1451,7 +1455,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] = ..., @@ -1471,7 +1475,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 = ..., @@ -1492,8 +1496,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] = ..., @@ -1513,9 +1517,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, @@ -2011,10 +2015,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 0ce45c02c8..2bda908a4f 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, Literal, Optional, Union, overload +from typing import TYPE_CHECKING, Any, Dict, List, 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]: """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 e475e45b8b..e5fca96792 100644 --- a/disnake/app_commands.py +++ b/disnake/app_commands.py @@ -5,8 +5,7 @@ import math import re from abc import ABC -from collections.abc import Mapping, Sequence -from typing import TYPE_CHECKING, ClassVar, Optional, Union, cast +from typing import TYPE_CHECKING, ClassVar, List, Mapping, Optional, Sequence, Tuple, Union, cast from .enums import ( ApplicationCommandPermissionType, @@ -266,8 +265,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 +284,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) @@ -301,9 +300,9 @@ def __init__( if channel_types is not None and not all(isinstance(t, ChannelType) for t in channel_types): raise TypeError("channel_types must be a list of `ChannelType`s") - 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: raise TypeError("can not specify both choices and autocomplete args") @@ -396,8 +395,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, @@ -509,7 +508,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", @@ -703,15 +702,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 ) @@ -731,7 +730,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): @@ -781,7 +780,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" ) @@ -847,7 +846,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__, ) @@ -909,7 +908,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" ) @@ -975,7 +974,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__, ) @@ -1047,7 +1046,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", @@ -1057,7 +1056,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, @@ -1079,7 +1078,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 ( @@ -1097,7 +1096,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, @@ -1195,7 +1194,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__, ) @@ -1310,7 +1309,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 e4fc566a8a..f24bbe69c5 100644 --- a/disnake/appinfo.py +++ b/disnake/appinfo.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional, cast +from typing import TYPE_CHECKING, Dict, List, Optional, cast from . import utils from .asset import Asset @@ -282,7 +282,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"]) @@ -305,12 +305,12 @@ 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(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" @@ -319,7 +319,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( @@ -327,7 +327,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(): @@ -446,7 +446,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 970104e9f1..6a9e1e3f0a 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, Union +from typing import TYPE_CHECKING, Any, Literal, Optional, Tuple, 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| @@ -190,7 +190,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 bd2442469e..6e81652792 100644 --- a/disnake/audit_logs.py +++ b/disnake/audit_logs.py @@ -2,13 +2,18 @@ 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, @@ -112,9 +117,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"])) @@ -194,7 +199,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) @@ -202,7 +207,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 @@ -212,8 +217,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] @@ -289,7 +294,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: @@ -308,7 +313,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), @@ -362,7 +367,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() @@ -435,7 +440,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 3a9071d8f7..35b0e82fed 100644 --- a/disnake/automod.py +++ b/disnake/automod.py @@ -3,10 +3,15 @@ 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, ) @@ -466,18 +471,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() @@ -492,7 +497,7 @@ def created_at(self) -> datetime.datetime: return snowflake_time(self.id) @property - def actions(self) -> list[AutoModAction]: + def actions(self) -> List[AutoModAction]: """List[Union[:class:`AutoModBlockMessageAction`, :class:`AutoModSendAlertAction`, :class:`AutoModTimeoutAction`, :class:`AutoModAction`]]: The list of actions that will execute if a matching event triggered this rule. """ @@ -506,12 +511,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]: """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]: """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))) @@ -786,7 +791,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 d8bfdba791..3f05cfb76d 100644 --- a/disnake/bans.py +++ b/disnake/bans.py @@ -2,8 +2,7 @@ from __future__ import annotations -from collections.abc import Sequence -from typing import TYPE_CHECKING, NamedTuple, Optional +from typing import TYPE_CHECKING, NamedTuple, Optional, Sequence __all__ = ("BanEntry",) diff --git a/disnake/channel.py b/disnake/channel.py index e5e3a9b74f..ab036d0f58 100644 --- a/disnake/channel.py +++ b/disnake/channel.py @@ -5,14 +5,20 @@ 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, @@ -334,14 +340,14 @@ def permissions_for( return base @property - def members(self) -> list[Member]: + def members(self) -> List[Member]: """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]: """List[:class:`Thread`]: Returns all the threads that you can see. .. versionadded:: 2.0 @@ -710,7 +716,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 @@ -771,7 +777,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 @@ -812,7 +818,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. @@ -1188,10 +1194,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: @@ -1216,12 +1222,12 @@ def _sorting_bucket(self) -> int: return ChannelType.voice.value @property - def members(self) -> list[Member]: + def members(self) -> List[Member]: """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) @@ -1230,7 +1236,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 @@ -1763,7 +1769,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 @@ -1820,7 +1826,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 @@ -1861,7 +1867,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. @@ -2077,7 +2083,7 @@ async def _get_channel(self) -> Self: return self @property - def requesting_to_speak(self) -> list[Member]: + def requesting_to_speak(self) -> List[Member]: """List[:class:`Member`]: A list of members who are requesting to speak in the stage channel.""" return [ member @@ -2086,7 +2092,7 @@ def requesting_to_speak(self) -> list[Member]: ] @property - def speakers(self) -> list[Member]: + def speakers(self) -> List[Member]: """List[:class:`Member`]: A list of members who have been permitted to speak in the stage channel. .. versionadded:: 2.0 @@ -2100,7 +2106,7 @@ def speakers(self) -> list[Member]: ] @property - def listeners(self) -> list[Member]: + def listeners(self) -> List[Member]: """List[:class:`Member`]: A list of members who are listening in the stage channel. .. versionadded:: 2.0 @@ -2108,7 +2114,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]: """List[:class:`Member`]: A list of members who are moderating the stage channel. .. versionadded:: 2.0 @@ -2345,7 +2351,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, @@ -2618,7 +2624,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 @@ -2675,7 +2681,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 @@ -2716,7 +2722,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. @@ -3094,7 +3100,7 @@ async def move(self, **kwargs: Any) -> None: return await super().move(**kwargs) @property - def channels(self) -> list[GuildChannelType]: + def channels(self) -> List[GuildChannelType]: """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. @@ -3102,7 +3108,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, @@ -3113,7 +3119,7 @@ def comparator(channel: GuildChannelType) -> tuple[bool, int]: return ret @property - def text_channels(self) -> list[TextChannel]: + def text_channels(self) -> List[TextChannel]: """List[:class:`TextChannel`]: Returns the text channels that are under this category.""" if isinstance(self.guild, Object): return [] @@ -3127,7 +3133,7 @@ def text_channels(self) -> list[TextChannel]: return ret @property - def voice_channels(self) -> list[VoiceChannel]: + def voice_channels(self) -> List[VoiceChannel]: """List[:class:`VoiceChannel`]: Returns the voice channels that are under this category.""" if isinstance(self.guild, Object): return [] @@ -3141,7 +3147,7 @@ def voice_channels(self) -> list[VoiceChannel]: return ret @property - def stage_channels(self) -> list[StageChannel]: + def stage_channels(self) -> List[StageChannel]: """List[:class:`StageChannel`]: Returns the stage channels that are under this category. .. versionadded:: 1.7 @@ -3158,7 +3164,7 @@ def stage_channels(self) -> list[StageChannel]: return ret @property - def forum_channels(self) -> list[ForumChannel]: + def forum_channels(self) -> List[ForumChannel]: """List[:class:`ForumChannel`]: Returns the forum channels that are under this category. .. versionadded:: 2.5 @@ -3175,7 +3181,7 @@ def forum_channels(self) -> list[ForumChannel]: return ret @property - def media_channels(self) -> list[MediaChannel]: + def media_channels(self) -> List[MediaChannel]: """List[:class:`MediaChannel`]: Returns the media channels that are under this category. .. versionadded:: 2.10 @@ -3351,7 +3357,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 @@ -3392,14 +3398,14 @@ def permissions_for( return base @property - def members(self) -> list[Member]: + def members(self) -> List[Member]: """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]: """List[:class:`Thread`]: Returns all the threads that you can see.""" if isinstance(self.guild, Object): return [] @@ -3459,7 +3465,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]: """List[:class:`ForumTag`]: The available tags for threads in this channel. To create/edit/delete tags, use :func:`edit`. @@ -3530,7 +3536,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]] = ..., @@ -3549,7 +3555,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 = ..., @@ -3569,8 +3575,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]] = ..., @@ -3589,9 +3595,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, @@ -3799,7 +3805,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. @@ -4946,7 +4952,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", []) ] @@ -5129,7 +5135,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 @@ -5151,8 +5157,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: @@ -5165,8 +5171,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) @@ -5177,7 +5183,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 @@ -5185,8 +5191,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 4631d81bf3..5a24514cf4 100644 --- a/disnake/client.py +++ b/disnake/client.py @@ -8,16 +8,22 @@ 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, @@ -164,7 +170,7 @@ class SessionStartLimit: The approximate time at which which the :attr:`.remaining` limit resets. """ - __slots__: tuple[str, ...] = ( + __slots__: Tuple[str, ...] = ( "total", "remaining", "reset_after", @@ -405,7 +411,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( @@ -416,12 +422,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 } @@ -470,7 +476,7 @@ def __init__( if self.gateway_params.encoding != "json": raise ValueError("Gateway encodings other than `json` are currently not supported.") - self.extra_events: dict[str, list[CoroFunc]] = {} + self.extra_events: Dict[str, List[CoroFunc]] = {} # internals @@ -548,17 +554,17 @@ def user(self) -> ClientUser: return self._connection.user @property - def guilds(self) -> list[Guild]: + def guilds(self) -> List[Guild]: """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]: """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]: """List[:class:`.GuildSticker`]: The stickers that the connected client has. .. versionadded:: 2.0 @@ -566,7 +572,7 @@ def stickers(self) -> list[GuildSticker]: return self._connection.stickers @property - def soundboard_sounds(self) -> list[GuildSoundboardSound]: + def soundboard_sounds(self) -> List[GuildSoundboardSound]: """List[:class:`.GuildSoundboardSound`]: The soundboard sounds that the connected client has. .. versionadded:: 2.10 @@ -582,7 +588,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]: """List[:class:`.abc.PrivateChannel`]: The private channels that the connected client is participating on. .. note:: @@ -593,7 +599,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]: """List[:class:`.VoiceProtocol`]: Represents a list of voice connections. These are usually :class:`.VoiceClient` instances. @@ -621,12 +627,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]: """List[Union[: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]: """List[:class:`.APISlashCommand`]: The client's global slash commands.""" return [ cmd @@ -635,7 +641,7 @@ def global_slash_commands(self) -> list[APISlashCommand]: ] @property - def global_user_commands(self) -> list[APIUserCommand]: + def global_user_commands(self) -> List[APIUserCommand]: """List[:class:`.APIUserCommand`]: The client's global user commands.""" return [ cmd @@ -644,7 +650,7 @@ def global_user_commands(self) -> list[APIUserCommand]: ] @property - def global_message_commands(self) -> list[APIMessageCommand]: + def global_message_commands(self) -> List[APIMessageCommand]: """List[:class:`.APIMessageCommand`]: The client's global message commands.""" return [ cmd @@ -926,7 +932,7 @@ def decorator(func: CoroT) -> CoroT: return decorator - def get_listeners(self) -> Mapping[str, list[CoroFunc]]: + def get_listeners(self) -> Mapping[str, List[CoroFunc]]: """Mapping[:class:`str`, List[Callable]]: A read-only mapping of event names to listeners. .. note:: @@ -1384,7 +1390,7 @@ def intents(self) -> Intents: # helpers/getters @property - def users(self) -> list[User]: + def users(self) -> List[User]: """List[:class:`~disnake.User`]: Returns a list of all the users the bot can see.""" return list(self._connection._users.values()) @@ -1567,7 +1573,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 @@ -1583,7 +1589,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 @@ -1599,7 +1605,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 @@ -1615,7 +1621,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 @@ -2318,7 +2324,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. @@ -2374,7 +2380,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. @@ -2476,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, 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. @@ -2668,7 +2674,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. @@ -2692,7 +2698,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 @@ -2776,7 +2782,7 @@ async def fetch_global_commands( self, *, with_localizations: bool = True, - ) -> list[APIApplicationCommand]: + ) -> List[APIApplicationCommand]: """|coro| Retrieves a list of global application commands. @@ -2913,8 +2919,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. @@ -2942,7 +2948,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. @@ -3095,8 +3101,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. @@ -3123,7 +3129,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. @@ -3163,7 +3169,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. @@ -3185,7 +3191,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. @@ -3214,7 +3220,7 @@ async def edit_role_connection_metadata( 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()) @@ -3224,7 +3230,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 4d9309152a..a203f64063 100644 --- a/disnake/colour.py +++ b/disnake/colour.py @@ -4,7 +4,7 @@ import colorsys import random -from typing import TYPE_CHECKING, Any, Optional, Union +from typing import TYPE_CHECKING, Any, Optional, Tuple, Union if TYPE_CHECKING: from typing_extensions import Self @@ -94,7 +94,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]: """Tuple[:class:`int`, :class:`int`, :class:`int`]: Returns an (r, g, b) tuple representing the colour.""" return (self.r, self.g, self.b) @@ -320,7 +320,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 3b7eb34d62..d66dc8647d 100644 --- a/disnake/components.py +++ b/disnake/components.py @@ -2,15 +2,19 @@ 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, @@ -210,9 +214,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 @@ -236,7 +240,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 @@ -261,16 +265,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 { @@ -320,7 +324,7 @@ class Button(Component): .. versionadded:: 2.11 """ - __slots__: tuple[str, ...] = ( + __slots__: Tuple[str, ...] = ( "style", "custom_id", "url", @@ -330,7 +334,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 @@ -424,7 +428,7 @@ class BaseSelectMenu(Component): .. versionadded:: 2.11 """ - __slots__: tuple[str, ...] = ( + __slots__: Tuple[str, ...] = ( "custom_id", "placeholder", "min_values", @@ -435,7 +439,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" ) @@ -452,7 +456,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) @@ -518,9 +522,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__, ) @@ -528,7 +532,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", []) ] @@ -582,7 +586,7 @@ class UserSelectMenu(BaseSelectMenu): .. versionadded:: 2.11 """ - __slots__: tuple[str, ...] = () + __slots__: Tuple[str, ...] = () type: Literal[ComponentType.user_select] @@ -633,7 +637,7 @@ class RoleSelectMenu(BaseSelectMenu): .. versionadded:: 2.11 """ - __slots__: tuple[str, ...] = () + __slots__: Tuple[str, ...] = () type: Literal[ComponentType.role_select] @@ -684,7 +688,7 @@ class MentionableSelectMenu(BaseSelectMenu): .. versionadded:: 2.11 """ - __slots__: tuple[str, ...] = () + __slots__: Tuple[str, ...] = () type: Literal[ComponentType.mentionable_select] @@ -738,9 +742,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__, ) @@ -750,7 +754,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 ) @@ -786,7 +790,7 @@ class SelectOption: Whether this option is selected by default. """ - __slots__: tuple[str, ...] = ( + __slots__: Tuple[str, ...] = ( "label", "value", "description", @@ -882,7 +886,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 @@ -942,7 +946,7 @@ class TextInput(Component): .. versionadded:: 2.11 """ - __slots__: tuple[str, ...] = ( + __slots__: Tuple[str, ...] = ( "style", "custom_id", "label", @@ -953,7 +957,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 @@ -1020,9 +1024,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 @@ -1030,7 +1034,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", []) ] @@ -1067,9 +1071,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 @@ -1110,7 +1114,7 @@ class UnfurledMediaItem: uploaded as an attachment. """ - __slots__: tuple[str, ...] = ( + __slots__: Tuple[str, ...] = ( "url", "proxy_url", "height", @@ -1175,13 +1179,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 @@ -1230,9 +1234,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 @@ -1240,7 +1244,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 { @@ -1266,7 +1270,7 @@ class MediaGalleryItem: Whether the item is marked as a spoiler. Defaults to ``False``. """ - __slots__: tuple[str, ...] = ( + __slots__: Tuple[str, ...] = ( "media", "description", "spoiler", @@ -1338,9 +1342,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 @@ -1389,9 +1393,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 @@ -1438,13 +1442,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 @@ -1453,7 +1457,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 @@ -1508,13 +1512,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 @@ -1571,7 +1575,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, @@ -1593,7 +1597,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 a26890e819..120c75ffa9 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, Union +from typing import TYPE_CHECKING, Optional, Type, 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 7e039d866d..35cb714660 100644 --- a/disnake/embeds.py +++ b/disnake/embeds.py @@ -3,14 +3,17 @@ 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, @@ -216,9 +219,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: @@ -652,14 +655,14 @@ def remove_author(self) -> Self: return self @property - def fields(self) -> list[_EmbedFieldProxy]: + def fields(self) -> List[_EmbedFieldProxy]: """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 ``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 dc0e768807..e474bbbed3 100644 --- a/disnake/emoji.py +++ b/disnake/emoji.py @@ -2,8 +2,7 @@ from __future__ import annotations -from collections.abc import Iterator -from typing import TYPE_CHECKING, Any, Optional, Union +from typing import TYPE_CHECKING, Any, Iterator, List, Optional, Tuple, Union from .asset import Asset, AssetMixin from .errors import InvalidData @@ -80,7 +79,7 @@ class Emoji(_EmojiTag, AssetMixin): having the :attr:`~Permissions.manage_guild_expressions` permission. """ - __slots__: tuple[str, ...] = ( + __slots__: Tuple[str, ...] = ( "require_colons", "animated", "managed", @@ -117,7 +116,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) @@ -158,7 +157,7 @@ def url(self) -> str: return f"{Asset.BASE}/emojis/{self.id}.{fmt}" @property - def roles(self) -> list[Role]: + def roles(self) -> List[Role]: """List[:class:`Role`]: A :class:`list` of roles that are allowed to use this emoji. If roles is empty, the emoji is unrestricted. @@ -259,7 +258,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 93551ecbe9..7ea1957269 100644 --- a/disnake/enums.py +++ b/disnake/enums.py @@ -2,15 +2,18 @@ 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, ) @@ -79,7 +82,7 @@ "NameplatePalette", ) -EnumMetaT = TypeVar("EnumMetaT", bound="type[EnumMeta]") +EnumMetaT = TypeVar("EnumMetaT", bound="Type[EnumMeta]") class _EnumValueBase(NamedTuple): @@ -105,7 +108,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 @@ -117,10 +120,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 = {} @@ -771,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, @@ -1070,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", @@ -2446,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. @@ -2463,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 ae3322c9e3..1bab2cf8ba 100644 --- a/disnake/errors.py +++ b/disnake/errors.py @@ -2,8 +2,7 @@ from __future__ import annotations -from collections.abc import Mapping -from typing import TYPE_CHECKING, Any, ClassVar, Optional, Union +from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, Mapping, Optional, Tuple, Union if TYPE_CHECKING: from aiohttp import ClientResponse, ClientWebSocketResponse @@ -71,14 +70,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: @@ -108,7 +107,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 c337f75674..6f23a6e11c 100644 --- a/disnake/ext/commands/_types.py +++ b/disnake/ext/commands/_types.py @@ -1,7 +1,6 @@ # SPDX-License-Identifier: MIT -from collections.abc import Coroutine -from typing import TYPE_CHECKING, Any, Callable, TypeVar, Union +from typing import TYPE_CHECKING, Any, Callable, Coroutine, 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 913d68d648..b655a1f4c8 100644 --- a/disnake/ext/commands/base_core.py +++ b/disnake/ext/commands/base_core.py @@ -10,7 +10,10 @@ TYPE_CHECKING, Any, Callable, + Dict, + List, Optional, + Tuple, TypeVar, Union, cast, @@ -131,7 +134,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: @@ -148,7 +151,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): raise TypeError("Name of a command must be a string.") @@ -172,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__ @@ -195,7 +198,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 @@ -254,7 +257,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 cd761df926..0cd80cb628 100644 --- a/disnake/ext/commands/bot.py +++ b/disnake/ext/commands/bot.py @@ -2,8 +2,7 @@ from __future__ import annotations -from collections.abc import Sequence -from typing import TYPE_CHECKING, Any, Callable, Optional, Union +from typing import TYPE_CHECKING, Any, Callable, List, Optional, Sequence, Set, Union import disnake @@ -257,7 +256,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 = ..., @@ -310,7 +309,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 = ..., @@ -322,7 +321,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, @@ -483,7 +482,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 = ..., @@ -529,7 +528,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 = ..., @@ -540,7 +539,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 d69f887fc4..ab5e6b9856 100644 --- a/disnake/ext/commands/bot_base.py +++ b/disnake/ext/commands/bot_base.py @@ -9,8 +9,7 @@ import sys import traceback import warnings -from collections.abc import Iterable -from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union +from typing import TYPE_CHECKING, Any, Callable, Iterable, List, Optional, Type, TypeVar, Union import disnake from disnake.utils import iscoroutinefunction @@ -47,7 +46,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. @@ -56,7 +55,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. @@ -85,7 +84,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 +150,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 @@ -429,7 +428,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 @@ -472,7 +471,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 beea8dcee9..b7551beed3 100644 --- a/disnake/ext/commands/cog.py +++ b/disnake/ext/commands/cog.py @@ -4,13 +4,17 @@ import inspect import logging -from collections.abc import Generator from typing import ( TYPE_CHECKING, Any, Callable, ClassVar, + Dict, + Generator, + List, Optional, + Tuple, + Type, Union, ) @@ -134,15 +138,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", {}) @@ -227,10 +231,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 @@ -243,7 +247,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) @@ -275,7 +279,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 @@ -290,7 +294,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 @@ -305,7 +309,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 @@ -320,7 +324,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 @@ -331,7 +335,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 @@ -372,7 +376,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 d3390f7fca..38b2da8566 100644 --- a/disnake/ext/commands/common_bot_base.py +++ b/disnake/ext/commands/common_bot_base.py @@ -11,8 +11,7 @@ import sys import time import types -from collections.abc import Mapping -from typing import TYPE_CHECKING, Any, Generic, Optional, TypeVar, Union +from typing import TYPE_CHECKING, Any, Dict, Generic, List, Mapping, Optional, Set, TypeVar, Union import disnake import disnake.utils @@ -39,24 +38,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: raise TypeError("Both owner_id and owner_ids are set.") diff --git a/disnake/ext/commands/context.py b/disnake/ext/commands/context.py index 8f41268a46..737bb40e08 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, Generic, Optional, TypeVar, Union +from typing import TYPE_CHECKING, Any, Dict, Generic, List, 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 8b4dc05cc6..7f403d348e 100644 --- a/disnake/ext/commands/converter.py +++ b/disnake/ext/commands/converter.py @@ -5,15 +5,19 @@ 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, @@ -378,7 +382,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/" @@ -472,7 +476,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) @@ -501,7 +505,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 @@ -999,7 +1003,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: @@ -1123,7 +1127,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, @@ -1145,7 +1149,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. @@ -1176,7 +1180,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: @@ -1218,14 +1222,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, @@ -1255,7 +1259,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: @@ -1331,7 +1335,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: @@ -1353,7 +1357,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 577da29b2f..971af2bd0f 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, Optional +from typing import TYPE_CHECKING, Any, Callable, Deque, Dict, Optional from disnake.enums import Enum from disnake.member import Member @@ -192,7 +192,7 @@ def __init__( if not callable(type): raise TypeError("Cooldown type must be a BucketType or callable") - self._cache: dict[Any, Cooldown] = {} + self._cache: Dict[Any, Cooldown] = {} self._cooldown: Optional[Cooldown] = original self._type: Callable[[Message], Any] = type @@ -296,7 +296,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)}>" @@ -342,7 +342,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 68708124b2..f4e4d06c9c 100644 --- a/disnake/ext/commands/core.py +++ b/disnake/ext/commands/core.py @@ -6,15 +6,20 @@ 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, @@ -162,7 +167,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()) @@ -256,7 +261,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 @@ -303,8 +308,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)): raise TypeError("Aliases of a command must be a list or a tuple of strings.") @@ -318,7 +323,7 @@ def __init__( except AttributeError: checks = kwargs.get("checks", []) - self.checks: list[Check] = checks + self.checks: List[Check] = checks try: cooldown = func.__commands_cooldown__ @@ -475,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__) @@ -601,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]: """Dict[:class:`str`, :class:`inspect.Parameter`]: Retrieves the parameter dictionary without the context or self parameters. @@ -626,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]]: """List[:class:`Group`]: Retrieves the parents of this command. If the command has no parents then it returns an empty :class:`list`. @@ -989,7 +994,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 @@ -1110,14 +1115,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]]: """Set[:class:`.Command`]: A unique set of commands without aliases that are registered.""" return set(self.all_commands.values()) @@ -1262,7 +1267,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]: ... @@ -1272,7 +1277,7 @@ def command( self, name: str = ..., *args: Any, - cls: type[CommandT], + cls: Type[CommandT], **kwargs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], CommandT]: ... @@ -1287,7 +1292,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: @@ -1312,7 +1317,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]: ... @@ -1322,7 +1327,7 @@ def group( self, name: str = ..., *args: Any, - cls: type[GroupT], + cls: Type[GroupT], **kwargs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], GroupT]: ... @@ -1337,7 +1342,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: @@ -1510,7 +1515,7 @@ def __call__( @overload def command( name: str, - cls: type[CommandT], + cls: Type[CommandT], **attrs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], CommandT]: ... @@ -1519,7 +1524,7 @@ def command( def command( name: str = ..., *, - cls: type[CommandT], + cls: Type[CommandT], **attrs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], CommandT]: ... @@ -1533,7 +1538,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` @@ -1579,7 +1584,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]: ... @@ -1588,7 +1593,7 @@ def group( def group( name: str = ..., *, - cls: type[GroupT], + cls: Type[GroupT], **attrs: Any, ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], GroupT]: ... @@ -1602,7 +1607,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 0585209c0e..b2fb6b2017 100644 --- a/disnake/ext/commands/ctx_menus_core.py +++ b/disnake/ext/commands/ctx_menus_core.py @@ -2,8 +2,7 @@ from __future__ import annotations -from collections.abc import Sequence -from typing import TYPE_CHECKING, Any, Callable, Optional, Union +from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Sequence, Tuple, Union from disnake.app_commands import MessageCommand, UserCommand from disnake.flags import ApplicationInstallTypes, InteractionContextTypes @@ -86,7 +85,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: @@ -197,7 +196,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: @@ -264,7 +263,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. @@ -369,7 +368,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 11f7c24997..a3e888a03e 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, Optional, Union +from typing import TYPE_CHECKING, Any, Callable, List, Optional, Tuple, 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 cb59438446..fadfd65f6f 100644 --- a/disnake/ext/commands/flag_converter.py +++ b/disnake/ext/commands/flag_converter.py @@ -5,14 +5,19 @@ 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, @@ -43,7 +48,7 @@ from .context import Context -FlagsMetaT = TypeVar("FlagsMetaT", bound="type[FlagsMeta]") +FlagsMetaT = TypeVar("FlagsMetaT", bound="Type[FlagsMeta]") @dataclass @@ -74,7 +79,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 @@ -94,7 +99,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, @@ -123,7 +128,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: raise ValueError("flag names should not be empty") @@ -137,13 +142,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): @@ -244,8 +249,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 @@ -254,8 +259,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, @@ -280,8 +285,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__"]) @@ -341,7 +346,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 @@ -368,7 +373,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 @@ -459,7 +464,7 @@ class FlagConverter(metaclass=FlagsMeta): """ @classmethod - def get_flags(cls) -> dict[str, Flag]: + def get_flags(cls) -> Dict[str, Flag]: """Dict[:class:`str`, :class:`Flag`]: A mapping of flag name to flag object this converter has.""" return cls.__commands_flags__.copy() @@ -467,7 +472,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)) @@ -493,8 +498,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 2127223056..dbad617712 100644 --- a/disnake/ext/commands/help.py +++ b/disnake/ext/commands/help.py @@ -6,14 +6,19 @@ 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, ) @@ -107,12 +112,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: @@ -176,7 +181,7 @@ def __len__(self) -> int: return total + self._count @property - def pages(self) -> list[str]: + def pages(self) -> List[str]: """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): @@ -238,7 +243,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 @@ -331,7 +336,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) @@ -377,10 +382,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] @@ -546,7 +551,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. @@ -594,7 +599,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: @@ -680,7 +685,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| @@ -1042,7 +1047,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 @@ -1290,7 +1295,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 7a5ce93dbb..550b4ba935 100644 --- a/disnake/ext/commands/interaction_bot_base.py +++ b/disnake/ext/commands/interaction_bot_base.py @@ -7,13 +7,18 @@ 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, @@ -68,14 +73,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", []) @@ -122,7 +127,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 @@ -154,7 +159,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 @@ -214,9 +219,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: @@ -240,22 +245,22 @@ def application_commands_iterator(self) -> Iterable[InvokableApplicationCommand] ) @property - def application_commands(self) -> set[InvokableApplicationCommand]: + def application_commands(self) -> Set[InvokableApplicationCommand]: """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]: """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]: """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]: """Set[:class:`InvokableMessageCommand`]: A set of all message commands the bot has.""" return set(self.all_message_commands.values()) @@ -495,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 @@ -616,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 @@ -719,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 @@ -815,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 44f69ff27d..40d535b493 100644 --- a/disnake/ext/commands/params.py +++ b/disnake/ext/commands/params.py @@ -13,7 +13,6 @@ 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 ( @@ -21,11 +20,17 @@ Any, Callable, ClassVar, + Dict, Final, + FrozenSet, Generic, + List, Literal, NoReturn, Optional, + Sequence, + Tuple, + Type, TypeVar, Union, cast, @@ -93,7 +98,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__ = ( @@ -112,7 +117,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(Union[int, str], int)`) and generic types (`issubclass(X[T], X)`) in the first argument. @@ -182,23 +187,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 @@ -224,7 +229,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 @@ -267,13 +272,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,) @@ -344,7 +349,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 @@ -360,7 +365,7 @@ def __or__(self, other): if TYPE_CHECKING: # aliased import since mypy doesn't understand `Range = Annotated` - from typing import Annotated as Range, Annotated as String + from typing_extensions import Annotated as Range, Annotated as String else: @dataclass(frozen=True, repr=False) @@ -387,7 +392,7 @@ def __post_init__(self) -> None: raise TypeError("Range[int, ...] bounds must be int, not float") @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 @@ -418,7 +423,7 @@ def __post_init__(self) -> None: raise ValueError("String bounds may not be negative") @classmethod - def _infer_type(cls, params: tuple[Any, ...]) -> type[Any]: + def _infer_type(cls, params: Tuple[Any, ...]) -> Type[Any]: return str @@ -427,7 +432,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: @@ -478,7 +483,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, @@ -496,7 +501,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, @@ -509,7 +514,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, @@ -591,8 +596,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 {} @@ -688,7 +693,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 @@ -864,8 +869,8 @@ def safe_call(function: Callable[..., T], /, *possible_args: Any, **possible_kwa ) 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(), @@ -899,8 +904,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, @@ -963,8 +968,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. @@ -975,8 +980,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]: @@ -1015,7 +1020,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) @@ -1033,7 +1038,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 @@ -1055,15 +1060,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())) @@ -1094,7 +1099,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 @@ -1142,7 +1147,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, @@ -1267,7 +1272,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. @@ -1304,7 +1309,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. @@ -1337,8 +1342,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. @@ -1386,7 +1391,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 8bf611f0b7..213af66291 100644 --- a/disnake/ext/commands/slash_core.py +++ b/disnake/ext/commands/slash_core.py @@ -4,12 +4,15 @@ import asyncio import inspect -from collections.abc import Sequence from typing import ( TYPE_CHECKING, Any, Callable, + Dict, + List, Optional, + Sequence, + Tuple, TypeVar, Union, ) @@ -102,7 +105,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 [ @@ -168,7 +171,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 @@ -194,7 +197,7 @@ def root_parent(self) -> InvokableSlashCommand: return self.parent @property - def parents(self) -> tuple[InvokableSlashCommand]: + def parents(self) -> Tuple[InvokableSlashCommand]: """Tuple[:class:`InvokableSlashCommand`]: Returns all parents of this group. .. versionadded:: 2.6 @@ -209,9 +212,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. @@ -289,15 +292,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", {}) ) @@ -331,7 +334,7 @@ def root_parent(self) -> InvokableSlashCommand: @property def parents( self, - ) -> Union[tuple[InvokableSlashCommand], tuple[SubCommandGroup, InvokableSlashCommand]]: + ) -> Union[Tuple[InvokableSlashCommand], Tuple[SubCommandGroup, InvokableSlashCommand]]: """Union[Tuple[:class:`InvokableSlashCommand`], Tuple[:class:`SubCommandGroup`, :class:`InvokableSlashCommand`]]: Returns all parents of this subcommand. @@ -446,25 +449,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", {}) ) @@ -511,7 +514,7 @@ def root_parent(self) -> None: return None @property - def parents(self) -> tuple[()]: + def parents(self) -> Tuple[()]: """Tuple[()]: This is mainly for consistency with :class:`SubCommand`, and is equivalent to an empty tuple. .. versionadded:: 2.6 @@ -542,7 +545,7 @@ def description(self) -> str: return self.body.description @property - def options(self) -> list[Option]: + def options(self) -> List[Option]: """List[:class:`.Option`]: The list of options the slash command has. Shorthand for :attr:`self.body.options <.SlashCommand.options>`.""" return self.body.options @@ -550,9 +553,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. @@ -614,7 +617,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. @@ -782,11 +785,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 4e4620bbf2..97b23df5da 100644 --- a/disnake/ext/mypy_plugin/__init__.py +++ b/disnake/ext/mypy_plugin/__init__.py @@ -1,5 +1,7 @@ # SPDX-License-Identifier: MIT +import typing as t + from mypy.plugin import Plugin @@ -8,5 +10,5 @@ class DisnakePlugin(Plugin): """Custom mypy plugin; no-op as of version 2.9.""" -def plugin(version: str) -> type[Plugin]: +def plugin(version: str) -> t.Type[Plugin]: return DisnakePlugin diff --git a/disnake/ext/tasks/__init__.py b/disnake/ext/tasks/__init__.py index 67d18dcb0c..1026e4e11a 100644 --- a/disnake/ext/tasks/__init__.py +++ b/disnake/ext/tasks/__init__.py @@ -7,14 +7,17 @@ import inspect import sys import traceback -from collections.abc import Coroutine, Sequence +from collections.abc import Sequence from typing import ( TYPE_CHECKING, Any, Callable, + Coroutine, Generic, + List, Optional, Protocol, + Type, TypeVar, Union, cast, @@ -193,7 +196,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() @@ -249,7 +252,7 @@ def hours(self) -> Optional[float]: return self._hours @property - def time(self) -> Optional[list[datetime.time]]: + def time(self) -> Optional[List[datetime.time]]: """Optional[List[:class:`datetime.time`]]: Read-only list for the exact times this loop runs at. ``None`` if relative times were passed instead. @@ -379,7 +382,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 @@ -416,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 @@ -601,9 +604,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] @@ -614,7 +617,7 @@ def _get_time_parameter( if not time: raise ValueError("time parameter must not be an empty sequence.") - ret: list[datetime.time] = [] + ret: List[datetime.time] = [] for index, t in enumerate(time): if not isinstance(t, dt): raise TypeError( @@ -676,7 +679,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)): raise TypeError("Cannot mix explicit time with relative time") @@ -721,12 +724,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 @@ -791,6 +794,6 @@ def decorator(func: LF) -> L_co: if not iscoroutinefunction(func): raise TypeError("decorated function must be a coroutine") - 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 ea8cd8e36c..b7fe44ee9b 100644 --- a/disnake/flags.py +++ b/disnake/flags.py @@ -4,15 +4,20 @@ 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, @@ -50,7 +55,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): @@ -83,12 +88,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) @@ -104,12 +109,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 @@ -124,7 +129,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 @@ -274,7 +279,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 @@ -316,7 +321,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 @@ -952,7 +957,7 @@ def active_developer(self) -> int: """ return UserFlags.active_developer.value - def all(self) -> list[UserFlags]: + def all(self) -> List[UserFlags]: """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 1713c9f84f..56ff150fc2 100644 --- a/disnake/gateway.py +++ b/disnake/gateway.py @@ -16,7 +16,10 @@ TYPE_CHECKING, Any, Callable, + Deque, + Dict, Final, + List, Literal, NamedTuple, Optional, @@ -98,9 +101,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] @@ -251,7 +254,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" @@ -348,7 +351,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() @@ -366,7 +369,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 @@ -456,8 +459,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. @@ -650,7 +653,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 @@ -806,7 +809,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: @@ -907,7 +910,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 @@ -1048,7 +1051,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 5c91de3912..82a683e7b8 100644 --- a/disnake/guild.py +++ b/disnake/guild.py @@ -5,15 +5,20 @@ 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, @@ -121,7 +126,7 @@ GuildChannel = Union[ VoiceChannel, StageChannel, TextChannel, CategoryChannel, ForumChannel, MediaChannel ] - ByCategoryItem = tuple[Optional[CategoryChannel], list[GuildChannel]] + ByCategoryItem = Tuple[Optional[CategoryChannel], List[GuildChannel]] class _GuildLimit(NamedTuple): @@ -467,7 +472,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), @@ -476,12 +481,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) @@ -519,8 +524,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: @@ -543,7 +548,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: @@ -643,23 +648,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") @@ -752,12 +757,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]: """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]: """List[:class:`Thread`]: A list of threads that you have permission to view. .. versionadded:: 2.0 @@ -779,7 +784,7 @@ def large(self) -> bool: return self._large @property - def voice_channels(self) -> list[VoiceChannel]: + def voice_channels(self) -> List[VoiceChannel]: """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. @@ -789,7 +794,7 @@ def voice_channels(self) -> list[VoiceChannel]: return r @property - def stage_channels(self) -> list[StageChannel]: + def stage_channels(self) -> List[StageChannel]: """List[:class:`StageChannel`]: A list of stage channels that belong to this guild. .. versionadded:: 1.7 @@ -801,7 +806,7 @@ def stage_channels(self) -> list[StageChannel]: return r @property - def forum_channels(self) -> list[ForumChannel]: + def forum_channels(self) -> List[ForumChannel]: """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. @@ -813,7 +818,7 @@ def forum_channels(self) -> list[ForumChannel]: return r @property - def media_channels(self) -> list[MediaChannel]: + def media_channels(self) -> List[MediaChannel]: """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. @@ -839,7 +844,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]: """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. @@ -849,7 +854,7 @@ def text_channels(self) -> list[TextChannel]: return r @property - def categories(self) -> list[CategoryChannel]: + def categories(self) -> List[CategoryChannel]: """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. @@ -858,7 +863,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. @@ -871,7 +876,7 @@ def by_category(self) -> list[ByCategoryItem]: List[Tuple[Optional[:class:`CategoryChannel`], 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, []) @@ -882,12 +887,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)) @@ -1046,7 +1051,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]: """List[:class:`Member`]: A list of members that belong to this guild.""" return list(self._members.values()) @@ -1066,12 +1071,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]: """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]: """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 @@ -1125,7 +1130,7 @@ def self_role(self) -> Optional[Role]: return None @property - def stage_instances(self) -> list[StageInstance]: + def stage_instances(self) -> List[StageInstance]: """List[:class:`StageInstance`]: Returns a :class:`list` of the guild's stage instances that are currently running. @@ -1151,7 +1156,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]: """List[:class:`GuildScheduledEvent`]: Returns a :class:`list` of existing guild scheduled events. .. versionadded:: 2.3 @@ -1316,7 +1321,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: @@ -1363,7 +1368,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| @@ -1517,7 +1522,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| @@ -1632,7 +1637,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, @@ -1709,7 +1714,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 @@ -1760,7 +1765,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, @@ -1910,7 +1915,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, @@ -2029,7 +2034,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: @@ -2072,7 +2077,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 @@ -2360,7 +2365,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 @@ -2543,7 +2548,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. @@ -2564,7 +2569,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: @@ -2574,7 +2579,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. @@ -2805,7 +2810,7 @@ async def create_scheduled_event( elif not isinstance(privacy_level, GuildScheduledEventPrivacyLevel): raise TypeError("privacy_level must be an instance of GuildScheduledEventPrivacyLevel") - fields: dict[str, Any] = { + fields: Dict[str, Any] = { "name": name, "privacy_level": privacy_level.value, "scheduled_start_time": utils.isoformat_utc(scheduled_start_time), @@ -2868,7 +2873,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: @@ -3162,7 +3167,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| @@ -3231,7 +3236,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. @@ -3256,7 +3261,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. @@ -3279,7 +3284,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 @@ -3326,7 +3331,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. @@ -3354,7 +3359,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"])) @@ -3427,7 +3432,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. @@ -3457,7 +3462,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. @@ -3597,7 +3602,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. @@ -3783,7 +3788,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. @@ -4031,8 +4036,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. @@ -4082,14 +4087,14 @@ async def edit_role_positions( if not isinstance(positions, dict): raise TypeError("positions parameter expects a dict.") - 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) @@ -4617,7 +4622,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. @@ -4655,10 +4660,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 @@ -4733,7 +4738,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 @@ -4772,7 +4777,7 @@ async def search_members( raise ValueError("limit must be at least 1") 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: @@ -4782,11 +4787,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. @@ -4825,8 +4830,8 @@ async def get_or_fetch_members( if presences and not self._state._intents.presences: raise ClientException("Intents.presences must be enabled to use this.") - 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) @@ -4865,7 +4870,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. @@ -4944,7 +4949,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. @@ -5045,7 +5050,7 @@ async def timeout( if not (duration is MISSING) ^ (until is MISSING): raise ValueError("Exactly one of `duration` and `until` must be provided") - payload: dict[str, Any] = {} + payload: Dict[str, Any] = {} if duration is not MISSING: if duration is None: @@ -5088,7 +5093,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. @@ -5324,7 +5329,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. @@ -5442,8 +5447,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 @@ -5467,12 +5472,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, @@ -5481,7 +5486,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( @@ -5653,7 +5658,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. @@ -5680,7 +5685,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, @@ -5740,7 +5745,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 f11689cbbb..e6c7ec81b0 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 +from typing import TYPE_CHECKING, Optional, Tuple 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 033d534553..27bded9ff5 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, Literal, Optional, overload +from typing import TYPE_CHECKING, Any, Dict, 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 fb2f39835e..70e7f549ce 100644 --- a/disnake/http.py +++ b/disnake/http.py @@ -7,14 +7,20 @@ 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, @@ -101,7 +107,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": @@ -113,7 +119,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 @@ -133,11 +139,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( { @@ -153,8 +159,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`` @@ -205,7 +211,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: @@ -274,7 +280,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 @@ -286,7 +292,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, } @@ -318,7 +324,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): @@ -499,7 +505,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, @@ -528,7 +534,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, @@ -538,7 +544,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 @@ -584,7 +590,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 @@ -625,7 +631,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, @@ -634,7 +640,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: @@ -668,7 +674,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, @@ -720,7 +726,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( @@ -778,7 +784,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}", @@ -787,7 +793,7 @@ def get_reaction_users( emoji=emoji, ) - params: dict[str, Any] = { + params: Dict[str, Any] = { "limit": limit, } if after: @@ -838,8 +844,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, } @@ -899,7 +905,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 @@ -910,7 +916,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}) @@ -947,7 +953,7 @@ def unban( def bulk_ban( self, - user_ids: list[Snowflake], + user_ids: List[Snowflake], guild_id: Snowflake, *, delete_message_seconds: int = 0, @@ -961,7 +967,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( @@ -985,7 +991,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( @@ -1015,12 +1021,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 @@ -1092,7 +1098,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]: @@ -1251,7 +1257,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 @@ -1265,7 +1271,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 @@ -1286,7 +1292,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) @@ -1340,7 +1346,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: @@ -1349,10 +1355,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]: @@ -1381,8 +1387,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), } @@ -1412,8 +1418,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, @@ -1486,7 +1492,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( @@ -1502,7 +1508,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", @@ -1538,8 +1544,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 @@ -1563,7 +1569,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, @@ -1580,13 +1586,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: @@ -1612,11 +1618,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", } @@ -1633,9 +1639,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: @@ -1654,7 +1660,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( @@ -1689,7 +1695,7 @@ def create_guild_sticker( finally: file.reset() - form: list[dict[str, Any]] = [ + form: List[Dict[str, Any]] = [ { "name": "file", "value": file.fp, @@ -1755,7 +1761,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]: @@ -1766,7 +1772,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, } @@ -1777,7 +1783,7 @@ def create_app_emoji(self, app_id: Snowflake, name: str, image: str) -> Response 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, } @@ -1805,7 +1811,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 [], @@ -1831,7 +1837,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( @@ -1839,7 +1845,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) @@ -1899,7 +1905,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: @@ -1919,7 +1925,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), @@ -1950,7 +1956,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, @@ -1985,10 +1991,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]: @@ -2003,7 +2009,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( @@ -2041,7 +2047,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]: @@ -2056,10 +2062,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) @@ -2186,7 +2192,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) @@ -2200,14 +2206,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, @@ -2279,8 +2285,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 @@ -2329,7 +2335,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) ) @@ -2353,7 +2359,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, @@ -2425,7 +2431,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) ) @@ -2443,8 +2449,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), @@ -2485,8 +2491,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: @@ -2525,7 +2531,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, @@ -2572,8 +2578,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) @@ -2626,8 +2632,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) @@ -2639,8 +2645,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) @@ -2717,8 +2723,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", @@ -2734,14 +2740,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: @@ -2770,7 +2776,7 @@ def create_interaction_response( interaction_id=interaction_id, interaction_token=token, ) - payload: dict[str, Any] = { + payload: Dict[str, Any] = { "type": type, } @@ -2798,9 +2804,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", @@ -2832,10 +2838,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( @@ -2862,9 +2868,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", @@ -2898,7 +2904,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", @@ -2924,7 +2930,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( @@ -2961,7 +2967,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, } @@ -3029,7 +3035,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: @@ -3042,7 +3048,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]: @@ -3050,7 +3056,7 @@ def application_info(self) -> 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", @@ -3063,7 +3069,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", @@ -3083,7 +3089,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 e291db6f41..5404942371 100644 --- a/disnake/i18n.py +++ b/disnake/i18n.py @@ -11,9 +11,13 @@ from typing import ( TYPE_CHECKING, Any, + DefaultDict, + Dict, Generic, Literal, Optional, + Set, + Type, TypeVar, Union, overload, @@ -44,7 +48,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) @@ -134,7 +138,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) @@ -178,7 +182,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 @@ -226,7 +230,7 @@ def _copy(self) -> LocalizationValue: return ins @property - def data(self) -> Optional[dict[str, str]]: + def data(self) -> Optional[Dict[str, str]]: """Optional[Dict[:class:`str`, :class:`str`]]: 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. @@ -259,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 @@ -319,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 @@ -407,7 +411,7 @@ def _load_file(self, path: Path) -> None: except Exception as e: raise RuntimeError(f"Unable to load '{path}': {e}") 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 32a36a0ef9..0bd92a762c 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, Optional +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type 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): raise TypeError("expire_behaviour field must be of type ExpireBehaviour") @@ -415,13 +415,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 2d04d924a7..3538c341c8 100644 --- a/disnake/interactions/application_command.py +++ b/disnake/interactions/application_command.py @@ -2,8 +2,7 @@ from __future__ import annotations -from collections.abc import Mapping -from typing import TYPE_CHECKING, Any, Optional, Union +from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Tuple, Union from .. import utils from ..enums import ApplicationCommandType, Locale, OptionType, try_enum @@ -160,12 +159,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]: """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]: """Dict[:class:`str`, :class:`Any`]: The options of the command (or sub-command) being invoked""" _, kwargs = self.data._get_chain_and_kwargs() return kwargs @@ -214,7 +213,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 @@ -263,7 +262,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", []) ] @@ -275,8 +274,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 = () @@ -306,7 +305,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 @@ -335,7 +334,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", []) ] @@ -361,8 +360,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 231dbb6dd0..0f2c2966f9 100644 --- a/disnake/interactions/base.py +++ b/disnake/interactions/base.py @@ -3,13 +3,17 @@ 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, @@ -196,7 +200,7 @@ class Interaction(Generic[ClientT]): .. versionadded:: 2.11 """ - __slots__: tuple[str, ...] = ( + __slots__: Tuple[str, ...] = ( "data", "id", "type", @@ -272,7 +276,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 [] @@ -441,10 +445,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, @@ -691,9 +695,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, @@ -830,7 +834,7 @@ class InteractionResponse: .. versionadded:: 2.0 """ - __slots__: tuple[str, ...] = ( + __slots__: Tuple[str, ...] = ( "_parent", "_response_type", ) @@ -912,7 +916,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: @@ -982,9 +986,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, @@ -1083,7 +1087,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, } @@ -1191,10 +1195,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, @@ -1425,7 +1429,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: @@ -1548,7 +1552,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], ), } @@ -1725,7 +1729,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] = ..., @@ -1740,8 +1744,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] = ..., @@ -1755,9 +1759,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] = ..., @@ -1771,9 +1775,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] = ..., @@ -1787,10 +1791,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, @@ -1978,7 +1982,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 @@ -2016,12 +2020,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 d097a48ac1..704fd3ae67 100644 --- a/disnake/interactions/message.py +++ b/disnake/interactions/message.py @@ -2,8 +2,7 @@ from __future__ import annotations -from collections.abc import Sequence -from typing import TYPE_CHECKING, Any, Optional, Union +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Union from ..components import VALID_ACTION_ROW_MESSAGE_COMPONENT_TYPES, ActionRowMessageComponent from ..enums import ComponentType, try_enum @@ -137,7 +136,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]]: """Optional[List[:class:`str`]]: The values the user selected. For select menus of type :attr:`~ComponentType.string_select`, @@ -169,7 +168,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 +189,7 @@ def component(self) -> ActionRowMessageComponent: raise Exception("MessageInteraction is malformed - no component found") # 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 +220,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 f476347ef3..220725ed24 100644 --- a/disnake/interactions/modal.py +++ b/disnake/interactions/modal.py @@ -2,12 +2,15 @@ from __future__ import annotations -from collections.abc import Generator, Sequence from typing import ( TYPE_CHECKING, Any, Callable, + Dict, + Generator, + List, Optional, + Sequence, TypeVar, Union, ) @@ -38,7 +41,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]): @@ -233,7 +236,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]: """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}``. """ @@ -250,7 +253,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 @@ -283,7 +286,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 49495ad892..5f7ea64e8a 100644 --- a/disnake/invite.py +++ b/disnake/invite.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional, Union +from typing import TYPE_CHECKING, List, 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 d62beda670..8146380058 100644 --- a/disnake/iterators.py +++ b/disnake/iterators.py @@ -4,11 +4,15 @@ 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, @@ -114,7 +118,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: @@ -124,13 +128,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: @@ -203,7 +207,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 ) @@ -353,35 +357,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 @@ -470,20 +474,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) @@ -595,7 +599,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) @@ -745,14 +749,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): @@ -761,10 +765,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): @@ -901,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: @@ -1002,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, @@ -1019,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, @@ -1048,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, @@ -1066,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 @@ -1117,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, @@ -1135,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, @@ -1221,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, @@ -1237,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, @@ -1344,7 +1348,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 c98bc7c23c..fb05bffbc2 100644 --- a/disnake/member.py +++ b/disnake/member.py @@ -5,14 +5,18 @@ 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, @@ -162,7 +166,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("_"): @@ -288,7 +292,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] @@ -335,8 +339,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") @@ -446,7 +450,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 @@ -458,7 +462,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, @@ -570,14 +574,14 @@ def color(self) -> Colour: return self.colour @property - def roles(self) -> list[Role]: + def roles(self) -> List[Role]: """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) @@ -861,7 +865,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 "" @@ -1019,7 +1023,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( @@ -1041,7 +1045,7 @@ async def edit( if self.voice is None or self.voice.channel is None: raise Exception("Cannot suppress a member which isn't in a vc") # 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 1e9070ee98..a5d867bc47 100644 --- a/disnake/mentions.py +++ b/disnake/mentions.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Union +from typing import TYPE_CHECKING, Any, List, Union from .enums import MessageType @@ -69,8 +69,8 @@ def __init__( self, *, everyone: bool = default, - users: Union[bool, list[Snowflake]] = default, - roles: Union[bool, list[Snowflake]] = default, + users: Union[bool, List[Snowflake]] = default, + roles: Union[bool, List[Snowflake]] = default, replied_user: bool = default, ) -> None: self.everyone = everyone @@ -119,7 +119,7 @@ def from_message(cls, message: Message) -> Self: ) def to_dict(self) -> AllowedMentionsPayload: - parse: list[AllowedMentionTypePayload] = [] + parse: List[AllowedMentionTypePayload] = [] data: AllowedMentionsPayload = {} # type: ignore if self.everyone: diff --git a/disnake/message.py b/disnake/message.py index d82d08d860..ab6d47aaf2 100644 --- a/disnake/message.py +++ b/disnake/message.py @@ -13,7 +13,11 @@ Any, Callable, ClassVar, + Dict, + List, Optional, + Tuple, + Type, Union, cast, overload, @@ -114,7 +118,8 @@ def convert_emoji_reaction(emoji: Union[EmojiInputType, Reaction]) -> str: s = emoji.strip("<>:") # `str.removeprefix` is py 3.9 only - s = s.removeprefix("a:") + if s.startswith("a:"): + s = s[2:] return s assert_never(emoji) @@ -133,10 +138,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, @@ -160,7 +165,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) @@ -951,7 +956,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) @@ -1152,13 +1157,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, @@ -1171,13 +1176,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 @@ -1195,10 +1200,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", []) ] @@ -1250,7 +1255,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"), @@ -1381,10 +1386,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: @@ -1414,7 +1419,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 @@ -1431,7 +1436,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): @@ -1439,7 +1444,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: @@ -1454,7 +1459,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]: """List[:class:`int`]: A property that returns an array of user IDs matched with the syntax of ``<@user_id>`` in the message content. @@ -1464,21 +1469,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]: """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]: """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]: """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. """ @@ -1789,7 +1794,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 @@ -1878,7 +1883,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] = ..., @@ -1893,8 +1898,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] = ..., @@ -1908,9 +1913,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] = ..., @@ -1924,9 +1929,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] = ..., @@ -1940,10 +1945,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, @@ -2650,7 +2655,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] = ..., @@ -2665,8 +2670,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] = ..., @@ -2680,9 +2685,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] = ..., @@ -2696,9 +2701,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] = ..., @@ -2712,10 +2717,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, @@ -2950,10 +2955,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"]) @@ -2961,15 +2966,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: @@ -2983,7 +2988,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 cc8026b9a3..ae2407d644 100644 --- a/disnake/oggparse.py +++ b/disnake/oggparse.py @@ -3,8 +3,7 @@ from __future__ import annotations import struct -from collections.abc import Generator -from typing import IO, TYPE_CHECKING, ClassVar, Optional +from typing import IO, TYPE_CHECKING, ClassVar, Generator, Optional, Tuple from .errors import DiscordException @@ -54,7 +53,7 @@ def __init__(self, stream: IO[bytes]) -> None: except Exception: raise OggError("bad data stream") 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 e2943dbd2b..069e0fb7fa 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, Optional, Union +from typing import TYPE_CHECKING, FrozenSet, List, 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]: """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]: """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]: """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 e2f66c5c06..b68c17ce34 100644 --- a/disnake/opus.py +++ b/disnake/opus.py @@ -14,8 +14,11 @@ TYPE_CHECKING, Any, Callable, + List, Literal, Optional, + Tuple, + Type, TypedDict, TypeVar, overload, @@ -105,14 +108,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__) @@ -125,8 +128,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 4e657fedae..167fb6589e 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, Optional, Union +from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, 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), @@ -255,7 +255,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 a63c787966..e0d78cec05 100644 --- a/disnake/permissions.py +++ b/disnake/permissions.py @@ -2,14 +2,17 @@ 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, ) @@ -1215,8 +1218,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 @@ -1292,7 +1295,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: @@ -1312,7 +1315,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]: """Tuple[:class:`Permissions`, :class:`Permissions`]: Returns the (allow, deny) pair from this overwrite.""" allow = Permissions.none() deny = Permissions.none() @@ -1443,6 +1446,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 e987e0fec8..5117896e12 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, TypeVar, Union +from typing import IO, TYPE_CHECKING, Any, Callable, Generic, Optional, Tuple, TypeVar, Union from . import utils from .errors import ClientException @@ -444,7 +444,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: @@ -511,10 +511,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. @@ -585,7 +585,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, @@ -614,7 +614,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 bae0d8908b..39f4140945 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, Optional, Union +from typing import TYPE_CHECKING, Dict, List, Optional, Union from . import utils from .abc import Snowflake @@ -241,7 +241,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__( f"Expected 'str' or 'PollMedia' for 'question', got {question.__class__.__name__!r}." ) - 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 @@ -277,7 +277,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]: """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 1f44254d94..92af91b993 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, Literal, Optional, Union, cast +from typing import TYPE_CHECKING, List, Literal, Optional, Set, 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 2672731f1d..461a11abd2 100644 --- a/disnake/role.py +++ b/disnake/role.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Optional, Union +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union from .asset import Asset from .colour import Colour @@ -484,7 +484,7 @@ def mention(self) -> str: return f"<@&{self.id}>" @property - def members(self) -> list[Member]: + def members(self) -> List[Member]: """List[:class:`Member`]: Returns all the members with this role.""" all_members = self.guild.members if self.is_default(): @@ -515,7 +515,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) @@ -625,9 +625,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 7dc5d50a2b..c17a05400d 100644 --- a/disnake/shard.py +++ b/disnake/shard.py @@ -9,9 +9,13 @@ TYPE_CHECKING, Any, Callable, + Dict, + List, Literal, NoReturn, Optional, + Tuple, + Type, Union, overload, ) @@ -95,7 +99,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, @@ -345,7 +349,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, @@ -371,7 +375,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) @@ -421,7 +425,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]]: """List[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)``. @@ -441,7 +445,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]: """Mapping[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 cc594e4c36..0d1d701dac 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, Optional, Union +from typing import TYPE_CHECKING, Any, Dict, 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 72ebba558e..06c8400d02 100644 --- a/disnake/state.py +++ b/disnake/state.py @@ -11,14 +11,19 @@ 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, @@ -123,7 +128,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() @@ -144,7 +149,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, @@ -157,9 +162,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) @@ -189,14 +194,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, @@ -217,8 +222,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) @@ -231,7 +236,7 @@ def __init__( raise TypeError("allowed_mentions parameter must be AllowedMentions.") 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): @@ -298,14 +303,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) @@ -313,19 +318,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(): @@ -366,7 +371,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]: @@ -434,7 +439,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]: @@ -526,15 +531,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]: @@ -550,7 +555,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]: @@ -618,7 +623,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") @@ -659,10 +664,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) @@ -1435,16 +1440,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: @@ -1520,7 +1525,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 ) @@ -2099,7 +2104,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 @@ -2268,7 +2273,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, @@ -2307,8 +2312,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] @@ -2322,7 +2327,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, @@ -2368,8 +2373,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 @@ -2384,7 +2389,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, @@ -2405,7 +2410,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: @@ -2473,7 +2478,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: @@ -2486,7 +2491,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 @@ -2517,8 +2522,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 09b17b9cb3..58303c2162 100644 --- a/disnake/sticker.py +++ b/disnake/sticker.py @@ -3,7 +3,7 @@ from __future__ import annotations import unicodedata -from typing import TYPE_CHECKING, Literal, Optional, Union +from typing import TYPE_CHECKING, List, Literal, Optional, Tuple, Type, 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"] @@ -326,7 +326,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 = [] @@ -509,7 +509,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 1beead048d..bf86e1a35a 100644 --- a/disnake/subscription.py +++ b/disnake/subscription.py @@ -3,7 +3,7 @@ from __future__ import annotations import datetime -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING, List, 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 e918180b62..a1f126304e 100644 --- a/disnake/team.py +++ b/disnake/team.py @@ -3,7 +3,7 @@ from __future__ import annotations import datetime -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING, List, 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 36c77c5858..e0b998d2bb 100644 --- a/disnake/template.py +++ b/disnake/template.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, NoReturn, Optional +from typing import TYPE_CHECKING, Any, List, NoReturn, Optional from .guild import Guild, Member from .utils import MISSING, _assetbytes_to_base64_data, parse_time @@ -60,7 +60,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 a746a7290c..d02b5ba06f 100644 --- a/disnake/threads.py +++ b/disnake/threads.py @@ -4,8 +4,7 @@ import asyncio import time -from collections.abc import Iterable, Sequence -from typing import TYPE_CHECKING, Callable, Literal, Optional, Union +from typing import TYPE_CHECKING, Callable, Dict, Iterable, List, Literal, Optional, Sequence, Union from .abc import GuildChannel, Messageable from .enums import ChannelType, ThreadArchiveDuration, try_enum, try_enum_to_int @@ -168,7 +167,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: @@ -199,7 +198,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: @@ -261,7 +260,7 @@ def mention(self) -> str: return f"<#{self.id}>" @property - def members(self) -> list[ThreadMember]: + def members(self) -> List[ThreadMember]: """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, @@ -399,7 +398,7 @@ def is_pinned(self) -> bool: return self.flags.pinned @property - def applied_tags(self) -> list[ForumTag]: + def applied_tags(self) -> List[ForumTag]: """List[:class:`ForumTag`]: The tags currently applied to this thread. Only applicable to threads in channels of type :class:`ForumChannel` or :class:`MediaChannel`. @@ -557,7 +556,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 @@ -618,7 +617,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 @@ -877,7 +876,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. @@ -954,7 +953,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) @@ -992,7 +991,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 d9ad7a6a0a..749f015bdc 100644 --- a/disnake/types/activity.py +++ b/disnake/types/activity.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Literal, Optional, TypedDict +from typing import List, 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 f20cac300f..639972fab0 100644 --- a/disnake/types/appinfo.py +++ b/disnake/types/appinfo.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Literal, Optional, TypedDict +from typing import Dict, List, Literal, Optional, TypedDict from typing_extensions import NotRequired @@ -28,7 +28,7 @@ class BaseAppInfo(TypedDict): class InstallParams(TypedDict): - scopes: list[str] + scopes: List[str] permissions: str @@ -37,7 +37,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] @@ -47,24 +47,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[str] - 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 diff --git a/disnake/types/audit_log.py b/disnake/types/audit_log.py index d2ff07f9db..cad5b52f4e 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 Literal, Optional, TypedDict, Union +from typing import List, 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 d596418142..f7ac372e5e 100644 --- a/disnake/types/automod.py +++ b/disnake/types/automod.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Literal, TypedDict, Union +from typing import List, 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 adca9c962b..d10a688caa 100644 --- a/disnake/types/channel.py +++ b/disnake/types/channel.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import Literal, Optional, TypedDict, Union +from typing import List, 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 d78753d0af..fa13f7d3be 100644 --- a/disnake/types/components.py +++ b/disnake/types/components.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Literal, Optional, TypedDict, Union +from typing import List, 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 ef33d1a5a2..a066b084d3 100644 --- a/disnake/types/embed.py +++ b/disnake/types/embed.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import Literal, TypedDict +from typing import List, 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 c19ac3e184..76ac0f423b 100644 --- a/disnake/types/emoji.py +++ b/disnake/types/emoji.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import Optional, TypedDict +from typing import List, 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 a1bbce8a43..31797bbf15 100644 --- a/disnake/types/gateway.py +++ b/disnake/types/gateway.py @@ -2,8 +2,7 @@ from __future__ import annotations -from collections.abc import Sequence -from typing import Any, Literal, Optional, TypedDict, Union +from typing import Any, List, Literal, Optional, Sequence, Tuple, TypedDict, Union from typing_extensions import NotRequired @@ -85,7 +84,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 @@ -170,12 +169,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] ##### @@ -253,10 +252,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 @@ -286,7 +285,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] @@ -417,9 +416,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 @@ -432,8 +431,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 @@ -450,7 +449,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] @@ -468,13 +467,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 @@ -554,11 +553,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] @@ -698,4 +697,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 7d4ce6776d..d76907940d 100644 --- a/disnake/types/guild.py +++ b/disnake/types/guild.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import Literal, Optional, TypedDict +from typing import List, 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 3518c4cd69..e8aa30eb23 100644 --- a/disnake/types/i18n.py +++ b/disnake/types/i18n.py @@ -1,4 +1,5 @@ # 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 127de48627..d12ff6f958 100644 --- a/disnake/types/integration.py +++ b/disnake/types/integration.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Literal, Optional, TypedDict, Union +from typing import List, 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 9ec318ce17..c24af62299 100644 --- a/disnake/types/interactions.py +++ b/disnake/types/interactions.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Literal, Optional, TypedDict, Union +from typing import TYPE_CHECKING, Dict, List, 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 d17628d8cb..6e0347bfeb 100644 --- a/disnake/types/message.py +++ b/disnake/types/message.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Literal, Optional, TypedDict, Union +from typing import List, 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 8b255e68b9..79d1bb86a2 100644 --- a/disnake/types/onboarding.py +++ b/disnake/types/onboarding.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import Literal, Optional, TypedDict +from typing import List, 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 a9a601d955..37d33e2206 100644 --- a/disnake/types/poll.py +++ b/disnake/types/poll.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Literal, Optional, TypedDict +from typing import List, 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 49741159e4..96b088524d 100644 --- a/disnake/types/snowflake.py +++ b/disnake/types/snowflake.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import Union +from typing import List, 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 c1825effe1..333d7033b3 100644 --- a/disnake/types/soundboard.py +++ b/disnake/types/soundboard.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Optional, TypedDict +from typing import List, 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 60c3c17966..06bc58aa05 100644 --- a/disnake/types/sticker.py +++ b/disnake/types/sticker.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Literal, Optional, TypedDict, Union +from typing import List, 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 e5ae691111..1cfaaf8684 100644 --- a/disnake/types/subscription.py +++ b/disnake/types/subscription.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import Literal, Optional, TypedDict +from typing import List, 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 bb80992b2f..0829c18b5c 100644 --- a/disnake/types/team.py +++ b/disnake/types/team.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Literal, Optional, TypedDict +from typing import List, 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 9be72c3a6a..30f630d916 100644 --- a/disnake/types/threads.py +++ b/disnake/types/threads.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Literal, Optional, TypedDict +from typing import List, 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 d4382b7a8f..3b59312ddf 100644 --- a/disnake/types/voice.py +++ b/disnake/types/voice.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import Literal, Optional, TypedDict +from typing import List, 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 425799cd8e..e98b7c3668 100644 --- a/disnake/types/welcome_screen.py +++ b/disnake/types/welcome_screen.py @@ -2,14 +2,14 @@ from __future__ import annotations -from typing import Optional, TypedDict +from typing import List, 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 9f638cd152..df011ac1a5 100644 --- a/disnake/types/widget.py +++ b/disnake/types/widget.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import Optional, TypedDict +from typing import List, 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 6e762e4a29..de7afa2735 100644 --- a/disnake/ui/_types.py +++ b/disnake/ui/_types.py @@ -2,8 +2,7 @@ from __future__ import annotations -from collections.abc import Sequence -from typing import TYPE_CHECKING, Any, Optional, TypeVar, Union +from typing import TYPE_CHECKING, Any, Optional, Sequence, 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 36509590d5..f9f056bcb9 100644 --- a/disnake/ui/action_row.py +++ b/disnake/ui/action_row.py @@ -2,14 +2,21 @@ 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, @@ -163,7 +170,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. @@ -195,7 +202,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): @@ -631,7 +638,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: @@ -832,7 +839,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, @@ -896,7 +903,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 @@ -927,7 +934,7 @@ def rows_from_message( 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 @@ -947,7 +954,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. @@ -1003,7 +1010,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 @@ -1046,24 +1053,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 @@ -1104,12 +1111,12 @@ def walk_components(components: Sequence[ComponentT]) -> Iterator[ComponentT]: Union[: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 @@ -1133,11 +1140,11 @@ def components_from_message(message: Message) -> list[MessageTopLevelComponent]: 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 20a9580e3c..bb16ca9485 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, TypeVar, Union, overload +from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, Tuple, 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 9ddb5ae019..f061d496ea 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, Optional, Union, cast +from typing import TYPE_CHECKING, ClassVar, List, Optional, Tuple, 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 @@ -129,7 +129,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 2c2c8d97f1..4ed1e7a476 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 +from typing import TYPE_CHECKING, ClassVar, Optional, Tuple 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 2328ff8c95..a529f02693 100644 --- a/disnake/ui/item.py +++ b/disnake/ui/item.py @@ -3,15 +3,18 @@ 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, ) @@ -68,7 +71,7 @@ class UIComponent(ABC): .. versionadded:: 2.11 """ - __repr_attributes__: ClassVar[tuple[str, ...]] + __repr_attributes__: ClassVar[Tuple[str, ...]] @property @abstractmethod @@ -102,7 +105,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 @@ -155,7 +158,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: ... @@ -228,7 +231,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 fa3dc6d1e6..ccde945bf1 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, Union, cast +from typing import TYPE_CHECKING, Any, ClassVar, Optional, Tuple, 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 70d1a1d78f..a876c06d0d 100644 --- a/disnake/ui/media_gallery.py +++ b/disnake/ui/media_gallery.py @@ -2,8 +2,7 @@ from __future__ import annotations -from collections.abc import Sequence -from typing import TYPE_CHECKING, ClassVar +from typing import TYPE_CHECKING, ClassVar, List, Sequence, Tuple from ..components import MediaGallery as MediaGalleryComponent, MediaGalleryItem from ..enums import ComponentType @@ -33,7 +32,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 @@ -45,7 +44,7 @@ def __init__(self, *items: MediaGalleryItem, id: int = 0) -> None: ) @property - def items(self) -> list[MediaGalleryItem]: + def items(self) -> List[MediaGalleryItem]: """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 7067c7dea7..5a53898a5e 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, Optional, TypeVar, Union, cast +from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Tuple, TypeVar, Union, cast from ..enums import TextInputStyle from ..utils import MISSING @@ -102,7 +102,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 @@ -117,7 +117,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. @@ -255,7 +255,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], ), } @@ -315,7 +315,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 759c32cca8..fb30771da8 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, Union, cast +from typing import TYPE_CHECKING, Any, ClassVar, List, Tuple, 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 4e0c303b4c..def5bd1e65 100644 --- a/disnake/ui/select/base.py +++ b/disnake/ui/select/base.py @@ -4,13 +4,17 @@ 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, ) @@ -62,7 +66,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", @@ -73,11 +77,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, @@ -91,7 +95,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( @@ -159,7 +163,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]: """List[:class:`.SelectDefaultValue`]: The list of values that are selected by default. Only available for auto-populated select menus. """ @@ -185,7 +189,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 @@ -213,8 +217,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 5a022b9fa5..cf21fe393d 100644 --- a/disnake/ui/select/channel.py +++ b/disnake/ui/select/channel.py @@ -2,13 +2,17 @@ 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, ) @@ -91,13 +95,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, @@ -118,7 +122,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, @@ -134,7 +138,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, @@ -149,7 +153,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, @@ -186,12 +190,12 @@ def from_component(cls, component: ChannelSelectMenu) -> Self: ) @property - def channel_types(self) -> Optional[list[ChannelType]]: + def channel_types(self) -> Optional[List[ChannelType]]: """Optional[List[:class:`disnake.ChannelType`]]: 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): raise TypeError("channel_types must be a list of ChannelType") @@ -212,7 +216,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 0968aac017..a45f9eeff1 100644 --- a/disnake/ui/select/mentionable.py +++ b/disnake/ui/select/mentionable.py @@ -2,13 +2,16 @@ 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, @@ -91,7 +94,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 8912b6f7f1..b77b87dcea 100644 --- a/disnake/ui/select/role.py +++ b/disnake/ui/select/role.py @@ -2,13 +2,16 @@ 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, ) @@ -87,7 +90,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 5d73d5655a..7004c59d67 100644 --- a/disnake/ui/select/string.py +++ b/disnake/ui/select/string.py @@ -2,13 +2,17 @@ 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, @@ -36,10 +40,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()] @@ -106,11 +110,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 @@ -186,12 +190,12 @@ def from_component(cls, component: StringSelectMenu) -> Self: ) @property - def options(self) -> list[SelectOption]: + def options(self) -> List[SelectOption]: """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): raise TypeError("options must be a list of SelectOption") if not all(isinstance(obj, SelectOption) for obj in value): diff --git a/disnake/ui/select/user.py b/disnake/ui/select/user.py index 997bca915a..bd5d894352 100644 --- a/disnake/ui/select/user.py +++ b/disnake/ui/select/user.py @@ -2,13 +2,16 @@ 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, @@ -89,7 +92,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 622ac69652..1f62b686b4 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 +from typing import TYPE_CHECKING, ClassVar, Tuple 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 9dffecba0e..05cd4e1533 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 +from typing import TYPE_CHECKING, ClassVar, Tuple 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 b3da61d41c..497499dc21 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 +from typing import TYPE_CHECKING, ClassVar, Optional, Tuple 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 e80ff4e0b1..b7c1b376ea 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 +from typing import TYPE_CHECKING, ClassVar, Optional, Tuple 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 c03e8e2245..cac0872a02 100644 --- a/disnake/ui/view.py +++ b/disnake/ui/view.py @@ -8,10 +8,9 @@ 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, Optional +from typing import TYPE_CHECKING, Callable, ClassVar, Dict, List, Optional, Sequence, Tuple from ..components import ( VALID_ACTION_ROW_MESSAGE_COMPONENT_TYPES, @@ -51,8 +50,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) @@ -115,10 +114,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__"): @@ -131,7 +130,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 @@ -167,12 +166,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: @@ -388,15 +387,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: @@ -484,9 +483,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 @@ -495,7 +494,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 15ea20ca9b..e6b4d24a6e 100644 --- a/disnake/user.py +++ b/disnake/user.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Optional, Union +from typing import TYPE_CHECKING, Any, Dict, List, 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]: """List[:class:`Guild`]: The guilds that the user shares with the client. .. note:: diff --git a/disnake/utils.py b/disnake/utils.py index fd8b130777..5d7709f813 100644 --- a/disnake/utils.py +++ b/disnake/utils.py @@ -17,19 +17,29 @@ 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, @@ -163,12 +173,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 @@ -184,7 +194,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: @@ -494,7 +504,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)) @@ -621,7 +631,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) @@ -631,7 +641,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): @@ -744,12 +754,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 @@ -945,7 +955,7 @@ class _DocstringParam(_DocstringLocalizationsMixin): class _ParsedDocstring(_DocstringLocalizationsMixin): description: str - params: dict[str, _DocstringParam] + params: Dict[str, _DocstringParam] def _count_left_spaces(string: str) -> int: @@ -957,7 +967,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): @@ -965,7 +975,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() @@ -980,12 +990,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() @@ -994,15 +1004,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 @@ -1021,7 +1031,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]: @@ -1067,7 +1077,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: @@ -1081,7 +1091,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: @@ -1096,14 +1106,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 @@ -1141,7 +1151,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: @@ -1151,13 +1161,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__): @@ -1176,9 +1186,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: @@ -1260,9 +1270,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) @@ -1286,7 +1296,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__ @@ -1299,16 +1309,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()) @@ -1522,7 +1532,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 53decdb057..0e12e09fed 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, Optional +from typing import TYPE_CHECKING, Any, Callable, List, Optional, Tuple 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 @@ -228,7 +228,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,7 +283,9 @@ async def on_voice_server_update(self, data: VoiceServerUpdateEvent) -> None: return self.endpoint = endpoint - self.endpoint = self.endpoint.removeprefix("wss://") + if self.endpoint.startswith("wss://"): + # Just in case, strip it off since we're going to add it later + self.endpoint = self.endpoint[6:] # This gets set later self.endpoint_ip = MISSING @@ -515,7 +517,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 1f6585a2c8..432afe025c 100644 --- a/disnake/webhook/async_.py +++ b/disnake/webhook/async_.py @@ -5,17 +5,21 @@ 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, @@ -86,7 +90,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: @@ -97,21 +101,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) @@ -132,7 +136,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 @@ -253,7 +257,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, @@ -265,7 +269,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, @@ -284,9 +288,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, @@ -314,7 +318,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 @@ -334,12 +338,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 @@ -363,7 +367,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 @@ -408,8 +412,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", @@ -418,7 +422,7 @@ def create_interaction_response( webhook_token=token, ) - payload: dict[str, Any] = { + payload: Dict[str, Any] = { "type": type, } @@ -453,9 +457,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", @@ -482,14 +486,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( @@ -502,10 +506,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, @@ -609,10 +613,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, @@ -796,10 +800,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, @@ -958,7 +962,7 @@ async def inner_call(delay: float = delay) -> None: class BaseWebhook(Hashable): - __slots__: tuple[str, ...] = ( + __slots__: Tuple[str, ...] = ( "id", "type", "guild_id", @@ -1159,7 +1163,7 @@ async def foo(): .. versionadded:: 2.6 """ - __slots__: tuple[str, ...] = ("session",) + __slots__: Tuple[str, ...] = ("session",) def __init__( self, @@ -1262,7 +1266,7 @@ def from_url( if m is None: raise ValueError("Invalid webhook URL given.") - data: dict[str, Any] = m.groupdict() + data: Dict[str, Any] = m.groupdict() data["type"] = 1 return cls(data, session, token=bot_token) # type: ignore @@ -1450,7 +1454,7 @@ async def edit( if self.token is None and self.auth_token is None: raise WebhookTokenMissing("This webhook does not have a token associated with it") - payload: dict[str, Any] = {} + payload: Dict[str, Any] = {} if name is not MISSING: payload["name"] = str(name) if name is not None else None @@ -1527,9 +1531,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 = ..., @@ -1553,9 +1557,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 = ..., @@ -1578,9 +1582,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, @@ -1895,10 +1899,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 e5f070b266..1da14d4ff0 100644 --- a/disnake/webhook/sync.py +++ b/disnake/webhook/sync.py @@ -12,13 +12,17 @@ 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, ) @@ -75,7 +79,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: @@ -86,23 +90,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: @@ -121,8 +125,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 @@ -243,7 +247,7 @@ def edit_webhook( self, webhook_id: int, token: str, - payload: dict[str, Any], + payload: Dict[str, Any], *, session: Session, reason: Optional[str] = None, @@ -255,7 +259,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, @@ -275,9 +279,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: ... @@ -289,9 +293,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: ... @@ -302,9 +306,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]: @@ -331,7 +335,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 @@ -351,12 +355,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 @@ -380,7 +384,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 @@ -450,10 +454,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. @@ -625,7 +629,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 @@ -722,7 +726,7 @@ def from_url( if m is None: raise ValueError("Invalid webhook URL given.") - data: dict[str, Any] = m.groupdict() + data: Dict[str, Any] = m.groupdict() data["type"] = 1 import requests @@ -868,7 +872,7 @@ def edit( if self.token is None and self.auth_token is None: raise WebhookTokenMissing("This webhook does not have a token associated with it") - payload: dict[str, Any] = {} + payload: Dict[str, Any] = {} if name is not MISSING: payload["name"] = str(name) if name is not None else None @@ -928,9 +932,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 = ..., @@ -949,9 +953,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 = ..., @@ -969,9 +973,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, @@ -1194,10 +1198,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 f56fd37e71..a2e2fa171c 100644 --- a/disnake/welcome_screen.py +++ b/disnake/welcome_screen.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional, Union +from typing import TYPE_CHECKING, List, Optional, Union from . import utils from .partial_emoji import PartialEmoji, _EmojiTag @@ -125,7 +125,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"] ] @@ -145,7 +145,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 c37acd3819..386b546b0a 100644 --- a/disnake/widget.py +++ b/disnake/widget.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Optional, Union +from typing import TYPE_CHECKING, Any, Dict, List, 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 34096eb0c3..40b4b3dc7d 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, Optional +from typing import Any, Dict, Optional from sphinx.application import Sphinx @@ -207,7 +207,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 5ca24f507e..4589d73e6d 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, NamedTuple, Optional +from typing import TYPE_CHECKING, ClassVar, DefaultDict, Dict, List, NamedTuple, Optional, Tuple from docutils import nodes from sphinx import addnodes @@ -103,7 +103,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: @@ -117,7 +117,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:
@@ -154,10 +154,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 = { @@ -209,12 +209,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"): [], } @@ -263,7 +263,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 037d0b7e2b..a37bdd3780 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 +from typing import TYPE_CHECKING, ClassVar, List 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 586059e9be..49ed16f539 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 +from typing import TYPE_CHECKING, List 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 b11aa3a50f..d5d4f62ba8 100644 --- a/docs/extensions/fulltoc.py +++ b/docs/extensions/fulltoc.py @@ -29,7 +29,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, cast +from typing import TYPE_CHECKING, List, 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 b008b25db2..46114dd743 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 +from typing import TYPE_CHECKING, Dict 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 f78e6d2892..d93f6f2715 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, Optional +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple 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 4664946515..0ff34a7b5f 100644 --- a/examples/basic_voice.py +++ b/examples/basic_voice.py @@ -9,7 +9,7 @@ import asyncio import os -from typing import Any, Optional +from typing import Any, Dict, 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 629321c08c..020313bdf5 100644 --- a/examples/interactions/autocomplete.py +++ b/examples/interactions/autocomplete.py @@ -3,6 +3,7 @@ """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 @@ -21,7 +22,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 31301f26dc..a6c929cc00 100644 --- a/examples/views/button/paginator.py +++ b/examples/views/button/paginator.py @@ -3,6 +3,7 @@ """A simple paginator example using views and buttons.""" import os +from typing import List import disnake from disnake.ext import commands @@ -10,7 +11,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 937234d1a5..32c0c222fb 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 Optional +from typing import List, 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 cc76c12822..7dc54e12f7 100755 --- a/noxfile.py +++ b/noxfile.py @@ -1,6 +1,6 @@ #!/usr/bin/env -S uv run --script # /// script -# requires-python = ">=3.9" +# requires-python = ">=3.8" # dependencies = [ # "nox==2025.5.1", # ] @@ -16,8 +16,11 @@ from typing import ( TYPE_CHECKING, Any, + Dict, Final, + List, Optional, + Tuple, ) import nox @@ -31,10 +34,10 @@ PYPROJECT = nox.project.load_toml() -SUPPORTED_PYTHONS: Final[list[str]] = nox.project.python_versions(PYPROJECT) +SUPPORTED_PYTHONS: Final[List[str]] = nox.project.python_versions(PYPROJECT) # TODO(onerandomusername): add 3.14 once CI supports 3.14. -EXPERIMENTAL_PYTHON_VERSIONS: Final[list[str]] = [] -ALL_PYTHONS: Final[list[str]] = [*SUPPORTED_PYTHONS, *EXPERIMENTAL_PYTHON_VERSIONS] +EXPERIMENTAL_PYTHON_VERSIONS: Final[List[str]] = [] +ALL_PYTHONS: Final[List[str]] = [*SUPPORTED_PYTHONS, *EXPERIMENTAL_PYTHON_VERSIONS] MIN_PYTHON: Final[str] = SUPPORTED_PYTHONS[0] CI: Final[bool] = "CI" in os.environ @@ -44,19 +47,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: @@ -67,7 +70,7 @@ def __post_init__(self) -> None: self[key] = getattr(self, key) # type: ignore -EXECUTION_GROUPS: list[ExecutionGroup] = [ +EXECUTION_GROUPS: List[ExecutionGroup] = [ ## pyright *( ExecutionGroup( @@ -122,7 +125,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] @@ -147,7 +150,7 @@ def install_deps(session: nox.Session, *, execution_group: Optional[ExecutionGro if not execution_group.project and execution_group.extras: raise TypeError("Cannot install extras without also installing the project") - command: list[str] + command: List[str] # If not using uv, install with pip if os.getenv("INSTALL_WITH_PIP") is not None: @@ -174,7 +177,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}") @@ -284,7 +287,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 a6f87d3c95..75f6d715b6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -209,6 +209,10 @@ 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 2b17943717..74855911f0 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 NamedTuple, NoReturn +from typing import List, NamedTuple, NoReturn TARGET_FILE = Path("disnake/__init__.py") ORIG_INIT_CONTENTS = TARGET_FILE.read_text("utf-8") @@ -66,7 +66,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 3f7effd43d..f0c892013d 100644 --- a/scripts/codemods/base.py +++ b/scripts/codemods/base.py @@ -1,10 +1,9 @@ # 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, Optional +from typing import TYPE_CHECKING, ClassVar, Generator, 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 1e6db4fc68..6c56a9be07 100644 --- a/scripts/codemods/overloads_no_missing.py +++ b/scripts/codemods/overloads_no_missing.py @@ -1,7 +1,6 @@ # SPDX-License-Identifier: MIT -from collections.abc import Sequence -from typing import Optional +from typing import List, Optional, Sequence import libcst as cst import libcst.matchers as m @@ -32,7 +31,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 0f3af98c13..827dc1149d 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 Optional, cast +from typing import List, 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: @@ -38,7 +38,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 bee16fffec..4bb389b0c9 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 Optional, Union +from typing import List, 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 6d712c0a81..28a8dd54ed 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 +from typing import Any, Tuple 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 4f88ffa4c6..bcf957d98e 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -4,8 +4,7 @@ import functools import inspect import types -from contextlib import AbstractContextManager -from typing import TYPE_CHECKING, Callable, Optional, TypeVar +from typing import TYPE_CHECKING, Callable, ContextManager, Optional, Type, TypeVar from unittest import mock if TYPE_CHECKING: @@ -29,7 +28,7 @@ def reveal_type(*args, **kwargs) -> None: CallableT = TypeVar("CallableT", bound=Callable) -class freeze_time(AbstractContextManager): +class freeze_time(ContextManager): """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. @@ -54,7 +53,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 7091874550..365edff619 100644 --- a/tests/test_colour.py +++ b/tests/test_colour.py @@ -1,6 +1,7 @@ # SPDX-License-Identifier: MIT import math +from typing import Tuple import pytest @@ -27,7 +28,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 @@ -37,7 +38,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 @@ -49,7 +50,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 9f15271fb7..ff5d01b452 100644 --- a/tests/test_mentions.py +++ b/tests/test_mentions.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import Union +from typing import Dict, 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 7b0d37bc33..4fcbf5bf01 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT -from typing import Literal, Optional +from typing import Dict, 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 7fa684ba69..fcc1ed60e8 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -9,10 +9,11 @@ import warnings from dataclasses import dataclass from datetime import timedelta, timezone -from typing import ( # noqa: UP035 +from typing import ( TYPE_CHECKING, Any, Callable, + Dict, List, Literal, Optional, @@ -780,8 +781,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), @@ -789,7 +790,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), # noqa: UP006 + ("Tuple[dict, List[Literal[42, 99]]]", Tuple[dict, List[Literal[42, 99]]], True), # 3.10 union syntax pytest.param( "int | float", @@ -821,43 +822,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: @@ -866,8 +867,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 @@ -876,7 +877,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 94ed2f3a73..710c3cca33 100644 --- a/tests/ui/test_components.py +++ b/tests/ui/test_components.py @@ -1,18 +1,19 @@ # 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 623145162e..2e9f3fec42 100644 --- a/tests/ui/test_decorators.py +++ b/tests/ui/test_decorators.py @@ -2,8 +2,7 @@ from __future__ import annotations import contextlib -from collections.abc import Iterator -from typing import Any, TypeVar +from typing import Any, Iterator, Type, TypeVar import pytest from typing_extensions import assert_type @@ -17,7 +16,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") @@ -56,7 +55,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 ae74fdbbd0..7711e861b8 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, TypeVar, Union +from typing import TYPE_CHECKING, List, 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"]) From caf4d8d7b02ddfba92816fa2775f16308ce7efe9 Mon Sep 17 00:00:00 2001 From: arielle Date: Thu, 25 Sep 2025 13:14:49 -0400 Subject: [PATCH 6/6] fix: noxfile 3.9 too --- noxfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noxfile.py b/noxfile.py index 7dc54e12f7..6d192b58ce 100755 --- a/noxfile.py +++ b/noxfile.py @@ -1,6 +1,6 @@ #!/usr/bin/env -S uv run --script # /// script -# requires-python = ">=3.8" +# requires-python = ">=3.9" # dependencies = [ # "nox==2025.5.1", # ]