Skip to content

Commit 9755fe8

Browse files
committed
♻️ move cached_slot_property to private
1 parent aec45a2 commit 9755fe8

File tree

7 files changed

+213
-67
lines changed

7 files changed

+213
-67
lines changed

discord/interactions.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import datetime
3030
from typing import TYPE_CHECKING, Any, Coroutine, Union
3131

32-
from .utils.private import get_as_snowflake, deprecated, delay_task
32+
from .utils.private import get_as_snowflake, deprecated, delay_task, cached_slot_property
3333
from . import utils
3434
from .channel import ChannelType, PartialMessageable, _threaded_channel_factory
3535
from .enums import (
@@ -297,7 +297,7 @@ def is_component(self) -> bool:
297297
"""Indicates whether the interaction is a message component."""
298298
return self.type == InteractionType.component
299299

300-
@utils.cached_slot_property("_cs_channel")
300+
@cached_slot_property("_cs_channel")
301301
@deprecated("Interaction.channel", "2.7", stacklevel=4)
302302
def cached_channel(self) -> InteractionChannel | None:
303303
"""The cached channel from which the interaction was sent.
@@ -322,12 +322,12 @@ def permissions(self) -> Permissions:
322322
"""
323323
return Permissions(self._permissions)
324324

325-
@utils.cached_slot_property("_cs_app_permissions")
325+
@cached_slot_property("_cs_app_permissions")
326326
def app_permissions(self) -> Permissions:
327327
"""The resolved permissions of the application in the channel, including overwrites."""
328328
return Permissions(self._app_permissions)
329329

330-
@utils.cached_slot_property("_cs_response")
330+
@cached_slot_property("_cs_response")
331331
def response(self) -> InteractionResponse:
332332
"""Returns an object responsible for handling responding to the interaction.
333333
@@ -336,7 +336,7 @@ def response(self) -> InteractionResponse:
336336
"""
337337
return InteractionResponse(self)
338338

339-
@utils.cached_slot_property("_cs_followup")
339+
@cached_slot_property("_cs_followup")
340340
def followup(self) -> Webhook:
341341
"""Returns the followup webhook for followup interactions."""
342342
payload = {
@@ -1542,7 +1542,7 @@ def __init__(self, *, data: InteractionMetadataPayload, state: ConnectionState):
15421542
def __repr__(self):
15431543
return f"<InteractionMetadata id={self.id} type={self.type!r} user={self.user!r}>"
15441544

1545-
@utils.cached_slot_property("_cs_original_response_message")
1545+
@cached_slot_property("_cs_original_response_message")
15461546
def original_response_message(self) -> Message | None:
15471547
"""Optional[:class:`Message`]: The original response message.
15481548
Returns ``None`` if the message is not in cache, or if :attr:`original_response_message_id` is ``None``.
@@ -1551,7 +1551,7 @@ def original_response_message(self) -> Message | None:
15511551
return None
15521552
return self._state._get_message(self.original_response_message_id)
15531553

1554-
@utils.cached_slot_property("_cs_interacted_message")
1554+
@cached_slot_property("_cs_interacted_message")
15551555
def interacted_message(self) -> Message | None:
15561556
"""Optional[:class:`Message`]: The message that triggered the interaction.
15571557
Returns ``None`` if the message is not in cache, or if :attr:`interacted_message_id` is ``None``.
@@ -1597,7 +1597,7 @@ def __eq__(self, other):
15971597
def __ne__(self, other):
15981598
return not self.__eq__(other)
15991599

1600-
@utils.cached_slot_property("_cs_user")
1600+
@cached_slot_property("_cs_user")
16011601
def user(self) -> User | None:
16021602
"""Optional[:class:`User`]: The user that authorized the integration.
16031603
Returns ``None`` if the user is not in cache, or if :attr:`user_id` is ``None``.
@@ -1606,7 +1606,7 @@ def user(self) -> User | None:
16061606
return None
16071607
return self._state.get_user(self.user_id)
16081608

1609-
@utils.cached_slot_property("_cs_guild")
1609+
@cached_slot_property("_cs_guild")
16101610
def guild(self) -> Guild | None:
16111611
"""Optional[:class:`Guild`]: The guild that authorized the integration.
16121612
Returns ``None`` if the guild is not in cache, or if :attr:`guild_id` is ``0`` or ``None``.

discord/message.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
)
4242
from urllib.parse import parse_qs, urlparse
4343

44-
from .utils.private import get_as_snowflake, parse_time, warn_deprecated, delay_task
44+
from .utils.private import get_as_snowflake, parse_time, warn_deprecated, delay_task, cached_slot_property
4545
from . import utils
4646
from .channel import PartialMessageable
4747
from .components import _component_factory
@@ -1263,7 +1263,7 @@ def interaction(self, value: MessageInteraction | None) -> None:
12631263
)
12641264
self._interaction = value
12651265

