Source code for discord.components.components_holder

from __future__ import annotations

from typing import Generic, cast

from typing_extensions import TypeVarTuple, Unpack, override

from .component import Component, WalkableComponentMixin
from .partial_components import PartialComponent, PartialWalkableComponentMixin
from .type_aliases import AnyComponent, AnyPartialComponent

Ts = TypeVarTuple(
    "Ts", default=Unpack[tuple[AnyComponent | AnyPartialComponent]]
)  # Unforntunately, we cannot use `TypeVarTuple` with upper bounds yet.


[docs] class ComponentsHolder(tuple[Unpack[Ts]], Generic[Unpack[Ts]]): """A sequence of components that can be used in Discord Bot UI Kit. This holder that is used to represent a collection of components, notably in a message. .. versionadded:: 3.0 """ __slots__: tuple[str, ...] = () def __new__(cls, *components: Unpack[Ts]) -> ComponentsHolder[Unpack[Ts]]: return super().__new__(cls, components)
[docs] def get_by_id(self, component_id: str | int) -> AnyComponent | AnyPartialComponent | None: """Get a component by its custom ID.""" for maybe_component in self: if not isinstance(maybe_component, (Component, PartialComponent)): raise TypeError(f"Expected {Component} or {PartialComponent} but got {maybe_component}") component = cast(AnyComponent | AnyPartialComponent, maybe_component) if isinstance(component_id, str) and getattr(component, "custom_id", None) == component_id: return component elif isinstance(component_id, int) and getattr(component, "id", None) == component_id: return component if isinstance(component, (WalkableComponentMixin, PartialWalkableComponentMixin)): if found := component.get_by_id(component_id): return found return None
@override def __repr__(self) -> str: return f"<ComponentsHolder components={super().__repr__()}>"