Skip to content

feat: Implement better get_or_fetch #2776

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 72 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
dce0206
Update CHANGELOG.md
Lumabots May 2, 2025
b2b8884
add a get or fetch to guild
Lumabots May 3, 2025
8f9a257
Implement better get_or_fetch using typevar and object
Lumabots May 3, 2025
9f6219c
shortcut for get or fetch
Lumabots May 3, 2025
4af5149
Update CHANGELOG.md
Lumabots May 3, 2025
6f59fcd
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 3, 2025
c0689cc
usage of subclass
Lumabots May 3, 2025
b20822a
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 3, 2025
4a363f5
add get_emoji method
Lumabots May 3, 2025
c3a7dd2
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 3, 2025
e614c47
add get_or_fetch_emoji method
Lumabots May 3, 2025
0c0a042
shortcut getorfetch client + removal of get_or_fetch user in favor of…
Lumabots May 4, 2025
466e41b
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 4, 2025
388a234
Update utils.py
Lumabots May 4, 2025
9737f69
Update guild.py
Lumabots May 4, 2025
656de14
Update client.py
Lumabots May 4, 2025
461eab7
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 4, 2025
b6f8878
Update utils.py
Lumabots May 4, 2025
f2a7d72
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 4, 2025
5d68207
add utils.deprecated
Lumabots May 4, 2025
4ca87d8
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 4, 2025
9903fb7
add warning
Lumabots May 4, 2025
a1ec6f9
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 4, 2025
47de080
Update client.py
Lumabots May 4, 2025
4430825
added backward support
Lumabots May 5, 2025
010cc78
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 5, 2025
368a55d
fixed missing coma
Lumabots May 5, 2025
76c56a8
ig im drunk
Lumabots May 5, 2025
811682d
fix my drunkness
Lumabots May 5, 2025
a102d5d
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 5, 2025
528b84b
now im not drunk
Lumabots May 5, 2025
7e766be
Update utils.py
Lumabots May 5, 2025
f6b8e18
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 5, 2025
a5deffe
Update utils.py
Lumabots May 5, 2025
fff74c4
Update utils.py
Lumabots May 5, 2025
9e45627
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 5, 2025
0baae1d
usage of abc
Lumabots May 5, 2025
a3aeb4b
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 5, 2025
2404d9c
_EmojiTag
Lumabots May 5, 2025
23409a7
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 5, 2025
8f278f8
Update utils.py
Lumabots May 5, 2025
6d5be54
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 5, 2025
11fbbc9
Update utils.py
Lumabots May 9, 2025
590339a
Merge branch 'master' into get_or_fetch
Lumabots May 9, 2025
267d574
Update discord/client.py
Lumabots May 9, 2025
dc45449
add the raise error
Lumabots May 9, 2025
f22d8a2
Update discord/utils.py
Lumabots May 9, 2025
cbb7951
Update utils.pyfix missing appemoji
Lumabots May 9, 2025
fdbb7d3
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 9, 2025
5b35d95
add missing raise to doc
Lumabots May 9, 2025
b8a8628
refactor: add TODO comments for removal of deprecated arguments in ge…
Lumabots May 9, 2025
ba5541e
refactor: move _FETCHABLE type variable to utils for better accessibi…
Lumabots May 9, 2025
5421a3f
fix: update import statement for _FETCHABLE from utils module
Lumabots May 9, 2025
50318c2
refactor: streamline get_or_fetch logic with a mapping for object types
Lumabots May 9, 2025
541e668
fix: add validation for Guild type in get_or_fetch function
Lumabots May 9, 2025
b20cffb
fix: correct base type resolution in get_or_fetch function
Lumabots May 9, 2025
3e94a4f
fix: add Role type support in get_or_fetch function
Lumabots May 14, 2025
7384d7c
fix: update role retrieval methods in get_or_fetch function
Lumabots May 14, 2025
b832b55
Merge branch 'master' into get_or_fetch
Lumabots May 14, 2025
0ffaa4b
Update CHANGELOG.md
Lumabots May 15, 2025
92d2987
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 15, 2025
b8c7f7f
Update CHANGELOG.md
Lumabots May 17, 2025
53dc93c
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 17, 2025
6d89376
Update CHANGELOG.md
Lumabots May 17, 2025
e2e8b3d
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 17, 2025
2abfba2
Update CHANGELOG.md
Lumabots May 18, 2025
fb9e077
Merge branch 'master' into get_or_fetch
Lumabots May 20, 2025
c60fbab
feat: update get_or_fetch method to accept Optional[int] for object_id
Lumabots Jun 6, 2025
29863f4
Merge branch 'master' into get_or_fetch
Lumabots Jun 6, 2025
4a5eca4
fix: "MISSING" not being exported
Lumabots Jun 14, 2025
2ed0de6
Merge branch 'master' into get_or_fetch
Lumabots Jun 20, 2025
0c99851
Merge branch 'master' into get_or_fetch
Lumabots Jun 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ These changes are available on the `master` branch, but have not yet been releas
([#2714](https://github.com/Pycord-Development/pycord/pull/2714))
- Added the ability to pass a `datetime.time` object to `format_dt`.
([#2747](https://github.com/Pycord-Development/pycord/pull/2747))
- Added `Guild.get_or_fetch()` and `Client.get_or_fetch()` shortcut methods.
([#2776](https://github.com/Pycord-Development/pycord/pull/2776))
- Added `discord.Interaction.created_at`.
([#2801](https://github.com/Pycord-Development/pycord/pull/2801))

Expand Down Expand Up @@ -147,6 +149,9 @@ These changes are available on the `master` branch, but have not yet been releas
([#2501](https://github.com/Pycord-Development/pycord/pull/2501))
- Deprecated `Interaction.cached_channel` in favor of `Interaction.channel`.
([#2658](https://github.com/Pycord-Development/pycord/pull/2658))
- Deprecated `utils.get_or_fetch(attr, id)` in favor of
`utils.get_or_fetch(object_type, object_id)`.
([#2776](https://github.com/Pycord-Development/pycord/pull/2776))

### Removed

Expand Down
67 changes: 62 additions & 5 deletions discord/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,15 @@
import sys
import traceback
from types import TracebackType
from typing import TYPE_CHECKING, Any, Callable, Coroutine, Generator, Sequence, TypeVar
from typing import (
TYPE_CHECKING,
Any,
Callable,
Coroutine,
Generator,
Sequence,
TypeVar,
)

import aiohttp

Expand Down Expand Up @@ -60,17 +68,25 @@
from .threads import Thread
from .ui.view import View
from .user import ClientUser, User
from .utils import MISSING
from .utils import _FETCHABLE, MISSING
from .voice_client import VoiceClient
from .webhook import Webhook
from .widget import Widget

if TYPE_CHECKING:
from .abc import GuildChannel, PrivateChannel, Snowflake, SnowflakeTime
from .channel import DMChannel
from .channel import (
CategoryChannel,
DMChannel,
ForumChannel,
StageChannel,
TextChannel,
VoiceChannel,
)
from .member import Member
from .message import Message
from .poll import Poll
from .threads import Thread, ThreadMember
from .voice_client import VoiceProtocol

__all__ = ("Client",)
Expand Down Expand Up @@ -1113,7 +1129,12 @@ def get_all_members(self) -> Generator[Member]:
for guild in self.guilds:
yield from guild.members

async def get_or_fetch_user(self, id: int, /) -> User | None:
@utils.deprecated(
instead="Client.get_or_fetch(User, id)",
since="2.7",
removed="3.0",
)
async def get_or_fetch_user(self, id: int, /) -> User | None: # TODO: Remove in 3.0
"""|coro|

Looks up a user in the user cache or fetches if not found.
Expand All @@ -1129,7 +1150,43 @@ async def get_or_fetch_user(self, id: int, /) -> User | None:
The user or ``None`` if not found.
"""

return await utils.get_or_fetch(obj=self, attr="user", id=id, default=None)
return await self.get_or_fetch(object_type=User, object_id=id, default=None)

async def get_or_fetch(
self: Client,
object_type: type[_FETCHABLE],
object_id: int | None,
default: Any = MISSING,
) -> _FETCHABLE | None:
"""
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.

Parameters
----------
object_type: Union[:class:`VoiceChannel`, :class:`TextChannel`, :class:`ForumChannel`, :class:`StageChannel`, :class:`CategoryChannel`, :class:`Thread`, :class:`User`, :class:`Guild`, :class:`GuildEmoji`, :class:`AppEmoji`]
Type of object to fetch or get.
object_id: :class:`int`
ID of object to get.
default : Any, optional
A default to return instead of raising if fetch fails.

Returns
-------
Optional[Union[:class:`VoiceChannel`, :class:`TextChannel`, :class:`ForumChannel`, :class:`StageChannel`, :class:`CategoryChannel`, :class:`Thread`, :class:`User`, :class:`Guild`, :class:`GuildEmoji`, :class:`AppEmoji`]]
The object of type that was specified or ``None`` if not found.

Raises
------
:exc:`NotFound`
Invalid ID for the object
:exc:`HTTPException`
An error occurred fetching the object
:exc:`Forbidden`
You do not have permission to fetch the object
"""
return await utils.get_or_fetch(
obj=self, object_type=object_type, object_id=object_id, default=default
)

# listeners/waiters

Expand Down
60 changes: 60 additions & 0 deletions discord/guild.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
from .sticker import GuildSticker
from .threads import Thread, ThreadMember
from .user import User
from .utils import _FETCHABLE
from .welcome_screen import WelcomeScreen, WelcomeScreenChannel
from .widget import Widget

Expand Down Expand Up @@ -863,6 +864,45 @@ def get_member(self, user_id: int, /) -> Member | None:
"""
return self._members.get(user_id)

async def get_or_fetch(
self: Guild,
object_type: type[_FETCHABLE],
object_id: int | None,
default: Any = MISSING,
) -> _FETCHABLE | None:
"""
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.

Parameters
----------
object_type: Union[:class:`VoiceChannel`, :class:`TextChannel`, :class:`ForumChannel`, :class:`StageChannel`, :class:`CategoryChannel`, :class:`Thread`, :class:`Role`, :class:`Member`, :class:`GuildEmoji`]
Type of object to fetch or get.

object_id: :class:`int`
ID of object to get.

default : Any, optional
A default to return instead of raising if fetch fails.

Returns
-------

Optional[Union[:class:`VoiceChannel`, :class:`TextChannel`, :class:`ForumChannel`, :class:`StageChannel`, :class:`CategoryChannel`, :class:`Thread`, :class:`Role`, :class:`Member`, :class:`GuildEmoji`]]
The object of type that was specified or ``None`` if not found.

Raises
------
:exc:`NotFound`
Invalid ID for the object
:exc:`HTTPException`
An error occurred fetching the object
:exc:`Forbidden`
You do not have permission to fetch the object
"""
return await utils.get_or_fetch(
obj=self, object_type=object_type, object_id=object_id, default=default
)

@property
def premium_subscribers(self) -> list[Member]:
"""A list of members who have "boosted" this guild."""
Expand Down Expand Up @@ -2664,6 +2704,26 @@ async def delete_sticker(
"""
await self._state.http.delete_guild_sticker(self.id, sticker.id, reason)

def get_emoji(self, emoji_id: int, /) -> GuildEmoji | None:
"""Returns an emoji with the given ID.

.. versionadded:: 2.7

Parameters
----------
emoji_id: int
The ID to search for.

Returns
-------
Optional[:class:`Emoji`]
The returned Emoji or ``None`` if not found.
"""
emoji = self._state.get_emoji(emoji_id)
if emoji and emoji.guild == self:
return emoji
return None

async def fetch_emojis(self) -> list[GuildEmoji]:
r"""|coro|

Expand Down
Loading