Skip to content

Commit fe68835

Browse files
committed
♻️ WalkableComponent -> WalkableComponentMixin
1 parent 7cca107 commit fe68835

File tree

7 files changed

+53
-30
lines changed

7 files changed

+53
-30
lines changed

discord/components/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from .action_row import ActionRow
2727
from .button import Button
2828
from .channel_select_menu import ChannelSelect
29-
from .component import Component, ModalComponentMixin, StateComponentMixin, WalkableComponent
29+
from .component import Component, ModalComponentMixin, StateComponentMixin, WalkableComponentMixin
3030
from .components_holder import ComponentsHolder
3131
from .container import Container
3232
from .default_select_option import DefaultSelectOption
@@ -80,7 +80,7 @@
8080
__all__ = (
8181
"Component",
8282
"StateComponentMixin",
83-
"WalkableComponent",
83+
"WalkableComponentMixin",
8484
"ModalComponentMixin",
8585
"ComponentsHolder",
8686
"ActionRow",

discord/components/action_row.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525

2626
from __future__ import annotations
2727

28-
from typing import TYPE_CHECKING, ClassVar, Literal, TypeAlias, cast
28+
from typing import TYPE_CHECKING, ClassVar, Iterator, Literal, TypeAlias, cast
2929

3030
from typing_extensions import override
3131

3232
from ..enums import ComponentType
3333
from ..types.component_types import ActionRow as ActionRowPayload
34-
from .component import WalkableComponent
34+
from .component import Component, WalkableComponentMixin
35+
from .types import C
3536

3637
if TYPE_CHECKING:
3738
from typing_extensions import Self
@@ -49,7 +50,7 @@
4950
)
5051

5152

52-
class ActionRow(WalkableComponent["ActionRowPayload", "AllowedActionRowComponents"]):
53+
class ActionRow(Component["ActionRowPayload"], WalkableComponentMixin["AllowedActionRowComponents"]):
5354
"""Represents a Discord Bot UI Kit Action Row.
5455
5556
This is a component that holds up to 5 children components in a row.
@@ -90,6 +91,10 @@ def __init__(self, *components: AllowedActionRowComponents, id: int | None = Non
9091
self.components: list[AllowedActionRowComponents] = list(components)
9192
super().__init__(id=id)
9293

94+
@override
95+
def walk_components(self) -> Iterator[AllowedActionRowComponents]:
96+
yield from self.components
97+
9398
@classmethod
9499
@override
95100
def from_payload(cls, payload: ActionRowPayload) -> Self:

discord/components/component.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -109,43 +109,53 @@ def from_payload(cls, payload: P, state: ConnectionState | None = None) -> Self:
109109
...
110110

111111

112-
class WalkableComponent(Component[P], ABC, Generic[P, C]):
112+
class WalkableComponentMixin(ABC, Generic[C]):
113113
"""A component that can be walked through.
114114
115115
This is an abstract class and cannot be instantiated directly.
116116
It is used to represent components that can be walked through, such as :class:`ActionRow`, :class:`Container` and :class:`Section`.
117117
"""
118118

119-
__slots__: tuple[str, ...] = ("components",) # pyright: ignore[reportIncompatibleUnannotatedOverride]
120-
components: list[C]
121-
122-
def walk_components(self) -> Iterator[C]:
123-
"""Walks through the components in this component."""
124-
for component in self.components:
125-
if isinstance(component, WalkableComponent):
126-
yield from component.walk_components()
127-
else:
128-
yield component
119+
@abstractmethod
120+
def walk_components(self) -> Iterator[C]: ...
129121

130122
__iter__: Callable[[Self], Iterator[C]] = walk_components
131123

132-
@override
124+
@abstractmethod
125+
def is_v2(self) -> bool: ...
126+
127+
@abstractmethod
128+
def is_dispatchable(self) -> bool: ...
129+
133130
def any_is_v2(self) -> bool:
134131
"""Whether this component or any of its children were introduced in Components V2."""
135132
return self.is_v2() or any(c.any_is_v2() for c in self.walk_components())
136133

137-
@override
138134
def any_is_dispatchable(self) -> bool:
139135
"""Whether this component or any of its children can be interacted with and lead to a :class:`Interaction`"""
140136
return self.is_dispatchable() or any(c.any_is_dispatchable() for c in self.walk_components())
141137

142138
def get_by_id(self, component_id: str | int) -> C | None:
139+
"""Gets a component by its ID or custom ID.
140+
141+
Parameters
142+
----------
143+
component_id:
144+
The ID (int) or custom ID (str) of the component to get.
145+
146+
Returns
147+
-------
148+
:class:`AllowedComponents` | :class:`None`
149+
The children component with the given ID or custom ID, or :data:`None` if not found.
150+
"""
143151
for component in self.walk_components():
144152
if isinstance(component_id, str) and getattr(component, "custom_id", None) == component_id:
145153
return component
146154
elif isinstance(component_id, int) and getattr(component, "id", None) == component_id:
147155
return component
148156

157+
return None
158+
149159

150160
class ModalComponentMixin(ABC, Generic[P]):
151161
"""A component that can be used in a modal.

discord/components/container.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,15 @@
2424

2525
from __future__ import annotations
2626

