add more advance converters

This commit is contained in:
Zomatree
2021-11-10 16:55:24 +00:00
parent 34a80ea5e2
commit 91fde98739
3 changed files with 55 additions and 12 deletions
+25 -12
View File
@@ -1,12 +1,12 @@
from __future__ import annotations
import traceback
from typing import TYPE_CHECKING, Any, Callable, Coroutine, Optional
from typing import TYPE_CHECKING, Annotated, Any, Callable, Coroutine, Optional, Union, get_args, get_origin
import revolt
import inspect
from contextlib import suppress
from revolt.utils import copy_doc
from revolt.utils import copy_doc, maybe_coroutine
if TYPE_CHECKING:
from .context import Context
@@ -84,20 +84,33 @@ class Command:
traceback.print_exception(type(error), error, error.__traceback__)
@staticmethod
async def convert_argument(arg: str, parameter: inspect.Parameter, context: Context):
def extract_type(t):
if origin := get_origin(t):
if origin is Annotated:
return get_args(t)[1]
return t
@classmethod
async def convert_argument(cls, arg: str, parameter: inspect.Parameter, context: Context):
if annot := parameter.annotation:
func = getattr(annot, "__convert__", None)
if annot is str: # no converting is needed - its already a string
return arg
if func:
output = func(context, arg)
else:
output = annot(arg)
if origin := get_origin(annot):
if origin is Union:
for converter in get_args(annot):
if inspect.isawaitable(output):
output = await output
return output
try:
return await maybe_coroutine(converter, arg, context)
except:
if converter is None:
context.view.undo()
return None
elif origin is Annotated:
converter: Callable[[str, Context], Any] = get_args(annot)[1] # the typehint affects the other if statement somehow
return await maybe_coroutine(converter, arg, context)
else:
return arg
+20
View File
@@ -0,0 +1,20 @@
from typing import Annotated
class ConverterError(Exception):
"""Raised when a converter fails"""
class BadBoolArgument(ConverterError):
"""Raised when the bool converter fails"""
IntConverter = Annotated[int, lambda arg, _: int(arg)]
def bool_converter(arg: str, _):
lowered = arg.lower()
if lowered in ["yes", "true", "ye", "y", "1", "on", "enable"]:
return True
elif lowered in ('no', 'n', 'false', 'f', '0', 'disable', 'off'):
return False
else:
raise BadBoolArgument(lowered)
BoolConverter = Annotated[bool, bool_converter]
+10
View File
@@ -4,6 +4,11 @@ from .errors import NoClosingQuote
class StringView:
def __init__(self, string: str):
self.value = iter(string)
self.temp = ""
self.should_undo = False
def undo(self):
self.should_undo = True
def next_char(self) -> str:
return next(self.value)
@@ -12,6 +17,10 @@ class StringView:
return "".join(self.value)
def get_next_word(self) -> str:
if self.should_undo:
self.should_undo = False
return self.temp
char = self.next_char()
temp = []
@@ -35,5 +44,6 @@ class StringView:
pass
output = "".join(temp)
self.temp = output
return output