diff options
| author | James <[email protected]> | 2021-04-04 23:05:49 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-04-04 18:05:49 -0400 |
| commit | 34ab772653152d8e448f21cc4ccb9990edafae73 (patch) | |
| tree | bb46bf3f14be9a672cd37358ad0d6948c6f49cfd /discord/abc.py | |
| parent | Flatten AsyncIterator.flatten (diff) | |
| download | discord.py-34ab772653152d8e448f21cc4ccb9990edafae73.tar.xz discord.py-34ab772653152d8e448f21cc4ccb9990edafae73.zip | |
Use typing.Protocol instead of abc.ABCMeta
Diffstat (limited to 'discord/abc.py')
| -rw-r--r-- | discord/abc.py | 112 |
1 files changed, 53 insertions, 59 deletions
diff --git a/discord/abc.py b/discord/abc.py index c3735f6c..4930ae31 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -22,10 +22,12 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -import abc +from __future__ import annotations + import sys import copy import asyncio +from typing import TYPE_CHECKING, Optional, Protocol, runtime_checkable from .iterators import HistoryIterator from .context_managers import Typing @@ -39,13 +41,22 @@ from .file import File from .voice_client import VoiceClient, VoiceProtocol from . import utils +if TYPE_CHECKING: + from datetime import datetime + + from .user import ClientUser + + class _Undefined: def __repr__(self): return 'see-below' + _undefined = _Undefined() -class Snowflake(metaclass=abc.ABCMeta): + +@runtime_checkable +class Snowflake(Protocol): """An ABC that details the common operations on a Discord model. Almost all :ref:`Discord models <discord_api_models>` meet this @@ -60,27 +71,16 @@ class Snowflake(metaclass=abc.ABCMeta): The model's unique ID. """ __slots__ = () + id: int @property - @abc.abstractmethod - def created_at(self): + def created_at(self) -> datetime: """:class:`datetime.datetime`: Returns the model's creation time as a naive datetime in UTC.""" raise NotImplementedError - @classmethod - def __subclasshook__(cls, C): - if cls is Snowflake: - mro = C.__mro__ - for attr in ('created_at', 'id'): - for base in mro: - if attr in base.__dict__: - break - else: - return NotImplemented - return True - return NotImplemented -class User(metaclass=abc.ABCMeta): +@runtime_checkable +class User(Snowflake, Protocol): """An ABC that details the common operations on a Discord user. The following implement this ABC: @@ -104,35 +104,24 @@ class User(metaclass=abc.ABCMeta): """ __slots__ = () + name: str + discriminator: str + avatar: Optional[str] + bot: bool + @property - @abc.abstractmethod - def display_name(self): + def display_name(self) -> str: """:class:`str`: Returns the user's display name.""" raise NotImplementedError @property - @abc.abstractmethod - def mention(self): + def mention(self) -> str: """:class:`str`: Returns a string that allows you to mention the given user.""" raise NotImplementedError - @classmethod - def __subclasshook__(cls, C): - if cls is User: - if Snowflake.__subclasshook__(C) is NotImplemented: - return NotImplemented - - mro = C.__mro__ - for attr in ('display_name', 'mention', 'name', 'avatar', 'discriminator', 'bot'): - for base in mro: - if attr in base.__dict__: - break - else: - return NotImplemented - return True - return NotImplemented -class PrivateChannel(metaclass=abc.ABCMeta): +@runtime_checkable +class PrivateChannel(Snowflake, Protocol): """An ABC that details the common operations on a private Discord channel. The following implement this ABC: @@ -149,18 +138,8 @@ class PrivateChannel(metaclass=abc.ABCMeta): """ __slots__ = () - @classmethod - def __subclasshook__(cls, C): - if cls is PrivateChannel: - if Snowflake.__subclasshook__(C) is NotImplemented: - return NotImplemented + me: ClientUser - mro = C.__mro__ - for base in mro: - if 'me' in base.__dict__: - return True - return NotImplemented - return NotImplemented class _Overwrites: __slots__ = ('id', 'allow', 'deny', 'type') @@ -179,7 +158,8 @@ class _Overwrites: 'type': self.type, } -class GuildChannel: + +class GuildChannel(Protocol): """An ABC that details the common operations on a Discord guild channel. The following implement this ABC: @@ -190,6 +170,11 @@ class GuildChannel: This ABC must also implement :class:`~discord.abc.Snowflake`. + Note + ---- + This ABC is not decorated with :func:`typing.runtime_checkable`, so will fail :func:`isinstance`/:func:`issubclass` + checks. + Attributes ----------- name: :class:`str` @@ -826,14 +811,13 @@ class GuildChannel: lock_permissions = kwargs.get('sync_permissions', False) reason = kwargs.get('reason') for index, channel in enumerate(channels): - d = { 'id': channel.id, 'position': index } + d = {'id': channel.id, 'position': index} if parent_id is not ... and channel.id == self.id: d.update(parent_id=parent_id, lock_permissions=lock_permissions) payload.append(d) await self._state.http.bulk_channel_update(self.guild.id, payload, reason=reason) - async def create_invite(self, *, reason=None, **fields): """|coro| @@ -908,7 +892,8 @@ class GuildChannel: return result -class Messageable(metaclass=abc.ABCMeta): + +class Messageable(Protocol): """An ABC that details the common operations on a model that can send messages. The following implement this ABC: @@ -919,11 +904,16 @@ class Messageable(metaclass=abc.ABCMeta): - :class:`~discord.User` - :class:`~discord.Member` - :class:`~discord.ext.commands.Context` + + + Note + ---- + This ABC is not decorated with :func:`typing.runtime_checkable`, so will fail :func:`isinstance`/:func:`issubclass` + checks. """ __slots__ = () - @abc.abstractmethod async def _get_channel(self): raise NotImplementedError @@ -1060,8 +1050,8 @@ class Messageable(metaclass=abc.ABCMeta): f.close() else: data = await state.http.send_message(channel.id, content, tts=tts, embed=embed, - nonce=nonce, allowed_mentions=allowed_mentions, - message_reference=reference) + nonce=nonce, allowed_mentions=allowed_mentions, + message_reference=reference) ret = state.create_message(channel=channel, data=data) if delete_after is not None: @@ -1213,21 +1203,25 @@ class Messageable(metaclass=abc.ABCMeta): """ return HistoryIterator(self, limit=limit, before=before, after=after, around=around, oldest_first=oldest_first) -class Connectable(metaclass=abc.ABCMeta): + +class Connectable(Protocol): """An ABC that details the common operations on a channel that can connect to a voice server. The following implement this ABC: - :class:`~discord.VoiceChannel` + + Note + ---- + This ABC is not decorated with :func:`typing.runtime_checkable`, so will fail :func:`isinstance`/:func:`issubclass` + checks. """ __slots__ = () - @abc.abstractmethod def _get_voice_client_key(self): raise NotImplementedError - @abc.abstractmethod def _get_voice_state_pair(self): raise NotImplementedError @@ -1286,6 +1280,6 @@ class Connectable(metaclass=abc.ABCMeta): except Exception: # we don't care if disconnect failed because connection failed pass - raise # re-raise + raise # re-raise return voice |