Browse Source

chore: fix errors

TextDisplay attribute error when doing TextDisplay.to_component_dict()
View.to_components() appending Item objects instead of Item.to_component_dict()
Changed View.to_components() sorting key
pull/10166/head
DA-344 5 months ago
parent
commit
0a0396889c
  1. 9
      discord/components.py
  2. 2
      discord/types/components.py
  3. 22
      discord/ui/container.py
  4. 38
      discord/ui/section.py
  5. 10
      discord/ui/text_display.py
  6. 38
      discord/ui/view.py

9
discord/components.py

@ -732,17 +732,13 @@ class SectionComponent(Component):
def __init__(self, data: SectionComponentPayload, state: Optional[ConnectionState]) -> None:
self.components: List[SectionComponentType] = []
self.accessory: Component = _component_factory(data['accessory'], state)
for component_data in data['components']:
component = _component_factory(component_data, state)
if component is not None:
self.components.append(component) # type: ignore # should be the correct type here
try:
self.accessory: Optional[Component] = _component_factory(data['accessory']) # type: ignore
except KeyError:
self.accessory = None
@property
def type(self) -> Literal[ComponentType.section]:
return ComponentType.section
@ -751,9 +747,8 @@ class SectionComponent(Component):
payload: SectionComponentPayload = {
'type': self.type.value,
'components': [c.to_dict() for c in self.components],
'accessory': self.accessory.to_dict()
}
if self.accessory:
payload['accessory'] = self.accessory.to_dict()
return payload

2
discord/types/components.py

@ -128,7 +128,7 @@ class SelectMenu(SelectComponent):
class SectionComponent(ComponentBase):
type: Literal[9]
components: List[Union[TextComponent, ButtonComponent]]
accessory: NotRequired[ComponentBase]
accessory: ComponentBase
class TextComponent(ComponentBase):

22
discord/ui/container.py

