clan-app: WebExecutor now mirrors jsonschema api types generically
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from functools import wraps
|
||||
from inspect import Parameter, signature
|
||||
from inspect import Parameter, Signature, signature
|
||||
from typing import Annotated, Any, Generic, Literal, TypeVar, get_type_hints
|
||||
|
||||
from clan_cli.errors import ClanError
|
||||
@@ -20,12 +20,14 @@ class ApiError:
|
||||
|
||||
@dataclass
|
||||
class SuccessDataClass(Generic[ResponseDataType]):
|
||||
op_key: str
|
||||
status: Annotated[Literal["success"], "The status of the response."]
|
||||
data: ResponseDataType
|
||||
|
||||
|
||||
@dataclass
|
||||
class ErrorDataClass:
|
||||
op_key: str
|
||||
status: Literal["error"]
|
||||
errors: list[ApiError]
|
||||
|
||||
@@ -39,7 +41,7 @@ def update_wrapper_signature(wrapper: Callable, wrapped: Callable) -> None:
|
||||
|
||||
# Add 'op_key' parameter
|
||||
op_key_param = Parameter(
|
||||
"op_key", Parameter.KEYWORD_ONLY, default=None, annotation=str | None
|
||||
"op_key", Parameter.KEYWORD_ONLY, default=None, annotation=str
|
||||
)
|
||||
params.append(op_key_param)
|
||||
|
||||
@@ -50,26 +52,28 @@ def update_wrapper_signature(wrapper: Callable, wrapped: Callable) -> None:
|
||||
|
||||
class MethodRegistry:
|
||||
def __init__(self) -> None:
|
||||
self._orig_annotations: dict[str, dict[str, Any]] = {}
|
||||
self._orig_signature: dict[str, Signature] = {}
|
||||
self._registry: dict[str, Callable[..., Any]] = {}
|
||||
|
||||
@property
|
||||
def annotations(self) -> dict[str, dict[str, Any]]:
|
||||
return self._orig_annotations
|
||||
def orig_signatures(self) -> dict[str, Signature]:
|
||||
return self._orig_signature
|
||||
|
||||
@property
|
||||
def signatures(self) -> dict[str, Signature]:
|
||||
return {name: signature(fn) for name, fn in self.functions.items()}
|
||||
|
||||
@property
|
||||
def functions(self) -> dict[str, Callable[..., Any]]:
|
||||
return self._registry
|
||||
|
||||
def reset(self) -> None:
|
||||
self._orig_annotations.clear()
|
||||
self._orig_signature.clear()
|
||||
self._registry.clear()
|
||||
|
||||
def register_abstract(self, fn: Callable[..., T]) -> Callable[..., T]:
|
||||
@wraps(fn)
|
||||
def wrapper(
|
||||
*args: Any, op_key: str | None = None, **kwargs: Any
|
||||
) -> ApiResponse[T]:
|
||||
def wrapper(*args: Any, op_key: str, **kwargs: Any) -> ApiResponse[T]:
|
||||
raise NotImplementedError(
|
||||
f"""{fn.__name__} - The platform didn't implement this function.
|
||||
|
||||
@@ -96,20 +100,19 @@ API.register(open_file)
|
||||
def register(self, fn: Callable[..., T]) -> Callable[..., T]:
|
||||
if fn.__name__ in self._registry:
|
||||
raise ValueError(f"Function {fn.__name__} already registered")
|
||||
if fn.__name__ in self._orig_annotations:
|
||||
if fn.__name__ in self._orig_signature:
|
||||
raise ValueError(f"Function {fn.__name__} already registered")
|
||||
# make copy of original function
|
||||
self._orig_annotations[fn.__name__] = fn.__annotations__.copy()
|
||||
self._orig_signature[fn.__name__] = signature(fn)
|
||||
|
||||
@wraps(fn)
|
||||
def wrapper(
|
||||
*args: Any, op_key: str | None = None, **kwargs: Any
|
||||
) -> ApiResponse[T]:
|
||||
def wrapper(*args: Any, op_key: str, **kwargs: Any) -> ApiResponse[T]:
|
||||
try:
|
||||
data: T = fn(*args, **kwargs)
|
||||
return SuccessDataClass(status="success", data=data)
|
||||
return SuccessDataClass(status="success", data=data, op_key=op_key)
|
||||
except ClanError as e:
|
||||
return ErrorDataClass(
|
||||
op_key=op_key,
|
||||
status="error",
|
||||
errors=[
|
||||
ApiError(
|
||||
@@ -127,7 +130,7 @@ API.register(open_file)
|
||||
wrapper.__annotations__["return"] = ApiResponse[orig_return_type] # type: ignore
|
||||
|
||||
# Add additional argument for the operation key
|
||||
wrapper.__annotations__["op_key"] = str | None # type: ignore
|
||||
wrapper.__annotations__["op_key"] = str # type: ignore
|
||||
|
||||
update_wrapper_signature(wrapper, fn)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user