Skip to content

Commit 3a97585

Browse files
committed
feat: allow list operations on ContainerComponent
Ideally improves UX. Hasn't been tested much.
1 parent cb0ed98 commit 3a97585

File tree

1 file changed

+84
-8
lines changed

1 file changed

+84
-8
lines changed

interactions/models/discord/components.py

Lines changed: 84 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
from collections import UserList
12
import contextlib
23
import uuid
34
from abc import abstractmethod
4-
from typing import Any, Dict, Iterator, List, Optional, Sequence, Union, TYPE_CHECKING
5+
from typing import Any, Dict, Iterator, List, Optional, Sequence, Union, TYPE_CHECKING, overload
6+
from typing_extensions import Self
57

68
import attrs
79
import discord_typings
@@ -1092,7 +1094,12 @@ def to_dict(self) -> dict:
10921094
}
10931095

10941096

1095-
class ContainerComponent(BaseComponent):
1097+
class ContainerComponent(
1098+
BaseComponent,
1099+
UserList[
1100+
ActionRow | SectionComponent | TextDisplayComponent | MediaGalleryComponent | FileComponent | SeparatorComponent
1101+
],
1102+
):
10961103
"""
10971104
A top-level layout component. Containers are visually distinct from surrounding components and have an optional customizable color bar.
10981105
@@ -1103,10 +1110,6 @@ class ContainerComponent(BaseComponent):
11031110
type Union[ComponentType, int]: The type of component, as defined by discord. This cannot be modified.
11041111
11051112
"""
1106-
1107-
components: list[
1108-
ActionRow | SectionComponent | TextDisplayComponent | MediaGalleryComponent | FileComponent | SeparatorComponent
1109-
]
11101113
accent_color: Optional[int] = None
11111114
spoiler: bool = False
11121115

@@ -1121,13 +1124,86 @@ def __init__(
11211124
accent_color: Optional[int] = None,
11221125
spoiler: bool = False,
11231126
):
1124-
self.components = list(components)
1127+
self.data = list(components)
11251128
self.accent_color = accent_color
11261129
self.spoiler = spoiler
11271130
self.type = ComponentType.CONTAINER
11281131

1132+
@property
1133+
def components(
1134+
self,
1135+
) -> list[
1136+
ActionRow | SectionComponent | TextDisplayComponent | MediaGalleryComponent | FileComponent | SeparatorComponent
1137+
]:
1138+
return self.data
1139+
1140+
@components.setter
1141+
def components(
1142+
self,
1143+
value: list[
1144+
ActionRow
1145+
| SectionComponent
1146+
| TextDisplayComponent
1147+
| MediaGalleryComponent
1148+
| FileComponent
1149+
| SeparatorComponent
1150+
],
1151+
) -> None:
1152+
self.data = value
1153+
1154+
@overload
1155+
def __getitem__(
1156+
self, i: int
1157+
) -> (
1158+
ActionRow | SectionComponent | TextDisplayComponent | MediaGalleryComponent | FileComponent | SeparatorComponent
1159+
): ...
1160+
1161+
@overload
1162+
def __getitem__(self, i: slice) -> Self: ...
1163+
1164+
def __getitem__(
1165+
self, i: int | slice
1166+
) -> (
1167+
Self
1168+
| ActionRow
1169+
| SectionComponent
1170+
| TextDisplayComponent
1171+
| MediaGalleryComponent
1172+
| FileComponent
1173+
| SeparatorComponent
1174+
):
1175+
if isinstance(i, slice):
1176+
return self.__class__(*self.data[i], accent_color=self.accent_color, spoiler=self.spoiler)
1177+
return self.data[i]
1178+
1179+
def __add__(self, other: Any) -> Self:
1180+
if isinstance(other, ContainerComponent):
1181+
return self.__class__(*(self.data + other.data), accent_color=self.accent_color, spoiler=self.spoiler)
1182+
if isinstance(other, UserList):
1183+
return self.__class__(*(self.data + other.data), accent_color=self.accent_color, spoiler=self.spoiler)
1184+
if isinstance(other, type(self.data)):
1185+
return self.__class__(*(self.data + other), accent_color=self.accent_color, spoiler=self.spoiler)
1186+
return self.__class__(*(self.data + list(other)), accent_color=self.accent_color, spoiler=self.spoiler)
1187+
1188+
def __radd__(self, other: Any) -> Self:
1189+
if isinstance(other, ContainerComponent):
1190+
return self.__class__(*(self.data + other.data), accent_color=other.accent_color, spoiler=other.spoiler)
1191+
if isinstance(other, UserList):
1192+
return self.__class__(*(other.data + self.data), accent_color=self.accent_color, spoiler=self.spoiler)
1193+
if isinstance(other, type(self.data)):
1194+
return self.__class__(*(other + self.data), accent_color=self.accent_color, spoiler=self.spoiler)
1195+
return self.__class__(*(list(other) + self.data), accent_color=self.accent_color, spoiler=self.spoiler)
1196+
1197+
def __mul__(self, n: int) -> Self:
1198+
return self.__class__(*(self.data * n), accent_color=self.accent_color, spoiler=self.spoiler)
1199+
1200+
__rmul__ = __mul__
1201+
1202+
def copy(self) -> Self:
1203+
return self.__class__(*self.data, accent_color=self.accent_color, spoiler=self.spoiler)
1204+
11291205
@classmethod
1130-
def from_dict(cls, data: dict) -> "ContainerComponent":
1206+
def from_dict(cls, data: dict) -> Self:
11311207
return cls(
11321208
*[BaseComponent.from_dict_factory(component) for component in data["components"]],
11331209
accent_color=data.get("accent_color"),

0 commit comments

Comments
 (0)