@ -29,6 +29,7 @@ from .item import Item
from .view import View, _component_to_item
from .dynamic import DynamicItem
from ..enums import ComponentType
from ..utils import MISSING
if TYPE_CHECKING:
from typing_extensions import Self
@ -61,13 +62,20 @@ class Container(View, Item[V]):
timeout: Optional[:class:`float`]
Timeout in seconds from last interaction with the UI before no longer accepting input.
If ``None`` then there is no timeout.
row: Optional[:class:`int`]
The relative row this container belongs to. By default
items are arranged automatically into those rows. If you'd
like to control the relative positioning of the row then
passing an index is advised. For example, row=1 will show
up before row=2. Defaults to ``None``, which is automatic
ordering. The row number must be between 0 and 9 (i.e. zero indexed)
"""
__discord_ui_container__ = True
def __init__(
self,
children: List[Item[Any]],
children: List[Item[Any]] = MISSING,
*,
accent_colour: Optional[Colour] = None,
accent_color: Optional[Color] = None,
@ -76,9 +84,10 @@ class Container(View, Item[V]):
row: Optional[int] = None,
) -> None:
super().__init__(timeout=timeout)
if len(children) + len(self._children) > 10:
raise ValueError('maximum number of components exceeded')
self._children.extend(children)
if children is not MISSING:
if len(children) + len(self._children) > 10:
raise ValueError('maximum number of components exceeded')
self._children.extend(children)
self.spoiler: bool = spoiler
self._colour = accent_colour or accent_color
@ -87,11 +96,6 @@ class Container(View, Item[V]):
self._rendered_row: Optional[int] = None
self.row: Optional[int] = row
def _init_children(self) -> List[Item[Self]]:
if self.__weights.max_weight != 10:
self.__weights.max_weight = 10
return super()._init_children()
@property
def children(self) -> List[Item[Self]]:
"""List[:class:`Item`]: The children of this container."""

38
discord/ui/section.py

@ -28,6 +28,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, TypeVar, U
from .item import Item
from .text_display import TextDisplay
from ..enums import ComponentType
from ..utils import MISSING
if TYPE_CHECKING:
from typing_extensions import Self
@ -37,6 +38,8 @@ if TYPE_CHECKING:
V = TypeVar('V', bound='View', covariant=True)
__all__ = ('Section',)
class Section(Item[V]):
"""Represents a UI section.
@ -47,8 +50,8 @@ class Section(Item[V]):
----------
children: List[Union[:class:`str`, :class:`TextDisplay`]]
The text displays of this section. Up to 3.
accessory: Optional[:class:`Item`]
The section accessory. Defaults to ``None``.
accessory: :class:`Item`
The section accessory.
row: Optional[:class:`int`]
The relative row this section belongs to. By default
items are arranged automatically into those rows. If you'd
@ -65,16 +68,23 @@ class Section(Item[V]):
def __init__(
self,
children: List[Union[Item[Any], str]],
children: List[Union[Item[Any], str]] = MISSING,
*,
accessory: Optional[Item[Any]] = None,
accessory: Item[Any],
row: Optional[int] = None,
) -> None:
super().__init__()
if len(children) > 3:
raise ValueError('maximum number of children exceeded')
self._children: List[Item[Any]] = [c if isinstance(c, Item) else TextDisplay(c) for c in children]
self.accessory: Optional[Item[Any]] = accessory
self._children: List[Item[Any]] = []
if children is not MISSING:
if len(children) > 3:
raise ValueError('maximum number of children exceeded')
self._children.extend(
[
c if isinstance(c, Item)
else TextDisplay(c) for c in children
],
)
self.accessory: Item[Any] = accessory
self.row = row
@ -106,13 +116,14 @@ class Section(Item[V]):
Parameters
----------
item: Union[:class:`str`, :class:`TextDisplay`]
The text display to add.
item: Union[:class:`str`, :class:`Item`]
The items to append, if it is a string it automatically wrapped around
:class:`TextDisplay`.
Raises
------
TypeError
A :class:`TextDisplay` was not passed.
An :class:`Item` or :class:`str` was not passed.
ValueError
Maximum number of children has been exceeded (3).
"""
@ -161,14 +172,13 @@ class Section(Item[V]):
return cls(
children=[_component_to_item(c) for c in component.components],
accessory=_component_to_item(component.accessory) if component.accessory else None,
accessory=_component_to_item(component.accessory),
)
def to_component_dict(self) -> Dict[str, Any]:
data = {
'components': [c.to_component_dict() for c in self._children],
'type': self.type.value,
'accessory': self.accessory.to_component_dict()
}
if self.accessory:
data['accessory'] = self.accessory.to_component_dict()
return data

10
discord/ui/text_display.py

@ -60,14 +60,14 @@ class TextDisplay(Item[V]):
def __init__(self, content: str, *, row: Optional[int] = None) -> None:
super().__init__()
self.content: str = content
self._underlying = TextDisplayComponent._raw_construct(
content=content,
)
self.row = row
def to_component_dict(self):
return self._underlying.to_dict()
return {
'type': self.type.value,
'content': self.content,
}
@property
def width(self):
@ -75,7 +75,7 @@ class TextDisplay(Item[V]):
@property
def type(self) -> Literal[ComponentType.text_display]:
return self._underlying.type
return ComponentType.text_display
def _is_v2(self) -> bool:
return True

38
discord/ui/view.py

@ -23,7 +23,7 @@ DEALINGS IN THE SOFTWARE.
"""
from __future__ import annotations
from typing import Any, Callable, ClassVar, Coroutine, Dict, Iterator, List, Optional, Sequence, TYPE_CHECKING, Tuple, Type
from typing import Any, Callable, ClassVar, Coroutine, Dict, Iterator, List, Optional, Sequence, TYPE_CHECKING, Tuple, Type, Union
from functools import partial
from itertools import groupby
@ -119,13 +119,11 @@ class _ViewWeights:
# fmt: off
__slots__ = (
'weights',
'max_weight',
)
# fmt: on
def __init__(self, children: List[Item]):
self.weights: List[int] = [0, 0, 0, 0, 0]
self.max_weight: int = 5
key = lambda i: sys.maxsize if i.row is None else i.row
children = sorted(children, key=key)
@ -146,8 +144,8 @@ class _ViewWeights:
self.weights.extend([0, 0, 0, 0, 0])
if item.row is not None:
total = self.weights[item.row] + item.width
if total > self.max_weight:
raise ValueError(f'item would not fit at row {item.row} ({total} > {self.max_weight} width)')
if total > 5:
raise ValueError(f'item would not fit at row {item.row} ({total} > 5 width)')
self.weights[item.row] = total
item._rendered_row = item.row
else:
@ -196,15 +194,15 @@ class View:
__discord_ui_view__: ClassVar[bool] = True
__discord_ui_modal__: ClassVar[bool] = False
__discord_ui_container__: ClassVar[bool] = False
__view_children_items__: ClassVar[List[ItemCallbackType[Any, Any]]] = []
__view_children_items__: ClassVar[List[Union[ItemCallbackType[Any, Any], Item[Any]]]] = []
def __init_subclass__(cls) -> None:
super().__init_subclass__()
children: Dict[str, ItemCallbackType[Any, Any]] = {}
children: Dict[str, Union[ItemCallbackType[Any, Any], Item]] = {}
for base in reversed(cls.__mro__):
for name, member in base.__dict__.items():
if hasattr(member, '__discord_ui_model_type__'):
if hasattr(member, '__discord_ui_model_type__') or isinstance(member, Item):
children[name] = member
if len(children) > 25:
@ -214,12 +212,16 @@ class View:
def _init_children(self) -> List[Item[Self]]:
children = []
for func in self.__view_children_items__:
item: Item = func.__discord_ui_model_type__(**func.__discord_ui_model_kwargs__)
item.callback = _ViewCallback(func, self, item) # type: ignore
item._view = self
setattr(self, func.__name__, item)
children.append(item)
if isinstance(func, Item):
children.append(func)
else:
item: Item = func.__discord_ui_model_type__(**func.__discord_ui_model_kwargs__)
item.callback = _ViewCallback(func, self, item) # type: ignore
item._view = self
setattr(self, func.__name__, item)
children.append(item)
return children
def __init__(self, *, timeout: Optional[float] = 180.0):
@ -275,7 +277,13 @@ class View:
# v2 components
def key(item: Item) -> int:
return item._rendered_row or 0
if item._rendered_row is not None:
return item._rendered_row
try:
return self._children.index(item)
except ValueError:
return 0
# instead of grouping by row we will sort it so it is added
# in order and should work as the original implementation
@ -290,7 +298,7 @@ class View:
index = rows_index.get(row)
if index is not None:
components[index]['components'].append(child)
components[index]['components'].append(child.to_component_dict())
else:
components.append(
{

Loading…
Cancel
Save