Skip to content
14 changes: 8 additions & 6 deletions discord/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@

from typing import Literal, NamedTuple

from .utils import deprecated
from typing_extensions import deprecated

from .utils import deprecated_message

try:
__version__ = version("py-cord")
Expand Down Expand Up @@ -84,27 +86,27 @@ def advanced(self, value: object) -> None:
_advanced = value

@property
@deprecated("releaselevel", "2.4")
@deprecated(deprecated_message("release_level", "releaselevel", "2.4"))
def release_level(self) -> Literal["alpha", "beta", "candidate", "final"]:
return self.releaselevel

@property
@deprecated('.advanced["serial"]', "2.4")
@deprecated(deprecated_message("serial", '.advanced["serial"]', "2.4"))
def serial(self) -> int:
return self.advanced["serial"]

@property
@deprecated('.advanced["build"]', "2.4")
@deprecated(deprecated_message("build", '.advanced["build"]', "2.4"))
def build(self) -> int | None:
return self.advanced["build"]

@property
@deprecated('.advanced["commit"]', "2.4")
@deprecated(deprecated_message("commit", '.advanced["commit"]', "2.4"))
def commit(self) -> str | None:
return self.advanced["commit"]

@property
@deprecated('.advanced["date"]', "2.4")
@deprecated(deprecated_message("date", '.advanced["date"]', "2.4"))
def date(self) -> datetime.date | None:
return self.advanced["date"]

Expand Down
38 changes: 33 additions & 5 deletions discord/interactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import datetime
from typing import TYPE_CHECKING, Any, Coroutine, Union

from typing_extensions import deprecated

