mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-06-07 20:28:38 +00:00
Implement app_commands.rename decorator
This commit is contained in:
parent
def035bf9a
commit
c6d0c82d66
@ -75,6 +75,7 @@ __all__ = (
|
|||||||
'command',
|
'command',
|
||||||
'describe',
|
'describe',
|
||||||
'check',
|
'check',
|
||||||
|
'rename',
|
||||||
'choices',
|
'choices',
|
||||||
'autocomplete',
|
'autocomplete',
|
||||||
'guilds',
|
'guilds',
|
||||||
@ -217,6 +218,29 @@ def _populate_descriptions(params: Dict[str, CommandParameter], descriptions: Di
|
|||||||
raise TypeError(f'unknown parameter given: {first}')
|
raise TypeError(f'unknown parameter given: {first}')
|
||||||
|
|
||||||
|
|
||||||
|
def _populate_renames(params: Dict[str, CommandParameter], renames: Dict[str, str]) -> None:
|
||||||
|
rename_map: Dict[str, str] = {}
|
||||||
|
|
||||||
|
# original name to renamed name
|
||||||
|
|
||||||
|
for name in params.keys():
|
||||||
|
new_name = renames.pop(name, MISSING)
|
||||||
|
|
||||||
|
if new_name is MISSING:
|
||||||
|
rename_map[name] = name
|
||||||
|
continue
|
||||||
|
|
||||||
|
if name in rename_map:
|
||||||
|
raise ValueError(f'{new_name} is already used')
|
||||||
|
|
||||||
|
rename_map[name] = new_name
|
||||||
|
params[name]._rename = new_name
|
||||||
|
|
||||||
|
if renames:
|
||||||
|
first = next(iter(renames))
|
||||||
|
raise ValueError(f'unknown parameter given: {first}')
|
||||||
|
|
||||||
|
|
||||||
def _populate_choices(params: Dict[str, CommandParameter], all_choices: Dict[str, List[Choice]]) -> None:
|
def _populate_choices(params: Dict[str, CommandParameter], all_choices: Dict[str, List[Choice]]) -> None:
|
||||||
for name, param in params.items():
|
for name, param in params.items():
|
||||||
choices = all_choices.pop(name, MISSING)
|
choices = all_choices.pop(name, MISSING)
|
||||||
@ -298,6 +322,13 @@ def _extract_parameters_from_callback(func: Callable[..., Any], globalns: Dict[s
|
|||||||
else:
|
else:
|
||||||
_populate_descriptions(result, descriptions)
|
_populate_descriptions(result, descriptions)
|
||||||
|
|
||||||
|
try:
|
||||||
|
renames = func.__discord_app_commands_param_rename__
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
_populate_renames(result, renames)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
choices = func.__discord_app_commands_param_choices__
|
choices = func.__discord_app_commands_param_choices__
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
@ -475,23 +506,29 @@ class Command(Generic[GroupT, P, T]):
|
|||||||
raise CheckFailure(f'The check functions for command {self.name!r} failed.')
|
raise CheckFailure(f'The check functions for command {self.name!r} failed.')
|
||||||
|
|
||||||
values = namespace.__dict__
|
values = namespace.__dict__
|
||||||
for name, param in self._params.items():
|
transformed_values = {}
|
||||||
|
# get parameters mapped to their renamed names
|
||||||
|
params = {param.display_name: param for param in self._params.values()}
|
||||||
|
|
||||||
|
for name, param in params.items():
|
||||||
try:
|
try:
|
||||||
value = values[name]
|
value = values[name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
if not param.required:
|
if not param.required:
|
||||||
values[name] = param.default
|
transformed_values[name] = param.default
|
||||||
else:
|
else:
|
||||||
raise CommandSignatureMismatch(self) from None
|
raise CommandSignatureMismatch(self) from None
|
||||||
else:
|
else:
|
||||||
values[name] = await param.transform(interaction, value)
|
if param._rename is not MISSING:
|
||||||
|
name = param.name
|
||||||
|
transformed_values[name] = await param.transform(interaction, value)
|
||||||
|
|
||||||
# These type ignores are because the type checker doesn't quite understand the narrowing here
|
# These type ignores are because the type checker doesn't quite understand the narrowing here
|
||||||
# Likewise, it thinks we're missing positional arguments when there aren't any.
|
# Likewise, it thinks we're missing positional arguments when there aren't any.
|
||||||
try:
|
try:
|
||||||
if self.binding is not None:
|
if self.binding is not None:
|
||||||
return await self._callback(self.binding, interaction, **values) # type: ignore
|
return await self._callback(self.binding, interaction, **transformed_values) # type: ignore
|
||||||
return await self._callback(interaction, **values) # type: ignore
|
return await self._callback(interaction, **transformed_values) # type: ignore
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
# In order to detect mismatch from the provided signature and the Discord data,
|
# In order to detect mismatch from the provided signature and the Discord data,
|
||||||
# there are many ways it can go wrong yet all of them eventually lead to a TypeError
|
# there are many ways it can go wrong yet all of them eventually lead to a TypeError
|
||||||
@ -1280,6 +1317,46 @@ def describe(**parameters: str) -> Callable[[T], T]:
|
|||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
def rename(**parameters: str) -> Callable[[T], T]:
|
||||||
|
r"""Renames the given parameters by their name using the key of the keyword argument
|
||||||
|
as the name.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: python3
|
||||||
|
|
||||||
|
@app_commands.command()
|
||||||
|
@app_commands.rename(the_member_to_ban='member')
|
||||||
|
async def ban(interaction: discord.Interaction, the_member_to_ban: discord.Member):
|
||||||
|
await interaction.response.send_message(f'Banned {the_member_to_ban}')
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
-----------
|
||||||
|
\*\*parameters
|
||||||
|
The name of the parameters.
|
||||||
|
|
||||||
|
Raises
|
||||||
|
--------
|
||||||
|
ValueError
|
||||||
|
The parameter name is already used by another parameter.
|
||||||
|
TypeError
|
||||||
|
The parameter name is not found.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def decorator(inner: T) -> T:
|
||||||
|
if isinstance(inner, Command):
|
||||||
|
_populate_renames(inner._params, parameters)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
inner.__discord_app_commands_param_rename__.update(parameters) # type: ignore - Runtime attribute access
|
||||||
|
except AttributeError:
|
||||||
|
inner.__discord_app_commands_param_rename__ = parameters # type: ignore - Runtime attribute assignment
|
||||||
|
|
||||||
|
return inner
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
def choices(**parameters: List[Choice[ChoiceT]]) -> Callable[[T], T]:
|
def choices(**parameters: List[Choice[ChoiceT]]) -> Callable[[T], T]:
|
||||||
r"""Instructs the given parameters by their name to use the given choices for their choices.
|
r"""Instructs the given parameters by their name to use the given choices for their choices.
|
||||||
|
|
||||||
|
@ -101,12 +101,13 @@ class CommandParameter:
|
|||||||
min_value: Optional[Union[int, float]] = None
|
min_value: Optional[Union[int, float]] = None
|
||||||
max_value: Optional[Union[int, float]] = None
|
max_value: Optional[Union[int, float]] = None
|
||||||
autocomplete: Optional[Callable[..., Coroutine[Any, Any, Any]]] = None
|
autocomplete: Optional[Callable[..., Coroutine[Any, Any, Any]]] = None
|
||||||
|
_rename: str = MISSING
|
||||||
_annotation: Any = MISSING
|
_annotation: Any = MISSING
|
||||||
|
|
||||||
def to_dict(self) -> Dict[str, Any]:
|
def to_dict(self) -> Dict[str, Any]:
|
||||||
base = {
|
base = {
|
||||||
'type': self.type.value,
|
'type': self.type.value,
|
||||||
'name': self.name,
|
'name': self.display_name,
|
||||||
'description': self.description,
|
'description': self.description,
|
||||||
'required': self.required,
|
'required': self.required,
|
||||||
}
|
}
|
||||||
@ -146,6 +147,11 @@ class CommandParameter:
|
|||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def display_name(self) -> str:
|
||||||
|
""":class:`str`: The name of the parameter as it should be displayed to the user."""
|
||||||
|
return self.name if self._rename is MISSING else self._rename
|
||||||
|
|
||||||
|
|
||||||
class Transformer:
|
class Transformer:
|
||||||
"""The base class that allows a type annotation in an application command parameter
|
"""The base class that allows a type annotation in an application command parameter
|
||||||
|
@ -462,6 +462,9 @@ Decorators
|
|||||||
.. autofunction:: discord.app_commands.describe
|
.. autofunction:: discord.app_commands.describe
|
||||||
:decorator:
|
:decorator:
|
||||||
|
|
||||||
|
.. autofunction:: discord.app_commands.rename
|
||||||
|
:decorator:
|
||||||
|
|
||||||
.. autofunction:: discord.app_commands.choices
|
.. autofunction:: discord.app_commands.choices
|
||||||
:decorator:
|
:decorator:
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user