Browse Source

Typehint Role and RoleTags

pull/6985/head
Rapptz 4 years ago
parent
commit
c475218112
  1. 107
      discord/role.py

107
discord/role.py

@ -22,19 +22,30 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
"""
from typing import Optional, Union, overload
from __future__ import annotations
from typing import Any, List, Optional, TypeVar, Union, overload, TYPE_CHECKING
from .permissions import Permissions
from .errors import InvalidArgument
from .colour import Colour
from .mixins import Hashable
from .utils import snowflake_time, _get_as_snowflake
from .utils import snowflake_time, _get_as_snowflake, MISSING
__all__ = (
'RoleTags',
'Role',
)
if TYPE_CHECKING:
import datetime
from .types.role import (
Role as RolePayload,
RoleTags as RoleTagPayload,
)
from .guild import Guild
from .member import Member
from .state import ConnectionState
class RoleTags:
"""Represents tags on a role.
@ -61,34 +72,37 @@ class RoleTags:
'_premium_subscriber',
)
def __init__(self, data):
self.bot_id = _get_as_snowflake(data, 'bot_id')
self.integration_id = _get_as_snowflake(data, 'integration_id')
def __init__(self, data: RoleTagPayload):
self.bot_id: Optional[int] = _get_as_snowflake(data, 'bot_id')
self.integration_id: Optional[int] = _get_as_snowflake(data, 'integration_id')
# NOTE: The API returns "null" for this if it's valid, which corresponds to None.
# This is different from other fields where "null" means "not there".
# So in this case, a value of None is the same as True.
# Which means we would need a different sentinel. For this purpose I used ellipsis.
self._premium_subscriber = data.get('premium_subscriber', ...)
# Which means we would need a different sentinel.
self._premium_subscriber: Optional[Any] = data.get('premium_subscriber', MISSING)
def is_bot_managed(self):
def is_bot_managed(self) -> bool:
""":class:`bool`: Whether the role is associated with a bot."""
return self.bot_id is not None
def is_premium_subscriber(self):
def is_premium_subscriber(self) -> bool:
""":class:`bool`: Whether the role is the premium subscriber, AKA "boost", role for the guild."""
return self._premium_subscriber is None
def is_integration(self):
def is_integration(self) -> bool:
""":class:`bool`: Whether the role is managed by an integration."""
return self.integration_id is not None
def __repr__(self):
def __repr__(self) -> str:
return (
f'<RoleTags bot_id={self.bot_id} integration_id={self.integration_id} '
f'premium_subscriber={self.is_premium_subscriber()}>'
)
R = TypeVar('R', bound='Role')
class Role(Hashable):
"""Represents a Discord role in a :class:`Guild`.
@ -171,19 +185,19 @@ class Role(Hashable):
'_state',
)
def __init__(self, *, guild, state, data):
self.guild = guild
self._state = state
self.id = int(data['id'])
def __init__(self, *, guild: Guild, state: ConnectionState, data: RolePayload):
self.guild: Guild = guild
self._state: ConnectionState = state
self.id: int = int(data['id'])
self._update(data)
def __str__(self):
def __str__(self) -> str:
return self.name
def __repr__(self):
def __repr__(self) -> str:
return f'<Role id={self.id} name={self.name!r}>'
def __lt__(self, other):
def __lt__(self: R, other: R) -> bool:
if not isinstance(other, Role) or not isinstance(self, Role):
return NotImplemented
@ -204,99 +218,96 @@ class Role(Hashable):
return False
def __le__(self, other):
def __le__(self: R, other: R) -> bool:
r = Role.__lt__(other, self)
if r is NotImplemented:
return NotImplemented
return not r
def __gt__(self, other):
def __gt__(self: R, other: R) -> bool:
return Role.__lt__(other, self)
def __ge__(self, other):
def __ge__(self: R, other: R) -> bool:
r = Role.__lt__(self, other)
if r is NotImplemented:
return NotImplemented
return not r
def _update(self, data):
self.name = data['name']
self._permissions = int(data.get('permissions', 0))
self.position = data.get('position', 0)
self._colour = data.get('color', 0)
self.hoist = data.get('hoist', False)
self.managed = data.get('managed', False)
self.mentionable = data.get('mentionable', False)
def _update(self, data: RolePayload):
self.name: str = data['name']
self._permissions: int = int(data.get('permissions', 0))
self.position: int = data.get('position', 0)
self._colour: int = data.get('color', 0)
self.hoist: bool = data.get('hoist', False)
self.managed: bool = data.get('managed', False)
self.mentionable: bool = data.get('mentionable', False)
self.tags: Optional[RoleTags]
try:
self.tags = RoleTags(data['tags'])
except KeyError:
self.tags = None
def is_default(self):
def is_default(self) -> bool:
""":class:`bool`: Checks if the role is the default role."""
return self.guild.id == self.id
def is_bot_managed(self):
def is_bot_managed(self) -> bool:
""":class:`bool`: Whether the role is associated with a bot.
.. versionadded:: 1.6
"""
return self.tags is not None and self.tags.is_bot_managed()
def is_premium_subscriber(self):
def is_premium_subscriber(self) -> bool:
""":class:`bool`: Whether the role is the premium subscriber, AKA "boost", role for the guild.
.. versionadded:: 1.6
"""
return self.tags is not None and self.tags.is_premium_subscriber()
def is_integration(self):
def is_integration(self) -> bool:
""":class:`bool`: Whether the role is managed by an integration.
.. versionadded:: 1.6
"""
return self.tags is not None and self.tags.is_integration()
def is_assignable(self):
def is_assignable(self) -> bool:
""":class:`bool`: Whether the role is able to be assigned or removed by the bot.
.. versionadded:: 2.0
"""
me = self.guild.me
return (
not self.is_default()
and not self.managed
and (me.top_role > self or me.id == self.guild.owner_id)
)
return not self.is_default() and not self.managed and (me.top_role > self or me.id == self.guild.owner_id)
@property
def permissions(self):
def permissions(self) -> Permissions:
""":class:`Permissions`: Returns the role's permissions."""
return Permissions(self._permissions)
@property
def colour(self):
def colour(self) -> Colour:
""":class:`Colour`: Returns the role colour. An alias exists under ``color``."""
return Colour(self._colour)
@property
def color(self):
def color(self) -> Colour:
""":class:`Colour`: Returns the role color. An alias exists under ``colour``."""
return self.colour
@property
def created_at(self):
def created_at(self) -> datetime.datetime:
""":class:`datetime.datetime`: Returns the role's creation time in UTC."""
return snowflake_time(self.id)
@property
def mention(self):
def mention(self) -> str:
""":class:`str`: Returns a string that allows you to mention a role."""
return f'<@&{self.id}>'
@property
def members(self):
def members(self) -> List[Member]:
"""List[:class:`Member`]: Returns all the members with this role."""
all_members = self.guild.members
if self.is_default():
@ -305,7 +316,7 @@ class Role(Hashable):
role_id = self.id
return [member for member in all_members if member._roles.has(role_id)]
async def _move(self, position, reason):
async def _move(self, position: int, reason: Optional[str]) -> None:
if position <= 0:
raise InvalidArgument("Cannot move role to position 0 or below")
@ -346,7 +357,7 @@ class Role(Hashable):
async def edit(self) -> None:
...
async def edit(self, *, reason=None, **fields):
async def edit(self, *, reason=None, **fields) -> None:
"""|coro|
Edits the role.
@ -412,7 +423,7 @@ class Role(Hashable):
data = await self._state.http.edit_role(self.guild.id, self.id, reason=reason, **payload)
self._update(data)
async def delete(self, *, reason: Optional[str] = None):
async def delete(self, *, reason: Optional[str] = None) -> None:
"""|coro|
Deletes the role.

Loading…
Cancel
Save