27-
from typing import TYPE_CHECKING, ClassVar, Literal, TypeAlias, cast
27+
from typing import TYPE_CHECKING, ClassVar, Iterator, Literal, TypeAlias, cast
2828

2929
from typing_extensions import override
3030

3131
from ..colour import Colour
3232
from ..enums import ComponentType
3333
from ..types.component_types import ContainerComponent as ContainerComponentPayload
34-
from .component import WalkableComponent
34+
from .component import Component, WalkableComponentMixin
35+
from .types import C
3536

3637
if TYPE_CHECKING:
3738
from typing_extensions import Self
@@ -48,7 +49,7 @@
4849
AllowedContainerComponents: TypeAlias = "ActionRow | TextDisplay | Section | MediaGallery | Separator | FileComponent"
4950

5051

51-
class Container(WalkableComponent["ContainerComponentPayload", "AllowedContainerComponents"]):
52+
class Container(Component["ContainerComponentPayload"], WalkableComponentMixin["AllowedContainerComponents"]):
5253
"""Represents a Container from Components V2.
5354
5455
This is a component that contains different :class:`Component` objects.
@@ -114,6 +115,10 @@ def __init__(
114115
self.components: list[AllowedContainerComponents] = list(components)
115116
super().__init__(id=id)
116117

118+
@override
119+
def walk_components(self) -> Iterator[AllowedContainerComponents]:
120+
yield from self.components
121+
117122
@override
118123
def to_dict(self) -> ContainerComponentPayload:
119124
payload: ContainerComponentPayload = {

discord/components/label.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
from ..enums import ComponentType
3434
from ..types.component_types import LabelComponent as LabelComponentPayload
35-
from .component import ModalComponentMixin, WalkableComponent
35+
from .component import Component, ModalComponentMixin, WalkableComponentMixin
3636

3737
if TYPE_CHECKING:
3838
from typing_extensions import Self
@@ -48,7 +48,9 @@
4848

4949

5050
class Label(
51-
WalkableComponent["LabelComponentPayload", "AllowedLabelComponents"], ModalComponentMixin["LabelComponentPayload"]
51+
Component["LabelComponentPayload"],
52+
WalkableComponentMixin["AllowedLabelComponents"],
53+
ModalComponentMixin["LabelComponentPayload"],
5254
):
5355
"""Represents a Label component.
5456
@@ -97,7 +99,6 @@ def __init__(
9799
description: str | None = None,
98100
id: int | None = None,
99101
):
100-
self.components: list = [] # pyright: ignore[reportMissingTypeArgument]
101102
self.label: str = label
102103
self.description: str | None = description
103104
self.component: AllowedLabelComponents = component

discord/components/partial_components.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def from_payload(cls, payload: P) -> Self: ...
7878
C = TypeVar("C", bound="AnyPartialComponent", covariant=True)
7979

8080

81-
class PartialWalkableComponent(PartialComponent[T, P], ABC, Generic[T, P, C]):
81+
class PartialWalkableComponentMixin(ABC, Generic[C]):
8282
@abstractmethod
8383
def walk_components(self) -> Iterator[C]: ...
8484

@@ -313,7 +313,8 @@ def from_payload(cls, payload: PartialTextInputPayload) -> Self:
313313

314314
@dataclass
315315
class PartialLabel(
316-
PartialWalkableComponent[Literal[ComponentType.label], PartialLabelPayload, AllowedPartialLabelComponents],
316+
PartialComponent[Literal[ComponentType.label], PartialLabelPayload],
317+
PartialWalkableComponentMixin[AllowedPartialLabelComponents],
317318
Generic[L_c],
318319
):
319320
"""Represents a :class:`Label` component as returned by Discord during a :class:`Interaction` of type :data:`InteractionType.modal_submit`.
@@ -347,7 +348,7 @@ def from_payload(cls, payload: PartialLabelPayload) -> Self:
347348
@override
348349
def walk_components(self) -> Iterator[AllowedPartialLabelComponents]:
349350
yield self.component
350-
if isinstance(self.component, PartialWalkableComponent):
351+
if isinstance(self.component, PartialWalkableComponentMixin):
351352
yield from self.component.walk_components() # pyright: ignore[reportReturnType]
352353

353354

discord/components/section.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
from ..enums import ComponentType
3434
from ..types.component_types import SectionComponent as SectionComponentPayload
35-
from .component import WalkableComponent
35+
from .component import Component, WalkableComponentMixin
3636

3737
if TYPE_CHECKING:
3838
from typing_extensions import Self
@@ -48,7 +48,8 @@
4848

4949

5050
class Section(
51-
WalkableComponent["SectionComponentPayload", "AllowedSectionComponents | AllowedSectionAccessoryComponents"],
51+
Component["SectionComponentPayload"],
52+
WalkableComponentMixin["AllowedSectionComponents | AllowedSectionAccessoryComponents"],
5253
):
5354
"""Represents a Section from Components V2.
5455
@@ -128,6 +129,6 @@ def to_dict(self) -> SectionComponentPayload:
128129

129130
@override
130131
def walk_components(self) -> Iterator[AllowedSectionComponents | AllowedSectionAccessoryComponents]:
131-
yield from super().walk_components()
132+
yield from self.components
132133
if self.accessory:
133134
yield self.accessory

0 commit comments

Comments
 (0)