[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.
This commit is contained in:
		| @@ -281,7 +281,15 @@ class Command: | |||||||
|         else: |         else: | ||||||
|             if origin is typing.Union: |             if origin is typing.Union: | ||||||
|                 errors = [] |                 errors = [] | ||||||
|  |                 _NoneType = type(None) | ||||||
|                 for conv in converter.__args__: |                 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: |                     try: | ||||||
|                         value = await self._actual_conversion(ctx, conv, argument, param) |                         value = await self._actual_conversion(ctx, conv, argument, param) | ||||||
|                     except CommandError as e: |                     except CommandError as e: | ||||||
| @@ -317,10 +325,12 @@ class Command: | |||||||
|                 raise MissingRequiredArgument(param) |                 raise MissingRequiredArgument(param) | ||||||
|             return param.default |             return param.default | ||||||
|  |  | ||||||
|  |         previous = view.index | ||||||
|         if consume_rest_is_special: |         if consume_rest_is_special: | ||||||
|             argument = view.read_rest().strip() |             argument = view.read_rest().strip() | ||||||
|         else: |         else: | ||||||
|             argument = quoted_word(view) |             argument = quoted_word(view) | ||||||
|  |         view.previous = previous | ||||||
|  |  | ||||||
|         return (await self.do_conversion(ctx, converter, argument, param)) |         return (await self.do_conversion(ctx, converter, argument, param)) | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user