aboutsummaryrefslogtreecommitdiff
path: root/discord/abc.py
diff options
context:
space:
mode:
authorJames <[email protected]>2021-04-04 23:05:49 +0100
committerGitHub <[email protected]>2021-04-04 18:05:49 -0400
commit34ab772653152d8e448f21cc4ccb9990edafae73 (patch)
treebb46bf3f14be9a672cd37358ad0d6948c6f49cfd /discord/abc.py
parentFlatten AsyncIterator.flatten (diff)
downloaddiscord.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.py112
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