Browse Source

Move ActionRow to its own separate type split from Component

pull/6978/head
Rapptz 4 years ago
parent
commit
8bd17ede47
  1. 85
      discord/components.py
  2. 8
      discord/types/components.py
  3. 8
      docs/api.rst

85
discord/components.py

@ -24,29 +24,75 @@ DEALINGS IN THE SOFTWARE.
from __future__ import annotations from __future__ import annotations
from typing import List, Optional, TYPE_CHECKING, Tuple, Type, TypeVar from typing import Any, ClassVar, Dict, List, Optional, TYPE_CHECKING, Tuple, Type, TypeVar
from .enums import try_enum, ComponentType, ButtonStyle from .enums import try_enum, ComponentType, ButtonStyle
from .utils import get_slots
from .partial_emoji import PartialEmoji from .partial_emoji import PartialEmoji
if TYPE_CHECKING: if TYPE_CHECKING:
from .types.components import ( from .types.components import (
Component as ComponentPayload, Component as ComponentPayload,
ButtonComponent as ButtonComponentPayload, ButtonComponent as ButtonComponentPayload,
ComponentContainer as ComponentContainerPayload, ActionRow as ActionRowPayload,
) )
__all__ = ( __all__ = (
'Component', 'Component',
'ActionRow',
'Button', 'Button',
) )
C = TypeVar('C', bound='Component') C = TypeVar('C', bound='Component')
class Component: class Component:
"""Represents a Discord Bot UI Kit Component. """Represents a Discord Bot UI Kit Component.
Currently, the only components supported by Discord are buttons and button groups. Currently, the only components supported by Discord are:
- :class:`ActionRow`
- :class:`Button`
This class is abstract and cannot be instantiated.
.. versionadded:: 2.0
Attributes
------------
type: :class:`ComponentType`
The type of component.
"""
__slots__: Tuple[str, ...] = ('type',)
__repr_info__: ClassVar[Tuple[str, ...]]
type: ComponentType
def __repr__(self) -> str:
attrs = ' '.join(f'{key}={getattr(self, key)!r}' for key in self.__repr_info__)
return f'<{self.__class__.__name__} type={self.type!r} {attrs}>'
@classmethod
def _raw_construct(cls: Type[C], **kwargs) -> C:
self: C = cls.__new__(cls)
for slot in get_slots(cls):
try:
value = kwargs[slot]
except KeyError:
pass
else:
setattr(self, slot, value)
return self
def to_dict(self) -> Dict[str, Any]:
raise NotImplementedError
class ActionRow(Component):
"""Represents a Discord Bot UI Kit Action Row.
This is a component that holds up to 5 children components in a row.
.. versionadded:: 2.0 .. versionadded:: 2.0
@ -58,36 +104,21 @@ class Component:
The children components that this holds, if any. The children components that this holds, if any.
""" """
__slots__: Tuple[str, ...] = ( __slots__: Tuple[str, ...] = ('children',)
'type',
'children', __repr_info__: ClassVar[Tuple[str, ...]] = __slots__
)
def __init__(self, data: ComponentPayload): def __init__(self, data: ComponentPayload):
self.type: ComponentType = try_enum(ComponentType, data['type']) self.type: ComponentType = try_enum(ComponentType, data['type'])
self.children: List[Component] = [_component_factory(d) for d in data.get('components', [])] self.children: List[Component] = [_component_factory(d) for d in data.get('components', [])]
def __repr__(self) -> str: def to_dict(self) -> ActionRowPayload:
attrs = ' '.join(f'{key}={getattr(self, key)!r}' for key in self.__slots__)
return f'<{self.__class__.__name__} type={self.type!r} {attrs}>'
def to_dict(self) -> ComponentContainerPayload:
return { return {
'type': int(self.type), 'type': int(self.type),
'components': [child.to_dict() for child in self.children], 'components': [child.to_dict() for child in self.children],
} # type: ignore } # type: ignore
@classmethod
def _raw_construct(cls: Type[C], **kwargs) -> C:
self: C = cls.__new__(cls)
slots = cls.__slots__
for attr, value in kwargs.items():
if attr in slots:
setattr(self, attr, value)
return self
class Button(Component): class Button(Component):
"""Represents a button from the Discord Bot UI Kit. """Represents a button from the Discord Bot UI Kit.
@ -112,7 +143,7 @@ class Button(Component):
The emoji of the button, if available. The emoji of the button, if available.
""" """
__slots__: Tuple[str, ...] = Component.__slots__ + ( __slots__: Tuple[str, ...] = (
'style', 'style',
'custom_id', 'custom_id',
'url', 'url',
@ -121,6 +152,8 @@ class Button(Component):
'emoji', 'emoji',
) )
__repr_info__: ClassVar[Tuple[str, ...]] = __slots__
def __init__(self, data: ButtonComponentPayload): def __init__(self, data: ButtonComponentPayload):
self.type: ComponentType = try_enum(ComponentType, data['type']) self.type: ComponentType = try_enum(ComponentType, data['type'])
self.style: ButtonStyle = try_enum(ButtonStyle, data['style']) self.style: ButtonStyle = try_enum(ButtonStyle, data['style'])
@ -152,11 +185,13 @@ class Button(Component):
return payload # type: ignore return payload # type: ignore
def _component_factory(data: ComponentPayload) -> Component: def _component_factory(data: ComponentPayload) -> Component:
component_type = data['type'] component_type = data['type']
if component_type == 1: if component_type == 1:
return Component(data) return ActionRow(data)
elif component_type == 2: elif component_type == 2:
return Button(data) # type: ignore return Button(data) # type: ignore
else: else:
return Component(data) as_enum = try_enum(ComponentType, component_type)
return Component._raw_construct(type=as_enum)

8
discord/types/components.py

@ -24,16 +24,16 @@ DEALINGS IN THE SOFTWARE.
from __future__ import annotations from __future__ import annotations
from typing import Literal, TypedDict, Union from typing import List, Literal, TypedDict, Union
from .emoji import PartialEmoji from .emoji import PartialEmoji
ComponentType = Literal[1, 2] ComponentType = Literal[1, 2]
ButtonStyle = Literal[1, 2, 3, 4, 5] ButtonStyle = Literal[1, 2, 3, 4, 5]
class ComponentContainer(TypedDict): class ActionRow(TypedDict):
type: Literal[1] type: Literal[1]
components: Component components: List[Component]
class _ButtonComponentOptional(TypedDict, total=False): class _ButtonComponentOptional(TypedDict, total=False):
@ -48,4 +48,4 @@ class ButtonComponent(_ButtonComponentOptional):
style: ButtonStyle style: ButtonStyle
Component = Union[ComponentContainer, ButtonComponent] Component = Union[ActionRow, ButtonComponent]

8
docs/api.rst

@ -2885,6 +2885,14 @@ Component
.. autoclass:: Component() .. autoclass:: Component()
:members: :members:
ActionRow
~~~~~~~~~~
.. attributetable:: ActionRow
.. autoclass:: ActionRow()
:members:
Button Button
~~~~~~~ ~~~~~~~

Loading…
Cancel
Save