1266-
@utils.cached_slot_property("_cs_raw_mentions")
1266+
@cached_slot_property("_cs_raw_mentions")
12671267
def raw_mentions(self) -> list[int]:
12681268
"""A property that returns an array of user IDs matched with
12691269
the syntax of ``<@user_id>`` in the message content.
@@ -1273,28 +1273,28 @@ def raw_mentions(self) -> list[int]:
12731273
"""
12741274
return [int(x) for x in re.findall(r"<@!?([0-9]{15,20})>", self.content)]
12751275

1276-
@utils.cached_slot_property("_cs_raw_channel_mentions")
1276+
@cached_slot_property("_cs_raw_channel_mentions")
12771277
def raw_channel_mentions(self) -> list[int]:
12781278
"""A property that returns an array of channel IDs matched with
12791279
the syntax of ``<#channel_id>`` in the message content.
12801280
"""
12811281
return [int(x) for x in re.findall(r"<#([0-9]{15,20})>", self.content)]
12821282

1283-
@utils.cached_slot_property("_cs_raw_role_mentions")
1283+
@cached_slot_property("_cs_raw_role_mentions")
12841284
def raw_role_mentions(self) -> list[int]:
12851285
"""A property that returns an array of role IDs matched with
12861286
the syntax of ``<@&role_id>`` in the message content.
12871287
"""
12881288
return [int(x) for x in re.findall(r"<@&([0-9]{15,20})>", self.content)]
12891289

1290-
@utils.cached_slot_property("_cs_channel_mentions")
1290+
@cached_slot_property("_cs_channel_mentions")
12911291
def channel_mentions(self) -> list[GuildChannel]:
12921292
if self.guild is None:
12931293
return []
12941294
it = filter(None, map(self.guild.get_channel, self.raw_channel_mentions))
12951295
return list(dict.fromkeys(it)) # using dict.fromkeys and not set to preserve order
12961296

1297-
@utils.cached_slot_property("_cs_clean_content")
1297+
@cached_slot_property("_cs_clean_content")
12981298
def clean_content(self) -> str:
12991299
"""A property that returns the content in a "cleaned up"
13001300
manner. This basically means that mentions are transformed
@@ -1371,7 +1371,7 @@ def is_system(self) -> bool:
13711371
MessageType.thread_starter_message,
13721372
)
13731373

1374-
@utils.cached_slot_property("_cs_system_content")
1374+
@cached_slot_property("_cs_system_content")
13751375
def system_content(self) -> str:
13761376
r"""A property that returns the content that is rendered
13771377
regardless of the :attr:`Message.type`.
@@ -2185,7 +2185,7 @@ def created_at(self) -> datetime.datetime:
21852185
def poll(self) -> Poll | None:
21862186
return self._state._polls.get(self.id)
21872187

2188-
@utils.cached_slot_property("_cs_guild")
2188+
@cached_slot_property("_cs_guild")
21892189
def guild(self) -> Guild | None:
21902190
"""The guild that the partial message belongs to, if applicable."""
21912191
return getattr(self.channel, "guild", None)

discord/stage_instance.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
from .enums import StagePrivacyLevel, try_enum
3131
from .errors import InvalidArgument
3232
from .mixins import Hashable
33-
from .utils import MISSING, Undefined, cached_slot_property
33+
from .utils import MISSING, Undefined
34+
from .utils.private import cached_slot_property
3435

3536
__all__ = ("StageInstance",)
3637

discord/sticker.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
from .enums import StickerFormatType, StickerType, try_enum
3333
from .errors import InvalidData
3434
from .mixins import Hashable
35-
from .utils import MISSING, Undefined, cached_slot_property, find, snowflake_time
35+
from .utils import MISSING, Undefined, find, snowflake_time
36+
from .utils.private import cached_slot_property
3637

