From 15bfdf66b209ce756f3ecf5ebf18a79a1428980b Mon Sep 17 00:00:00 2001 From: Rapptz Date: Tue, 20 Apr 2021 08:00:47 -0400 Subject: [PATCH] [commands] Default construct flags if they're not passed as parameters This only applies if and only if the flag can be default constructible. Ergo, all the flags are optional or not required. --- discord/ext/commands/core.py | 2 ++ discord/ext/commands/flags.py | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/discord/ext/commands/core.py b/discord/ext/commands/core.py index 5809a156d..642fbe0f7 100644 --- a/discord/ext/commands/core.py +++ b/discord/ext/commands/core.py @@ -559,6 +559,8 @@ class Command(_BaseCommand): if required: if self._is_typing_optional(param.annotation): return None + if hasattr(converter, '__commands_is_flag__') and converter._can_be_constructible(): + return await converter._construct_default(ctx) raise MissingRequiredArgument(param) return param.default diff --git a/discord/ext/commands/flags.py b/discord/ext/commands/flags.py index dc6327213..08f77d93f 100644 --- a/discord/ext/commands/flags.py +++ b/discord/ext/commands/flags.py @@ -408,6 +408,22 @@ class FlagConverter(metaclass=FlagsMeta): """Dict[:class:`str`, :class:`Flag`]: A mapping of flag name to flag object this converter has.""" return cls.__commands_flags__.copy() + @classmethod + def _can_be_constructible(cls) -> bool: + return all(not flag.required for flag in cls.__commands_flags__.values()) + + @classmethod + async def _construct_default(cls: Type[F], ctx: Context) -> F: + self: F = cls.__new__(cls) + flags = cls.__commands_flags__ + for flag in flags.values(): + if callable(flag.default): + default = await maybe_coroutine(flag.default, ctx) + setattr(self, flag.attribute, default) + else: + setattr(self, flag.attribute, flag.default) + return self + def __repr__(self) -> str: pairs = ' '.join([f'{flag.attribute}={getattr(self, flag.attribute)!r}' for flag in self.get_flags().values()]) return f'<{self.__class__.__name__} {pairs}>'