from . import utils
from .channel import ChannelType, PartialMessageable, _threaded_channel_factory
from .enums import (
Expand All @@ -47,6 +49,7 @@
from .object import Object
from .permissions import Permissions
from .user import User
from .utils import deprecated_message
from .webhook.async_ import (
Webhook,
WebhookMessage,
Expand Down Expand Up @@ -351,7 +354,10 @@ def is_component(self) -> bool:
return self.type == InteractionType.component

@utils.cached_slot_property("_cs_channel")
@utils.deprecated("Interaction.channel", "2.7", stacklevel=4)
@deprecated(
deprecated_message("Interaction.cached_channel", "Interaction.channel", "2.7"),
stacklevel=2,
)
def cached_channel(self) -> InteractionChannel | None:
"""The cached channel from which the interaction was sent.
DM channels are not resolved. These are :class:`PartialMessageable` instead.
Expand Down Expand Up @@ -490,7 +496,11 @@ async def original_response(self) -> InteractionMessage:
self._original_response = message
return message

@utils.deprecated("Interaction.original_response", "2.2")
@deprecated(
deprecated_message(
"Interaction.original_message", "Interaction.original_response", "2.2"
)
)
async def original_message(self):
"""An alias for :meth:`original_response`.

Expand Down Expand Up @@ -623,7 +633,13 @@ async def edit_original_response(

return message

@utils.deprecated("Interaction.edit_original_response", "2.2")
@deprecated(
deprecated_message(
"Interaction.edit_original_message",
"Interaction.edit_original_response",
"2.2",
)
)
async def edit_original_message(self, **kwargs):
"""An alias for :meth:`edit_original_response`.

Expand Down Expand Up @@ -681,7 +697,13 @@ async def delete_original_response(self, *, delay: float | None = None) -> None:
else:
await func

@utils.deprecated("Interaction.delete_original_response", "2.2")
@deprecated(
deprecated_message(
"Interaction.delete_original_message",
"Interaction.delete_original_response",
"2.2",
)
)
async def delete_original_message(self, **kwargs):
"""An alias for :meth:`delete_original_response`.

Expand Down Expand Up @@ -1375,7 +1397,13 @@ async def send_modal(self, modal: Modal) -> Interaction:
self._parent._state.store_modal(modal, self._parent.user.id)
return self._parent

@utils.deprecated("a button with type ButtonType.premium", "2.6")
@deprecated(
deprecated_message(
"InteractionResponse.premium_required",
"a button with type ButtonType.premium",
"2.6",
)
)
async def premium_required(self) -> Interaction:
"""|coro|

Expand Down
8 changes: 4 additions & 4 deletions discord/role.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

from typing import TYPE_CHECKING, Any, TypeVar

from typing_extensions import Self
from typing_extensions import Self, deprecated

from .asset import Asset
from .colour import Colour
Expand All @@ -39,7 +39,7 @@
MISSING,
_bytes_to_base64_data,
_get_as_snowflake,
deprecated,
deprecated_message,
snowflake_time,
warn_deprecated,
)
Expand Down Expand Up @@ -478,7 +478,7 @@ def permissions(self) -> Permissions:
return Permissions(self._permissions)

@property
@deprecated("colours.primary", "2.7")
@deprecated(deprecated_message("colours.primary", "2.7"))
def colour(self) -> Colour:
"""Returns the role colour. Equivalent to :attr:`colours.primary`.
An alias exists under ``color``.
Expand All @@ -488,7 +488,7 @@ def colour(self) -> Colour:
return self.colours.primary

@property
@deprecated("colors.primary", "2.7")
@deprecated(deprecated_message("colors.primary", "2.7"))
def color(self) -> Colour:
"""Returns the role's primary color. Equivalent to :attr:`colors.primary`.
An alias exists under ``colour``.
Expand Down
65 changes: 28 additions & 37 deletions discord/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import asyncio
import collections.abc
import datetime
import functools
import importlib.resources
import itertools
import json
Expand Down Expand Up @@ -94,7 +93,7 @@
__all__ = (
"parse_time",
"warn_deprecated",
"deprecated",
"deprecated_message",
"oauth_url",
"snowflake_time",
"time_snowflake",
Expand Down Expand Up @@ -302,16 +301,15 @@ def decorator(overridden: T) -> T:
return decorator


def warn_deprecated(
def deprecated_message(
name: str,
instead: str | None = None,
since: str | None = None,
removed: str | None = None,
reference: str | None = None,
stacklevel: int = 3,
) -> None:
"""Warn about a deprecated function, with the ability to specify details about the deprecation. Emits a
DeprecationWarning.
) -> str:
"""
Generates a deprecation message, with the ability to specify details about the deprecation.

Parameters
----------
Expand All @@ -328,8 +326,11 @@ def warn_deprecated(
reference: Optional[:class:`str`]
A reference that explains the deprecation, typically a URL to a page such as a changelog entry or a GitHub
issue/PR.
stacklevel: :class:`int`
The stacklevel kwarg passed to :func:`warnings.warn`. Defaults to 3.

Returns
-------
:class:`str`
The deprecation message.
"""
message = f"{name} is deprecated"
if since:
Expand All @@ -341,24 +342,24 @@ def warn_deprecated(
message += "."
if reference:
message += f" See {reference} for more information."

warnings.warn(message, stacklevel=stacklevel, category=DeprecationWarning)
return message


def deprecated(
def warn_deprecated(
name: str,
instead: str | None = None,
since: str | None = None,
removed: str | None = None,
reference: str | None = None,
stacklevel: int = 3,
*,
use_qualname: bool = True,
) -> Callable[[Callable[[P], T]], Callable[[P], T]]:
"""A decorator implementation of :func:`warn_deprecated`. This will automatically call :func:`warn_deprecated` when
the decorated function is called.
) -> None:
"""Warn about a deprecated function, with the ability to specify details about the deprecation. Emits a
DeprecationWarning.

Parameters
----------
name: str
The name of the deprecated function.
instead: Optional[:class:`str`]
A recommended alternative to the function.
since: Optional[:class:`str`]
Expand All @@ -372,28 +373,18 @@ def deprecated(
issue/PR.
stacklevel: :class:`int`
The stacklevel kwarg passed to :func:`warnings.warn`. Defaults to 3.
use_qualname: :class:`bool`
Whether to use the qualified name of the function in the deprecation warning. If ``False``, the short name of
the function will be used instead. For example, __qualname__ will display as ``Client.login`` while __name__
will display as ``login``. Defaults to ``True``.
"""
warnings.simplefilter("always", DeprecationWarning) # turn off filter
message = deprecated_message(
name=name,
instead=instead,
since=since,
removed=removed,
reference=reference,
)

def actual_decorator(func: Callable[[P], T]) -> Callable[[P], T]:
@functools.wraps(func)
def decorated(*args: P.args, **kwargs: P.kwargs) -> T:
warn_deprecated(
name=func.__qualname__ if use_qualname else func.__name__,
instead=instead,
since=since,
removed=removed,
reference=reference,
stacklevel=stacklevel,
)
return func(*args, **kwargs)

return decorated

return actual_decorator
warnings.warn(message, stacklevel=stacklevel, category=DeprecationWarning)
warnings.simplefilter("default", DeprecationWarning) # reset filter


def oauth_url(
Expand Down
Loading