Browse Source

Use descriptor protocol to obtain attribute name instead of a dict

pull/7611/head
Rapptz 3 years ago
parent
commit
0d126c594c
  1. 46
      discord/app_commands/commands.py

46
discord/app_commands/commands.py

@ -37,6 +37,7 @@ from typing import (
Set,
TYPE_CHECKING,
Tuple,
Type,
TypeVar,
Union,
)
@ -325,12 +326,16 @@ class Command(Generic[GroupT, P, T]):
):
self.name: str = name
self.description: str = description
self._attr: Optional[str] = None
self._callback: CommandCallback[GroupT, P, T] = callback
self.parent: Optional[Group] = parent
self.binding: Optional[GroupT] = None
self.on_error: Optional[Error[GroupT]] = None
self._params: Dict[str, CommandParameter] = _extract_parameters_from_callback(callback, callback.__globals__)
def __set_name__(self, owner: Type[Any], name: str) -> None:
self._attr = name
@property
def callback(self) -> CommandCallback[GroupT, P, T]:
""":ref:`coroutine <coroutine>`: The coroutine that is executed when the command is called."""
@ -341,6 +346,7 @@ class Command(Generic[GroupT, P, T]):
copy = cls.__new__(cls)
copy.name = self.name
copy.description = self.description
copy._attr = self._attr
copy._callback = self._callback
copy.parent = self.parent
copy.on_error = self.on_error
@ -621,23 +627,27 @@ class Group:
The parent group. ``None`` if there isn't one.
"""
__discord_app_commands_group_children__: ClassVar[Dict[str, Union[Command, Group]]] = {}
__discord_app_commands_group_children__: ClassVar[List[Union[Command, Group]]] = []
__discord_app_commands_default_guilds__: List[int]
__discord_app_commands_group_name__: str = MISSING
__discord_app_commands_group_description__: str = MISSING
def __init_subclass__(cls, *, name: str = MISSING, description: str = MISSING) -> None:
cls.__discord_app_commands_group_children__ = children = {
name: member
for name, member in cls.__dict__.items()
if isinstance(member, (Group, Command)) and member.parent is None
}
found = set()
for child in children.values():
if child.name in found:
raise TypeError(f'Command {child.name!r} is a duplicate')
found.add(child.name)
if not cls.__discord_app_commands_group_children__:
cls.__discord_app_commands_group_children__ = children = [
member
for name, member in cls.__dict__.items()
if isinstance(member, (Group, Command)) and member.parent is None
]
found = set()
for child in children:
if child.name in found:
raise TypeError(f'Command {child.name!r} is a duplicate')
found.add(child.name)
if len(children) > 25:
raise TypeError('groups cannot have more than 25 commands')
if name is MISSING:
cls.__discord_app_commands_group_name__ = _to_kebab_case(cls.__name__)
@ -652,8 +662,6 @@ class Group:
else:
cls.__discord_app_commands_group_description__ = description
if len(children) > 25:
raise TypeError('groups cannot have more than 25 commands')
def __init__(
self,
@ -665,6 +673,7 @@ class Group:
cls = self.__class__
self.name: str = name if name is not MISSING else cls.__discord_app_commands_group_name__
self.description: str = description or cls.__discord_app_commands_group_description__
self._attr: Optional[str] = None
if not self.description:
raise TypeError('groups must have a description')
@ -673,21 +682,26 @@ class Group:
self._children: Dict[str, Union[Command, Group]] = {}
for attr, child in self.__discord_app_commands_group_children__.items():
for child in self.__discord_app_commands_group_children__:
child = child._copy_with_binding(self)
child.parent = self
self._children[child.name] = child
setattr(self, attr, child)
if child._attr:
setattr(self, child._attr, child)
if parent is not None and parent.parent is not None:
raise ValueError('groups can only be nested at most one level')
def __set_name__(self, owner: Type[Any], name: str) -> None:
self._attr = name
def _copy_with_binding(self, binding: Group) -> Group:
cls = self.__class__
copy = cls.__new__(cls)
copy.name = self.name
copy.description = self.description
copy.parent = self.parent
copy._attr = self._attr
copy._children = {child.name: child._copy_with_binding(binding) for child in self._children.values()}
return copy

Loading…
Cancel
Save