Allow a single builder with `components=`
Closed this issue · 2 comments
Summary
Allow users to pass a custom class that is built into a list of action row payloads. This should help with abstracting some custom component handlers.
Why is this needed?
There have been a few new component handlers recently. Generally, users are forced to use components as follows:
handler = library.SomeHandler(...)
await channel.send(components=handler.build())
It'd be ideal if the .build()
could be abstracted away with:
handler = library.SomeHandler(...)
await channel.send(components=handler)
Ideal implementations
new builder protocol/abc
components
will allow Sequence[ComponentBuilder] | CoolComponentHandlerNameIsWIP
await channel.send(components=handler)
allow pre-existing ComponentBuilder
to return lists
If ComponentBuilder
returns a sequence it will be assumed to be a list of action row payloads.
await channel.send(component=handler)
Checklist
- I have searched the issue tracker and have made sure it's not a duplicate. If it is a follow up of another issue, I have specified it.
I dont think this will be implemented, mostly because the solution to remove the .build()
is quite simple. All you need is to make your handler = library.SomeHandler(...)
a sequence, as specified in the typehint. This would look something like this:
class SomeComponent:
def to_builder() -> ComponentBuilder:
return ComponentBuilder(...)
class SomeHandler(typing.Sequence[ComponentBuilder]):
_custom_components: typing.List[SomeComponent]
def __len__(self) -> int:
return len(self._custom_components)
@typing.overload
def __getitem__(self, index: int) -> ComponentBuilder:
...
@typing.overload
def __getitem__(self, index: slice) -> typing.Sequence[ComponentBuilder]:
...
def __getitem__(
self, index: typing.Union[int, slice]
) -> typing.Union[ComponentBuilder, typing.Sequence[ComponentBuilder]]:
if isinstance(index, int):
return self._custom_components[index].to_builder()
return [component.to_builder() for component in self._custom_components[index]]
def __iter__(self) -> typing.Iterator[ComponentBuilder]:
# This is not necessary, but a worthwhile optimization
yield from (component.to_builder() for component in self._custom_components)
and that can be safely passed into the components
argument.
Because of this, will be closing this issue. Feel free to comment to it or open a new one if you have any comments :)
Ye, outdated. Would still be cool to allow for just an iterable though.