-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcli_interface.py
93 lines (63 loc) · 2.67 KB
/
cli_interface.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
from __future__ import annotations
from typing import get_args, get_origin, Callable, Iterable
from types import UnionType
from inspect import signature, _ParameterKind
from type_def import EelTypeBase, EelTypeString, EelTypeError, decode_literal_or_repr
from exceptions import EelExcNotAnEelRepr, EelExcTypeError, EelWhenEvaluating
from misc import read_to_eof
PIPE_IN_HOLDER = "@"
BASIC_INTERFACES: dict[str, Callable] = {}
def convert_arg(raw: str, pipe_in: bool = True) -> EelTypeBase:
if pipe_in and raw == PIPE_IN_HOLDER:
raw = read_to_eof()
elif pipe_in and raw[:2] == (PIPE_IN_HOLDER * 2):
raw = raw[1:]
try:
result = decode_literal_or_repr(raw)
if issubclass(type(result), EelTypeError):
raise EelWhenEvaluating(f"", result.value)
return result
except EelExcNotAnEelRepr:
return EelTypeString(raw)
def get_types(func) -> dict[str, tuple[type, ...]]:
result = {}
for t in signature(func).parameters.values():
if get_origin(t.annotation) is UnionType:
result[t.name] = get_args(t.annotation)
continue
result[t.name] = (t.annotation, )
return result
def get_arg_names_by_kind(func: Callable, kinds: Iterable[_ParameterKind]) -> list[str]:
return list(map(lambda x: x.name, filter(
lambda param: param.kind in kinds,
signature(func).parameters.values())))
def format_list_types(list_types: list[str]) -> str:
if len(list_types) > 1:
result = ", ".join(list_types[:-1]) + " or " + list_types[-1]
else:
result = list_types[0]
return result
def basic_interface(name: str, pipe_in: bool = True):
def runner_conv(func: Callable):
arg_types = get_types(func)
kind_positionals = (_ParameterKind.POSITIONAL_ONLY, _ParameterKind.POSITIONAL_OR_KEYWORD)
positional = get_arg_names_by_kind(func, kind_positionals)
def runner(*args: str):
converted_args: list[EelTypeBase] = []
for i, arg in enumerate(args):
arg_type = arg_types[positional[i]]
try:
converted_arg = convert_arg(arg, pipe_in)
except EelWhenEvaluating as e:
raise EelWhenEvaluating(f"{name} {' '.join(args)}", e.exit_code)
if not issubclass(type(converted_arg), arg_type):
get_name = lambda t: (t.NAME if hasattr(t, "NAME") else t.__name__)
expected = format_list_types([get_name(t) for t in arg_type])
got = get_name(type(converted_arg))
raise EelExcTypeError(
f"{name} on arg#{i}: expected {expected}, got {got}")
converted_args.append(converted_arg)
return func(*converted_args)
BASIC_INTERFACES[name] = runner
return runner
return runner_conv