Browse Source

[commands] Add support for Greedy for hybrid commands

pull/7881/head
Rapptz 3 years ago
parent
commit
393fdde037
  1. 6
      discord/ext/commands/converter.py
  2. 27
      discord/ext/commands/hybrid.py

6
discord/ext/commands/converter.py

@ -1021,6 +1021,12 @@ class Greedy(List[T]):
``[1, 2, 3, 4, 5, 6]`` and ``reason`` with ``hello``\. ``[1, 2, 3, 4, 5, 6]`` and ``reason`` with ``hello``\.
For more information, check :ref:`ext_commands_special_converters`. For more information, check :ref:`ext_commands_special_converters`.
.. note::
For interaction based contexts the conversion error is propagated
rather than swallowed due to the difference in user experience with
application commands.
""" """
__slots__ = ('converter',) __slots__ = ('converter',)

27
discord/ext/commands/hybrid.py

@ -43,9 +43,10 @@ from discord import app_commands
from discord.utils import MISSING, maybe_coroutine, async_all from discord.utils import MISSING, maybe_coroutine, async_all
from .core import Command, Group from .core import Command, Group
from .errors import BadArgument, CommandRegistrationError, CommandError, HybridCommandError, ConversionError from .errors import BadArgument, CommandRegistrationError, CommandError, HybridCommandError, ConversionError
from .converter import Converter, Range from .converter import Converter, Range, Greedy, run_converters
from .parameters import Parameter from .parameters import Parameter
from .cog import Cog from .cog import Cog
from .view import StringView
if TYPE_CHECKING: if TYPE_CHECKING:
from typing_extensions import Self, ParamSpec, Concatenate from typing_extensions import Self, ParamSpec, Concatenate
@ -137,6 +138,24 @@ def make_callable_transformer(func: Callable[[str], Any]) -> Type[app_commands.T
return type('CallableTransformer', (app_commands.Transformer,), {'transform': classmethod(transform)}) return type('CallableTransformer', (app_commands.Transformer,), {'transform': classmethod(transform)})
def make_greedy_transformer(converter: Any, parameter: Parameter) -> Type[app_commands.Transformer]:
async def transform(cls, interaction: discord.Interaction, value: str) -> Any:
view = StringView(value)
result = []
while True:
arg = view.get_quoted_word()
if arg is None:
break
# This propagates the exception
converted = await run_converters(interaction._baton, converter, arg, parameter)
result.append(converted)
return result
return type('GreedyTransformer', (app_commands.Transformer,), {'transform': classmethod(transform)})
def replace_parameters(parameters: Dict[str, Parameter], signature: inspect.Signature) -> List[inspect.Parameter]: def replace_parameters(parameters: Dict[str, Parameter], signature: inspect.Signature) -> List[inspect.Parameter]:
# Need to convert commands.Parameter back to inspect.Parameter so this will be a bit ugly # Need to convert commands.Parameter back to inspect.Parameter so this will be a bit ugly
params = signature.parameters.copy() params = signature.parameters.copy()
@ -152,6 +171,12 @@ def replace_parameters(parameters: Dict[str, Parameter], signature: inspect.Sign
if isinstance(parameter.converter, Range): if isinstance(parameter.converter, Range):
r = parameter.converter r = parameter.converter
param = param.replace(annotation=app_commands.Range[r.annotation, r.min, r.max]) # type: ignore param = param.replace(annotation=app_commands.Range[r.annotation, r.min, r.max]) # type: ignore
elif isinstance(parameter.converter, Greedy):
# Greedy is "optional" in ext.commands
# However, in here, it probably makes sense to make it required.
# I'm unsure how to allow the user to choose right now.
inner = parameter.converter.converter
param = param.replace(annotation=make_greedy_transformer(inner, parameter))
elif is_converter(parameter.converter): elif is_converter(parameter.converter):
param = param.replace(annotation=make_converter_transformer(parameter.converter)) param = param.replace(annotation=make_converter_transformer(parameter.converter))
elif origin is Union and len(args) == 2 and args[-1] is _NoneType: elif origin is Union and len(args) == 2 and args[-1] is _NoneType:

Loading…
Cancel
Save