3738
__all__ = (
3839
"StickerPack",

discord/utils/__init__.py

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,11 @@
3030
TYPE_CHECKING,
3131
Any,
3232
AsyncIterator,
33-
Callable,
34-
Generic,
3533
Iterator,
3634
Mapping,
3735
Protocol,
3836
TypeVar,
3937
Union,
40-
overload,
4138
)
4239

4340
from ..errors import HTTPException
@@ -126,50 +123,6 @@ class _RequestLike(Protocol):
126123
_Iter = Union[Iterator[T], AsyncIterator[T]]
127124

128125

129-
class CachedSlotProperty(Generic[T, T_co]):
130-
def __init__(self, name: str, function: Callable[[T], T_co]) -> None:
131-
self.name = name
132-
self.function = function
133-
self.__doc__ = getattr(function, "__doc__")
134-
135-
@overload
136-
def __get__(self, instance: None, owner: type[T]) -> CachedSlotProperty[T, T_co]: ...
137-
138-
@overload
139-
def __get__(self, instance: T, owner: type[T]) -> T_co: ...
140-
141-
def __get__(self, instance: T | None, owner: type[T]) -> Any:
142-
if instance is None:
143-
return self
144-
145-
try:
146-
return getattr(instance, self.name)
147-
except AttributeError:
148-
value = self.function(instance)
149-
setattr(instance, self.name, value)
150-
return value
151-
152-
153-
class classproperty(Generic[T_co]):
154-
def __init__(self, fget: Callable[[Any], T_co]) -> None:
155-
self.fget = fget
156-
157-
def __get__(self, instance: Any | None, owner: type[Any]) -> T_co:
158-
return self.fget(owner)
159-
160-
def __set__(self, instance, value) -> None:
161-
raise AttributeError("cannot set attribute")
162-
163-
164-
def cached_slot_property(
165-
name: str,
166-
) -> Callable[[Callable[[T], T_co]], CachedSlotProperty[T, T_co]]:
167-
def decorator(func: Callable[[T], T_co]) -> CachedSlotProperty[T, T_co]:
168-
return CachedSlotProperty(name, func)
169-
170-
return decorator
171-
172-
173126
async def get_or_fetch(obj, attr: str, id: int, *, default: Any = MISSING) -> Any:
174127
"""|coro|
175128

discord/utils/private.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
Iterator,
3333
)
3434

35-
from . import T_co
3635
from ..errors import InvalidArgument, HTTPException
3736

3837
if TYPE_CHECKING:
@@ -43,6 +42,7 @@
4342

4443
P = ParamSpec("P")
4544
T = TypeVar("T")
45+
T_co = TypeVar("T_co", covariant=True)
4646

4747

4848
def resolve_invite(invite: Invite | str) -> str:
@@ -489,3 +489,36 @@ def index(self, value: Any, *args, **kwargs) -> int:
489489

490490
def count(self, value: Any) -> int:
491491
return self.__proxied.count(value)
492+
493+
494+
class CachedSlotProperty(Generic[T, T_co]):
495+
def __init__(self, name: str, function: Callable[[T], T_co]) -> None:
496+
self.name = name
497+
self.function = function
498+
self.__doc__ = getattr(function, "__doc__")
499+
500+
@overload
501+
def __get__(self, instance: None, owner: type[T]) -> CachedSlotProperty[T, T_co]: ...
502+
503+
@overload
504+
def __get__(self, instance: T, owner: type[T]) -> T_co: ...
505+
506+
def __get__(self, instance: T | None, owner: type[T]) -> Any:
507+
if instance is None:
508+
return self
509+
510+
try:
511+
return getattr(instance, self.name)
512+
except AttributeError:
513+
value = self.function(instance)
514+
setattr(instance, self.name, value)
515+
return value
516+
517+
518+
def cached_slot_property(
519+
name: str,
520+
) -> Callable[[Callable[[T], T_co]], CachedSlotProperty[T, T_co]]:
521+
def decorator(func: Callable[[T], T_co]) -> CachedSlotProperty[T, T_co]:
522+
return CachedSlotProperty(name, func)
523+
524+
return decorator

0 commit comments

Comments
 (0)