diff --git a/discord/_version.py b/discord/_version.py index ba68799dfe..dbbebd63ee 100644 --- a/discord/_version.py +++ b/discord/_version.py @@ -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") @@ -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"] diff --git a/discord/interactions.py b/discord/interactions.py index 888ed7658f..e151fef62c 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -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 ( @@ -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, @@ -340,7 +343,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. @@ -482,7 +488,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`. @@ -611,7 +621,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`. @@ -669,7 +685,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`. @@ -1322,7 +1344,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| diff --git a/discord/role.py b/discord/role.py index 60016f1aec..9bed278068 100644 --- a/discord/role.py +++ b/discord/role.py @@ -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 @@ -39,7 +39,7 @@ MISSING, _bytes_to_base64_data, _get_as_snowflake, - deprecated, + deprecated_message, snowflake_time, warn_deprecated, ) @@ -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``. @@ -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``. diff --git a/discord/utils.py b/discord/utils.py index 17cee5fc10..c406f54856 100644 --- a/discord/utils.py +++ b/discord/utils.py @@ -29,7 +29,6 @@ import asyncio import collections.abc import datetime -import functools import importlib.resources import itertools import json @@ -76,7 +75,7 @@ __all__ = ( "parse_time", "warn_deprecated", - "deprecated", + "deprecated_message", "oauth_url", "snowflake_time", "time_snowflake", @@ -293,16 +292,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 ---------- @@ -319,10 +317,12 @@ 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. """ - warnings.simplefilter("always", DeprecationWarning) # turn off filter message = f"{name} is deprecated" if since: message += f" since version {since}" @@ -333,25 +333,24 @@ def warn_deprecated( message += "." if reference: message += f" See {reference} for more information." - - warnings.warn(message, stacklevel=stacklevel, category=DeprecationWarning) - warnings.simplefilter("default", DeprecationWarning) # reset filter + 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`] @@ -365,28 +364,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(