From 00a445310b796ad0a8325b9eb7c01cbf1f4b61dc Mon Sep 17 00:00:00 2001 From: Rapptz Date: Sun, 23 Sep 2018 06:12:26 -0400 Subject: [PATCH] [commands] Allow for backtracking parsing with typing.Optional Original code by zephyrkul. This new parsing mode allows for backtracking in case of failure when a typing.Union[..., NoneType] or a typing.Optional[...] is used. This means that if a type would fail to parse, the view is undo'd to a previous state, passing the default parameter to the callback, and then continuing on the next parameter as if nothing had happened. --- discord/ext/commands/core.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/discord/ext/commands/core.py b/discord/ext/commands/core.py index e11642ca6..c64aeb9a1 100644 --- a/discord/ext/commands/core.py +++ b/discord/ext/commands/core.py @@ -281,7 +281,15 @@ class Command: else: if origin is typing.Union: errors = [] + _NoneType = type(None) for conv in converter.__args__: + # if we got to this part in the code, then the previous conversions have failed + # so we should just undo the view, return the default, and allow parsing to continue + # with the other parameters + if conv is _NoneType and param.kind != param.VAR_POSITIONAL: + ctx.view.undo() + return None if param.default is param.empty else param.default + try: value = await self._actual_conversion(ctx, conv, argument, param) except CommandError as e: @@ -317,10 +325,12 @@ class Command: raise MissingRequiredArgument(param) return param.default + previous = view.index if consume_rest_is_special: argument = view.read_rest().strip() else: argument = quoted_word(view) + view.previous = previous return (await self.do_conversion(ctx, converter, argument, param))