mirror of
https://github.com/stoatchat/python-client-sdk.git
synced 2026-07-20 15:38:19 -04:00
add more advance converters
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
Executable
+20
@@ -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]
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user