Skip to content

Commit fe7111e

Browse files
authored
Merge branch 'master' into fix/async-static-autocomplete
2 parents 3b7645a + a0f8e75 commit fe7111e

5 files changed

Lines changed: 387 additions & 47 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ These changes are available on the `master` branch, but have not yet been releas
1717
([#2711](https://github.com/Pycord-Development/pycord/pull/2711))
1818
- Added `RawMessageUpdateEvent.new_message` - message update events now contain full
1919
message objects ([#2780](https://github.com/Pycord-Development/pycord/pull/2780))
20+
- Added `Guild.get_or_fetch()` and `Client.get_or_fetch()` shortcut methods.
21+
([#2776](https://github.com/Pycord-Development/pycord/pull/2776))
2022
- Added support for setting guild-specific `avatar`, `banner`, and `bio` for the bot
2123
user through `Member.edit`.
2224
([#2908](https://github.com/Pycord-Development/pycord/pull/2908))
@@ -57,6 +59,12 @@ These changes are available on the `master` branch, but have not yet been releas
5759
- Fixed `TypeError` when using Python 3.12+ `type` syntax for typing slash command
5860
parameters. ([#2952](https://github.com/Pycord-Development/pycord/pull/2952))
5961

62+
### Deprecated
63+
64+
- Deprecated `utils.get_or_fetch(attr, id)` and `Client.get_or_fetch_user(id)` in favour
65+
of `utils.get_or_fetch(object_type, object_id)` and `Client.get_or_fetch(User, id)`.
66+
([#2776](https://github.com/Pycord-Development/pycord/pull/2776))
67+
6068
### Removed
6169

6270
## [2.7.0rc1] - 2025-08-30

discord/client.py

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,15 @@
3131
import sys
3232
import traceback
3333
from types import TracebackType
34-
from typing import TYPE_CHECKING, Any, Callable, Coroutine, Generator, Sequence, TypeVar
34+
from typing import (
35+
TYPE_CHECKING,
36+
Any,
37+
Callable,
38+
Coroutine,
39+
Generator,
40+
Sequence,
41+
TypeVar,
42+
)
3543

3644
import aiohttp
3745

@@ -61,19 +69,27 @@
6169
from .threads import Thread
6270
from .ui.view import View
6371
from .user import ClientUser, User
64-
from .utils import MISSING
72+
from .utils import _D, _FETCHABLE, MISSING
6573
from .voice_client import VoiceClient
6674
from .webhook import Webhook
6775
from .widget import Widget
6876

6977
if TYPE_CHECKING:
7078
from .abc import GuildChannel, PrivateChannel, Snowflake, SnowflakeTime
71-
from .channel import DMChannel
79+
from .channel import (
80+
CategoryChannel,
81+
DMChannel,
82+
ForumChannel,
83+
StageChannel,
84+
TextChannel,
85+
VoiceChannel,
86+
)
7287
from .interactions import Interaction
7388
from .member import Member
7489
from .message import Message
7590
from .poll import Poll
7691
from .soundboard import SoundboardSound
92+
from .threads import Thread, ThreadMember
7793
from .ui.item import Item
7894
from .voice_client import VoiceProtocol
7995

@@ -1165,7 +1181,12 @@ def get_all_members(self) -> Generator[Member]:
11651181
for guild in self.guilds:
11661182
yield from guild.members
11671183

1168-
async def get_or_fetch_user(self, id: int, /) -> User | None:
1184+
@utils.deprecated(
1185+
instead="Client.get_or_fetch(User, id)",
1186+
since="2.7",
1187+
removed="3.0",
1188+
)
1189+
async def get_or_fetch_user(self, id: int, /) -> User | None: # TODO: Remove in 3.0
11691190
"""|coro|
11701191
11711192
Looks up a user in the user cache or fetches if not found.
@@ -1181,7 +1202,49 @@ async def get_or_fetch_user(self, id: int, /) -> User | None:
11811202
The user or ``None`` if not found.
11821203
"""
11831204

1184-
return await utils.get_or_fetch(obj=self, attr="user", id=id, default=None)
1205+
return await self.get_or_fetch(object_type=User, object_id=id, default=None)
1206+
1207+
async def get_or_fetch(
1208+
self: Client,
1209+
object_type: type[_FETCHABLE],
1210+
object_id: int | None,
1211+
default: _D = None,
1212+
) -> _FETCHABLE | _D | None:
1213+
"""
1214+
Shortcut method to get data from an object either by returning the cached version, or if it does not exist, attempting to fetch it from the API.
1215+
1216+
Parameters
1217+
----------
1218+
object_type: Type[:class:`VoiceChannel` | :class:`TextChannel` | :class:`ForumChannel` | :class:`StageChannel` | :class:`CategoryChannel` | :class:`Thread` | :class:`User` | :class:`Guild` | :class:`GuildEmoji` | :class:`AppEmoji`]
1219+
Type of object to fetch or get.
1220+
1221+
object_id: :class:`int` | :data:`None`
1222+
ID of object to get. If :data:`None`, returns `default` if provided, else :data:`None`.
1223+
1224+
default: Any | :data:`None`
1225+
A default to return instead of raising if fetch fails.
1226+
1227+
Returns
1228+
-------
1229+
:class:`VoiceChannel` | :class:`TextChannel` | :class:`ForumChannel` | :class:`StageChannel` | :class:`CategoryChannel` | :class:`Thread` | :class:`User` | :class:`Guild` | :class:`GuildEmoji` | :class:`AppEmoji` | :data:`None`
1230+
The object if found, or `default` if provided when not found.
1231+
1232+
Raises
1233+
------
1234+
:exc:`TypeError`
1235+
Raised when required parameters are missing or invalid types are provided.
1236+
:exc:`InvalidArgument`
1237+
Raised when an unsupported or incompatible object type is used.
1238+
"""
1239+
try:
1240+
return await utils.get_or_fetch(
1241+
obj=self,
1242+
object_type=object_type,
1243+
object_id=object_id,
1244+
default=default,
1245+
)
1246+
except (HTTPException, ValueError, InvalidData):
1247+
return default
11851248

11861249
# listeners/waiters
11871250

discord/guild.py

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
VoiceRegion,
6767
try_enum,
6868
)
69-
from .errors import ClientException, InvalidArgument, InvalidData
69+
from .errors import ClientException, HTTPException, InvalidArgument, InvalidData
7070
from .file import File
7171
from .flags import SystemChannelFlags
7272
from .incidents import IncidentsData
@@ -90,6 +90,7 @@
9090
from .sticker import GuildSticker
9191
from .threads import Thread, ThreadMember
9292
from .user import User
93+
from .utils import _D, _FETCHABLE
9394
from .welcome_screen import WelcomeScreen, WelcomeScreenChannel
9495
from .widget import Widget
9596

@@ -1041,6 +1042,49 @@ def get_member(self, user_id: int, /) -> Member | None:
10411042
"""
10421043
return self._members.get(user_id)
10431044

1045+
async def get_or_fetch(
1046+
self: Guild,
1047+
object_type: type[_FETCHABLE],
1048+
object_id: int | None,
1049+
default: _D = None,
1050+
) -> _FETCHABLE | _D | None:
1051+
"""
1052+
Shortcut method to get data from this guild either by returning the cached version,
1053+
or if it does not exist, attempting to fetch it from the API.
1054+
1055+
Parameters
1056+
----------
1057+
object_type: Type[:class:`VoiceChannel` | :class:`TextChannel` | :class:`ForumChannel` | :class:`StageChannel` | :class:`CategoryChannel` | :class:`Thread` | :class:`Role` | :class:`Member` | :class:`GuildEmoji`]
1058+
Type of object to fetch or get.
1059+
1060+
object_id: :class:`int` | :data:`None`
1061+
ID of the object to get. If :data:`None`, returns `default` if provided, otherwise :data:`None`.
1062+
1063+
default: Any | :data:`None`
1064+
The value to return instead of raising if fetching fails or if `object_id` is :data:`None`.
1065+
1066+
Returns
1067+
-------
1068+
:class:`VoiceChannel` | :class:`TextChannel` | :class:`ForumChannel` | :class:`StageChannel` | :class:`CategoryChannel` | :class:`Thread` | :class:`Role` | :class:`Member` | :class:`GuildEmoji` | :data:`None`
1069+
The object if found, or `default` if provided when not found.
1070+
1071+
Raises
1072+
------
1073+
:exc:`TypeError`
1074+
Raised when required parameters are missing or invalid types are provided.
1075+
:exc:`InvalidArgument`
1076+
Raised when an unsupported or incompatible object type is used.
1077+
"""
1078+
try:
1079+
return await utils.get_or_fetch(
1080+
obj=self,
1081+
object_type=object_type,
1082+
object_id=object_id,
1083+
default=default,
1084+
)
1085+
except (HTTPException, ValueError, InvalidData):
1086+
return default
1087+
10441088
@property
10451089
def premium_subscribers(self) -> list[Member]:
10461090
"""A list of members who have "boosted" this guild."""
@@ -3012,6 +3056,26 @@ async def delete_sticker(
30123056
"""
30133057
await self._state.http.delete_guild_sticker(self.id, sticker.id, reason)
30143058

3059+
def get_emoji(self, emoji_id: int, /) -> GuildEmoji | None:
3060+
"""Returns an emoji with the given ID.
3061+
3062+
.. versionadded:: 2.7
3063+
3064+
Parameters
3065+
----------
3066+
emoji_id: int
3067+
The ID to get.
3068+
3069+
Returns
3070+
-------
3071+
Optional[:class:`Emoji`]
3072+
The returned Emoji or ``None`` if not found.
3073+
"""
3074+
emoji = self._state.get_emoji(emoji_id)
3075+
if emoji and emoji.guild == self:
3076+
return emoji
3077+
return None
3078+
30153079
async def fetch_emojis(self) -> list[GuildEmoji]:
30163080
r"""|coro|
30173081

discord/incidents.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,27 @@
1+
"""
2+
The MIT License (MIT)
3+
4+
Copyright (c) 2021-present Pycord Development
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a
7+
copy of this software and associated documentation files (the "Software"),
8+
to deal in the Software without restriction, including without limitation
9+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
10+
and/or sell copies of the Software, and to permit persons to whom the
11+
Software is furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in
14+
all copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22+
DEALINGS IN THE SOFTWARE.
23+
"""
24+
125
from __future__ import annotations
226

327
import datetime

0 commit comments

Comments
 (0)