Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ These changes are available on the `master` branch, but have not yet been releas

### Changed

- Migrated away from `utils.deprecated` in favor of `warnings.deprecated` for
deprecation warnings.
([#3042](https://github.com/Pycord-Development/pycord/pull/3042))
- Updated `Role.is_assignable()` to also check whether the bot has the `MANAGE_ROLES`
permission. ([#3048](https://github.com/Pycord-Development/pycord/pull/3048))

Expand Down
24 changes: 16 additions & 8 deletions discord/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,12 @@
import warnings
from importlib.metadata import PackageNotFoundError, version

from typing_extensions import TypedDict
from typing_extensions import TypedDict, deprecated

__all__ = ("__version__", "VersionInfo", "version_info")

from typing import Literal, NamedTuple

from .utils import deprecated

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

@property
@deprecated("releaselevel", "2.4")
@deprecated(
"VersionInfo.release_level is deprecated since version 2.4, consider using releaselevel instead."
)
def release_level(self) -> Literal["alpha", "beta", "candidate", "final"]:
return self.releaselevel

@property
@deprecated('.advanced["serial"]', "2.4")
@deprecated(
'VersionInfo.serial is deprecated since version 2.4, consider using .advanced["serial"] instead.'
)
def serial(self) -> int:
return self.advanced["serial"]

@property
@deprecated('.advanced["build"]', "2.4")
@deprecated(
'VersionInfo.build is deprecated since version 2.4, consider using .advanced["build"] instead.'
)
def build(self) -> int | None:
return self.advanced["build"]

@property
@deprecated('.advanced["commit"]', "2.4")
@deprecated(
'VersionInfo.commit is deprecated since version 2.4, consider using .advanced["commit"] instead.'
)
def commit(self) -> str | None:
return self.advanced["commit"]

@property
@deprecated('.advanced["date"]', "2.4")
@deprecated(
'VersionInfo.date is deprecated since version 2.4, consider using .advanced["date"] instead.'
)
def date(self) -> datetime.date | None:
return self.advanced["date"]

Expand Down
14 changes: 6 additions & 8 deletions discord/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
overload,
)

from typing_extensions import deprecated

import discord.abc

from . import utils
Expand Down Expand Up @@ -3118,21 +3120,17 @@ async def create_forum_channel(self, name: str, **options: Any) -> ForumChannel:
"""
return await self.guild.create_forum_channel(name, category=self, **options)

@utils.deprecated(
since="2.7",
removed="3.0",
reference="NSFW categories are not available in the Discord API.",
@deprecated(
"CategoryChannel.is_nsfw is deprecated since version 2.7 and will be removed in version 3.0. NSFW categories are not available in the Discord API."
)
def is_nsfw(self) -> bool:
return False

# TODO: Remove in 3.0

@property
@utils.deprecated(
since="2.7",
removed="3.0",
reference="NSFW categories are not available in the Discord API.",
@deprecated(
"CategoryChannel.nsfw is deprecated since version 2.7 and will be removed in version 3.0. NSFW categories are not available in the Discord API."
)
def nsfw(self) -> bool:
return False
Expand Down
7 changes: 3 additions & 4 deletions discord/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
)

import aiohttp
from typing_extensions import deprecated

from . import utils
from .activity import ActivityTypes, BaseActivity, create_activity
Expand Down Expand Up @@ -1181,10 +1182,8 @@ def get_all_members(self) -> Generator[Member]:
for guild in self.guilds:
yield from guild.members

@utils.deprecated(
instead="Client.get_or_fetch(User, id)",
since="2.7",
removed="3.0",
@deprecated(
"Client.get_or_fetch_user is deprecated since version 2.7 and will be removed in version 3.0, consider using Client.get_or_fetch(User, id) instead."
)
async def get_or_fetch_user(self, id: int, /) -> User | None: # TODO: Remove in 3.0
"""|coro|
Expand Down
38 changes: 27 additions & 11 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 Down Expand Up @@ -222,6 +224,7 @@ def __init__(self, *, data: InteractionPayload, state: ConnectionState):
self._session: ClientSession = state.http._HTTPClient__session
self._original_response: InteractionMessage | None = None
self.callback: InteractionCallback | None = None
self._cs_channel: InteractionChannel | None = MISSING
self._from_data(data)

def _from_data(self, data: InteractionPayload):
Expand Down Expand Up @@ -350,14 +353,19 @@ def is_component(self) -> bool:
"""Indicates whether the interaction is a message component."""
return self.type == InteractionType.component

@utils.cached_slot_property("_cs_channel")
@utils.deprecated("Interaction.channel", "2.7", stacklevel=4)
@property
@deprecated(
"Interaction.cached_channel is deprecated since version 2.7, consider using Interaction.channel instead."
)
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.

.. deprecated:: 2.7
"""
if self._cs_channel is not MISSING:
return self._cs_channel
r: InteractionChannel | None = None
guild = self.guild
channel = guild and guild._resolve_channel(self.channel_id)
if channel is None:
Expand All @@ -367,11 +375,11 @@ def cached_channel(self) -> InteractionChannel | None:
if self.guild_id is not None
else ChannelType.private
)
return PartialMessageable(
state=self._state, id=self.channel_id, type=type
)
return None
return channel
r = PartialMessageable(state=self._state, id=self.channel_id, type=type)
else:
r = channel
self._cs_channel = r
return r

@property
def permissions(self) -> Permissions:
Expand Down Expand Up @@ -489,7 +497,9 @@ async def original_response(self) -> InteractionMessage:
self._original_response = message
return message

@utils.deprecated("Interaction.original_response", "2.2")
@deprecated(
"Interaction.original_message is deprecated since version 2.2, consider using Interaction.original_response instead."
)
async def original_message(self):
"""An alias for :meth:`original_response`.

Expand Down Expand Up @@ -622,7 +632,9 @@ async def edit_original_response(

return message

@utils.deprecated("Interaction.edit_original_response", "2.2")
@deprecated(
"Interaction.edit_original_message is deprecated since version 2.2, consider using Interaction.edit_original_response instead."
)
async def edit_original_message(self, **kwargs):
"""An alias for :meth:`edit_original_response`.

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

@utils.deprecated("Interaction.delete_original_response", "2.2")
@deprecated(
"Interaction.delete_original_message is deprecated since version 2.2, consider using Interaction.delete_original_response instead."
)
async def delete_original_message(self, **kwargs):
"""An alias for :meth:`delete_original_response`.

Expand Down Expand Up @@ -1374,7 +1388,9 @@ 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(
"InteractionResponse.premium_required is deprecated since version 2.6, consider using a button with type ButtonType.premium instead."
)
async def premium_required(self) -> Interaction:
"""|coro|

Expand Down
11 changes: 7 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,6 @@
MISSING,
_bytes_to_base64_data,
_get_as_snowflake,
deprecated,
snowflake_time,
warn_deprecated,
)
Expand Down Expand Up @@ -489,7 +488,9 @@ def permissions(self) -> Permissions:
return Permissions(self._permissions)

@property
@deprecated("colours.primary", "2.7")
@deprecated(
"Role.colour is deprecated since version 2.7, consider using colours.primary instead."
)
def colour(self) -> Colour:
"""Returns the role colour. Equivalent to :attr:`colours.primary`.
An alias exists under ``color``.
Expand All @@ -499,7 +500,9 @@ def colour(self) -> Colour:
return self.colours.primary

@property
@deprecated("colors.primary", "2.7")
@deprecated(
"Role.color is deprecated since version 2.7, consider using colors.primary instead."
)
def color(self) -> Colour:
"""Returns the role's primary color. Equivalent to :attr:`colors.primary`.
An alias exists under ``colour``.
Expand Down
52 changes: 0 additions & 52 deletions discord/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@
__all__ = (
"parse_time",
"warn_deprecated",
"deprecated",
"oauth_url",
"snowflake_time",
"time_snowflake",
Expand Down Expand Up @@ -345,57 +344,6 @@ def warn_deprecated(
warnings.warn(message, stacklevel=stacklevel, category=DeprecationWarning)


def deprecated(
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.

Parameters
----------
instead: Optional[:class:`str`]
A recommended alternative to the function.
since: Optional[:class:`str`]
The version in which the function was deprecated. This should be in the format ``major.minor(.patch)``, where
the patch version is optional.
removed: Optional[:class:`str`]
The version in which the function is planned to be removed. This should be in the format
``major.minor(.patch)``, where the patch version is optional.
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.
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``.
"""

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


def oauth_url(
client_id: int | str,
*,
Expand Down