Browse Source

changes to every item, mostly on repr

pull/10166/head
DA-344 2 months ago
parent
commit
ff55d37166
  1. 11
      discord/ui/action_row.py
  2. 4
      discord/ui/button.py
  3. 24
      discord/ui/container.py
  4. 3
      discord/ui/dynamic.py
  5. 7
      discord/ui/file.py
  6. 9
      discord/ui/item.py
  7. 9
      discord/ui/media_gallery.py
  8. 8
      discord/ui/section.py
  9. 4
      discord/ui/select.py
  10. 7
      discord/ui/separator.py
  11. 1
      discord/ui/text_input.py
  12. 8
      discord/ui/thumbnail.py

11
discord/ui/action_row.py

@ -143,6 +143,10 @@ class ActionRow(Item[V]):
__action_row_children_items__: ClassVar[List[ItemCallbackType[Any]]] = []
__discord_ui_action_row__: ClassVar[bool] = True
__discord_ui_update_view__: ClassVar[bool] = True
__item_repr_attributes__ = (
'row',
'id',
)
def __init__(
self,
@ -176,6 +180,9 @@ class ActionRow(Item[V]):
cls.__action_row_children_items__ = list(children.values())
def __repr__(self) -> str:
return f'{super().__repr__()[:-1]} children={len(self._children)}>'
def _init_children(self) -> List[Item[Any]]:
children = []
@ -303,7 +310,7 @@ class ActionRow(Item[V]):
return self
def get_item_by_id(self, id: int, /) -> Optional[Item[V]]:
def get_item(self, id: int, /) -> Optional[Item[V]]:
"""Gets an item with :attr:`Item.id` set as ``id``, or ``None`` if
not found.
@ -321,7 +328,7 @@ class ActionRow(Item[V]):
Optional[:class:`Item`]
The item found, or ``None``.
"""
return _utils_get(self._children, id=id)
return _utils_get(self.walk_children(), id=id)
def clear_items(self) -> Self:
"""Removes all items from the row.

4
discord/ui/button.py

@ -97,6 +97,7 @@ class Button(Item[V]):
'emoji',
'row',
'sku_id',
'id',
)
def __init__(
@ -269,6 +270,9 @@ class Button(Item[V]):
return self.url is not None
return super().is_persistent()
def _can_be_dynamic(self) -> bool:
return True
def _refresh_component(self, button: ButtonComponent) -> None:
self._underlying = button

24
discord/ui/container.py

@ -132,6 +132,12 @@ class Container(Item[V]):
__container_children_items__: ClassVar[Dict[str, Union[ItemCallbackType[Any], Item[Any]]]] = {}
__discord_ui_update_view__: ClassVar[bool] = True
__discord_ui_container__: ClassVar[bool] = True
__item_repr_attributes__ = (
'accent_colour',
'spoiler',
'row',
'id',
)
def __init__(
self,
@ -156,6 +162,9 @@ class Container(Item[V]):
self.row = row
self.id = id
def __repr__(self) -> str:
return f'<{super().__repr__()[:-1]} children={len(self._children)}>'
def _add_dispatchable(self, item: Item[Any]) -> None:
self.__dispatchable.append(item)
@ -173,14 +182,13 @@ class Container(Item[V]):
if isinstance(raw, Item):
item = copy.deepcopy(raw)
item._parent = self
if getattr(item, '__discord_ui_action_row__', False):
if getattr(item, '__discord_ui_action_row__', False) and item.is_dispatchable():
if item.is_dispatchable():
self.__dispatchable.extend(item._children) # type: ignore
if getattr(item, '__discord_ui_section__', False):
if item.accessory.is_dispatchable(): # type: ignore
if item.accessory._provided_custom_id is False: # type: ignore
item.accessory.custom_id = os.urandom(16).hex() # type: ignore
self.__dispatchable.append(item.accessory) # type: ignore
if getattr(item, '__discord_ui_section__', False) and item.accessory.is_dispatchable(): # type: ignore
if item.accessory._provided_custom_id is False: # type: ignore
item.accessory.custom_id = os.urandom(16).hex() # type: ignore
self.__dispatchable.append(item.accessory) # type: ignore
setattr(self, name, item)
children.append(item)
@ -415,7 +423,7 @@ class Container(Item[V]):
self._view._total_children -= 1
return self
def get_item_by_id(self, id: int, /) -> Optional[Item[V]]:
def get_item(self, id: int, /) -> Optional[Item[V]]:
"""Gets an item with :attr:`Item.id` set as ``id``, or ``None`` if
not found.
@ -433,7 +441,7 @@ class Container(Item[V]):
Optional[:class:`Item`]
The item found, or ``None``.
"""
return _utils_get(self._children, id=id)
return _utils_get(self.walk_children(), id=id)
def clear_items(self) -> Self:
"""Removes all the items from the container.

3
discord/ui/dynamic.py

@ -107,6 +107,9 @@ class DynamicItem(Generic[BaseT], Item[Union[View, LayoutView]]):
if not self.item.is_dispatchable():
raise TypeError('item must be dispatchable, e.g. not a URL button')
if not self.item._can_be_dynamic():
raise TypeError(f'{self.item.__class__.__name__} cannot be set as a dynamic item')
if not self.template.match(self.custom_id):
raise ValueError(f'item custom_id {self.custom_id!r} must match the template {self.template.pattern!r}')

7
discord/ui/file.py

@ -77,6 +77,13 @@ class File(Item[V]):
The ID of this component. This must be unique across the view.
"""
__item_repr_attributes__ = (
'media',
'spoiler',
'row',
'id',
)
def __init__(
self,
media: Union[str, UnfurledMediaItem],

9
discord/ui/item.py

@ -66,7 +66,7 @@ class Item(Generic[V]):
.. versionadded:: 2.0
"""
__item_repr_attributes__: Tuple[str, ...] = ('row',)
__item_repr_attributes__: Tuple[str, ...] = ('row', 'id')
def __init__(self):
self._view: Optional[V] = None
@ -162,6 +162,13 @@ class Item(Generic[V]):
return can_run
def _can_be_dynamic(self) -> bool:
# if an item can be dynamic then it must override this, this is mainly used
# by DynamicItem's so a user cannot set, for example, a Container with a dispatchable
# button as a dynamic item, and cause errors where Container can't be dispatched
# or lost interactions
return False
async def callback(self, interaction: Interaction[ClientT]) -> Any:
"""|coro|

9
discord/ui/media_gallery.py

@ -67,6 +67,12 @@ class MediaGallery(Item[V]):
The ID of this component. This must be unique across the view.
"""
__item_repr_attributes__ = (
'items',
'row',
'id',
)
def __init__(
self,
*items: MediaGalleryItem,
@ -83,6 +89,9 @@ class MediaGallery(Item[V]):
self.row = row
self.id = id
def __repr__(self) -> str:
return f'<{super().__repr__()[:-1]} items={len(self._underlying.items)}>'
@property
def items(self) -> List[MediaGalleryItem]:
"""List[:class:`.MediaGalleryItem`]: Returns a read-only list of this gallery's items."""

8
discord/ui/section.py

@ -67,6 +67,11 @@ class Section(Item[V]):
The ID of this component. This must be unique across the view.
"""
__item_repr_attributes__ = (
'accessory',
'row',
'id',
)
__discord_ui_section__: ClassVar[bool] = True
__discord_ui_update_view__: ClassVar[bool] = True
@ -94,6 +99,9 @@ class Section(Item[V]):
self.row = row
self.id = id
def __repr__(self) -> str:
return f'<{super().__repr__()[:-1]} children={len(self._children)}'
@property
def type(self) -> Literal[ComponentType.section]:
return ComponentType.section

4
discord/ui/select.py

@ -217,6 +217,7 @@ class BaseSelect(Item[V]):
'min_values',
'max_values',
'disabled',
'id',
)
__component_attributes__: Tuple[str, ...] = (
'custom_id',
@ -363,6 +364,9 @@ class BaseSelect(Item[V]):
kwrgs = {key: getattr(component, key) for key in constructor.__component_attributes__}
return constructor(**kwrgs)
def _can_be_dynamic(self) -> bool:
return True
class Select(BaseSelect[V]):
"""Represents a UI select menu with a list of custom options. This is represented

7
discord/ui/separator.py

@ -64,6 +64,13 @@ class Separator(Item[V]):
The ID of this component. This must be unique across the view.
"""
__item_repr_attributes__ = (
'visible',
'spacing',
'row',
'id',
)
def __init__(
self,
*,

1
discord/ui/text_input.py

@ -102,6 +102,7 @@ class TextInput(Item[V]):
'label',
'placeholder',
'required',
'id',
)
def __init__(

8
discord/ui/thumbnail.py

@ -66,6 +66,14 @@ class Thumbnail(Item[V]):
The ID of this component. This must be unique across the view.
"""
__item_repr_attributes__ = (
'media',
'description',
'spoiler',
'row',
'id',
)
def __init__(
self,
media: Union[str, UnfurledMediaItem],

Loading…
Cancel
Save