kash-shell 0.3.10__py3-none-any.whl → 0.3.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kash/actions/core/format_markdown_template.py +2 -5
- kash/actions/core/markdownify.py +2 -4
- kash/actions/core/readability.py +2 -4
- kash/actions/core/render_as_html.py +30 -11
- kash/actions/core/show_webpage.py +6 -11
- kash/actions/core/strip_html.py +2 -6
- kash/actions/core/{webpage_config.py → tabbed_webpage_config.py} +5 -3
- kash/actions/core/{webpage_generate.py → tabbed_webpage_generate.py} +5 -4
- kash/commands/base/files_command.py +28 -10
- kash/commands/workspace/workspace_commands.py +1 -2
- kash/config/colors.py +2 -2
- kash/exec/action_decorators.py +6 -6
- kash/exec/llm_transforms.py +6 -3
- kash/exec/preconditions.py +6 -0
- kash/exec/resolve_args.py +4 -0
- kash/file_storage/file_store.py +20 -18
- kash/help/function_param_info.py +1 -1
- kash/local_server/local_server_routes.py +1 -7
- kash/model/items_model.py +74 -28
- kash/shell/utils/shell_function_wrapper.py +15 -15
- kash/text_handling/doc_normalization.py +1 -1
- kash/text_handling/markdown_render.py +1 -0
- kash/text_handling/markdown_utils.py +22 -0
- kash/utils/common/function_inspect.py +360 -110
- kash/utils/file_utils/file_ext.py +4 -0
- kash/utils/file_utils/file_formats_model.py +17 -1
- kash/web_gen/__init__.py +0 -4
- kash/web_gen/simple_webpage.py +52 -0
- kash/web_gen/tabbed_webpage.py +23 -16
- kash/web_gen/template_render.py +37 -2
- kash/web_gen/templates/base_styles.css.jinja +76 -56
- kash/web_gen/templates/base_webpage.html.jinja +85 -67
- kash/web_gen/templates/item_view.html.jinja +47 -37
- kash/web_gen/templates/simple_webpage.html.jinja +24 -0
- kash/web_gen/templates/tabbed_webpage.html.jinja +42 -32
- {kash_shell-0.3.10.dist-info → kash_shell-0.3.11.dist-info}/METADATA +5 -5
- {kash_shell-0.3.10.dist-info → kash_shell-0.3.11.dist-info}/RECORD +40 -38
- {kash_shell-0.3.10.dist-info → kash_shell-0.3.11.dist-info}/WHEEL +0 -0
- {kash_shell-0.3.10.dist-info → kash_shell-0.3.11.dist-info}/entry_points.txt +0 -0
- {kash_shell-0.3.10.dist-info → kash_shell-0.3.11.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,111 +2,172 @@ import inspect
|
|
|
2
2
|
import types
|
|
3
3
|
from collections.abc import Callable
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
+
from enum import Enum
|
|
5
6
|
from inspect import Parameter
|
|
6
|
-
from typing import Any, Union, cast, get_args, get_origin # pyright: ignore
|
|
7
|
+
from typing import Any, Union, cast, get_args, get_origin # pyright: ignore[reportDeprecated]
|
|
7
8
|
|
|
8
|
-
NO_DEFAULT = Parameter.empty
|
|
9
|
+
NO_DEFAULT = Parameter.empty # Alias for clarity
|
|
10
|
+
|
|
11
|
+
ParameterKind = Parameter.POSITIONAL_ONLY.__class__
|
|
9
12
|
|
|
10
13
|
|
|
11
14
|
@dataclass(frozen=True)
|
|
12
15
|
class FuncParam:
|
|
16
|
+
"""
|
|
17
|
+
Hold structured information about a single function parameter.
|
|
18
|
+
"""
|
|
19
|
+
|
|
13
20
|
name: str
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
21
|
+
kind: ParameterKind # e.g., POSITIONAL_OR_KEYWORD
|
|
22
|
+
annotation: Any # The raw type annotation (can be Parameter.empty)
|
|
23
|
+
default: Any # The raw default value (can be Parameter.empty)
|
|
24
|
+
position: int | None # Position index for positional args, None for keyword-only
|
|
18
25
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
# Resolved type information
|
|
27
|
+
# This is the concrete, simplified main type (e.g., str from str | None, list from list[int])
|
|
28
|
+
effective_type: type | None
|
|
29
|
+
inner_type: type | None # For collections, the type of elements (e.g., str from list[str])
|
|
30
|
+
is_explicitly_optional: bool # True if original annotation was Optional[X] or X | None
|
|
23
31
|
|
|
24
32
|
@property
|
|
25
33
|
def has_default(self) -> bool:
|
|
26
34
|
"""Does this parameter have a default value?"""
|
|
27
35
|
return self.default != NO_DEFAULT
|
|
28
36
|
|
|
37
|
+
@property
|
|
38
|
+
def is_pure_positional(self) -> bool:
|
|
39
|
+
"""Is this a plain or varargs positional parameter, with no default value?"""
|
|
40
|
+
return self.position is not None and not self.has_default
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def is_positional_only(self) -> bool:
|
|
44
|
+
"""Is a true positional parameter, with no default value."""
|
|
45
|
+
return self.kind == Parameter.POSITIONAL_ONLY
|
|
29
46
|
|
|
30
|
-
|
|
47
|
+
@property
|
|
48
|
+
def is_positional_or_keyword(self) -> bool:
|
|
49
|
+
return self.kind == Parameter.POSITIONAL_OR_KEYWORD
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def is_varargs(self) -> bool:
|
|
53
|
+
return self.kind == Parameter.VAR_POSITIONAL or self.kind == Parameter.VAR_KEYWORD
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def is_keyword_only(self) -> bool:
|
|
57
|
+
return self.kind == Parameter.KEYWORD_ONLY
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _resolve_type_details(annotation: Any) -> tuple[type | None, type | None, bool]:
|
|
31
61
|
"""
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
Note that technically, parameters are of 5 types, positional-only,
|
|
40
|
-
positional-or-keyword, keyword-only, varargs, or varargs-keyword, which is what
|
|
41
|
-
`inspect` tells you, but in practice you typically just want to know
|
|
42
|
-
`FuncParam.is_positional()`, i.e. if it is a pure positional parameter (no default)
|
|
43
|
-
and not a keyword (with a default).
|
|
62
|
+
Resolves an annotation into (effective_type, inner_type, is_explicitly_optional).
|
|
63
|
+
|
|
64
|
+
- effective_type: The main type (e.g., str from Optional[str], list from list[int]).
|
|
65
|
+
- inner_type: The type of elements if effective_type is a collection
|
|
66
|
+
(e.g., int from list[int]). For non-collection or unparameterized
|
|
67
|
+
collection, this is None.
|
|
68
|
+
- is_explicitly_optional: True if the annotation was X | None or Optional[X].
|
|
44
69
|
"""
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
params: list[FuncParam] = []
|
|
70
|
+
if annotation is Parameter.empty or annotation is Any:
|
|
71
|
+
return (None, None, False)
|
|
48
72
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
Parameter.POSITIONAL_ONLY,
|
|
52
|
-
Parameter.POSITIONAL_OR_KEYWORD,
|
|
53
|
-
Parameter.VAR_POSITIONAL,
|
|
54
|
-
)
|
|
55
|
-
is_varargs = param.kind in (Parameter.VAR_POSITIONAL, Parameter.VAR_KEYWORD)
|
|
56
|
-
has_default = param.default != NO_DEFAULT
|
|
57
|
-
|
|
58
|
-
# Get type from type annotation or default value.
|
|
59
|
-
param_type: type | None = None
|
|
60
|
-
if param.annotation != Parameter.empty:
|
|
61
|
-
param_type = _extract_simple_type(param.annotation)
|
|
62
|
-
elif param.default is not Parameter.empty:
|
|
63
|
-
param_type = type(param.default)
|
|
64
|
-
|
|
65
|
-
func_param = FuncParam(
|
|
66
|
-
name=param.name,
|
|
67
|
-
type=param_type,
|
|
68
|
-
default=param.default if has_default else NO_DEFAULT,
|
|
69
|
-
position=i + 1 if is_positional else None,
|
|
70
|
-
is_varargs=is_varargs,
|
|
71
|
-
)
|
|
72
|
-
params.append(func_param)
|
|
73
|
+
current_annotation = annotation
|
|
74
|
+
is_optional_flag = False
|
|
73
75
|
|
|
74
|
-
|
|
76
|
+
# Unwrap Optional[T] or T | None (from Python 3.10+ UnionType)
|
|
77
|
+
origin: type | None = get_origin(current_annotation)
|
|
78
|
+
args = get_args(current_annotation)
|
|
79
|
+
|
|
80
|
+
if origin is Union or ( # pyright: ignore[reportDeprecated]
|
|
81
|
+
hasattr(types, "UnionType") and isinstance(current_annotation, types.UnionType)
|
|
82
|
+
):
|
|
83
|
+
non_none_args = [arg for arg in args if arg is not type(None)]
|
|
84
|
+
if len(non_none_args) == 1:
|
|
85
|
+
is_optional_flag = True
|
|
86
|
+
current_annotation = non_none_args[0]
|
|
87
|
+
origin = get_origin(current_annotation) # Re-evaluate for the unwrapped type
|
|
88
|
+
args = get_args(current_annotation)
|
|
89
|
+
elif not non_none_args: # Handles Union[NoneType] or just NoneType
|
|
90
|
+
return (type(None), None, True)
|
|
91
|
+
# If multiple non_none_args (e.g., int | str), current_annotation remains the Union for now.
|
|
92
|
+
|
|
93
|
+
# Determine effective_type and inner_type from (potentially unwrapped) current_annotation
|
|
94
|
+
final_effective_type: type | None = None
|
|
95
|
+
final_inner_type: type | None = None
|
|
96
|
+
|
|
97
|
+
if isinstance(
|
|
98
|
+
current_annotation, type
|
|
99
|
+
): # Covers simple types (int, str) and resolved Union types (int | str)
|
|
100
|
+
final_effective_type = current_annotation
|
|
101
|
+
elif origin and isinstance(origin, type): # Generics like list, dict, tuple (e.g., list[str])
|
|
102
|
+
final_effective_type = cast(type, origin) # This would be `list` for `list[str]`
|
|
103
|
+
if args and _is_type_tuple(args) and args[0] is not Any:
|
|
104
|
+
# For simplicity, take the first type argument as inner_type.
|
|
105
|
+
# E.g., for list[str], inner_type is str. For dict[str, int], inner_type is str.
|
|
106
|
+
final_inner_type = args[0]
|
|
107
|
+
# A more sophisticated approach might handle all args for tuples like tuple[str, int]
|
|
108
|
+
|
|
109
|
+
return final_effective_type, final_inner_type, is_optional_flag
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _is_type_tuple(args: tuple[Any, ...]) -> bool:
|
|
113
|
+
"""Are all args types?"""
|
|
114
|
+
if not args:
|
|
115
|
+
return False
|
|
116
|
+
return all(isinstance(arg, type) for arg in args)
|
|
75
117
|
|
|
76
118
|
|
|
77
|
-
def
|
|
119
|
+
def inspect_function_params(func: Callable[..., Any], unwrap: bool = True) -> list[FuncParam]:
|
|
78
120
|
"""
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
121
|
+
Inspects a Python function's signature and returns a list of `ParamInfo` objects.
|
|
122
|
+
A convenience wrapper for `inspect.signature` that provides a detailed, structured
|
|
123
|
+
representation of each parameter, making it easier to build tools like CLI argument
|
|
124
|
+
parsers. By default, it unwraps decorated functions to get to the original signature.
|
|
82
125
|
"""
|
|
83
|
-
|
|
84
|
-
|
|
126
|
+
unwrapped_func = inspect.unwrap(func) if unwrap else func
|
|
127
|
+
signature = inspect.signature(unwrapped_func)
|
|
85
128
|
|
|
86
|
-
|
|
87
|
-
if hasattr(types, "UnionType") and isinstance(annotation, types.UnionType):
|
|
88
|
-
args = get_args(annotation)
|
|
89
|
-
non_none_args = [arg for arg in args if arg is not type(None)]
|
|
90
|
-
if len(non_none_args) == 1 and isinstance(non_none_args[0], type):
|
|
91
|
-
return non_none_args[0]
|
|
129
|
+
param_infos: list[FuncParam] = []
|
|
92
130
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
131
|
+
for i, (param_name, param_obj) in enumerate(signature.parameters.items()):
|
|
132
|
+
effective_type, inner_type, is_optional = _resolve_type_details(param_obj.annotation)
|
|
133
|
+
|
|
134
|
+
# Fallback: if type is not resolved from annotation, try to infer from default value.
|
|
135
|
+
if (
|
|
136
|
+
effective_type is None
|
|
137
|
+
and param_obj.default is not NO_DEFAULT
|
|
138
|
+
and param_obj.default is not None
|
|
139
|
+
):
|
|
140
|
+
if not is_optional: # Avoid setting NoneType if it was Optional[SomethingElse]
|
|
141
|
+
effective_type = type(param_obj.default)
|
|
142
|
+
|
|
143
|
+
# Determine position
|
|
144
|
+
is_positional = param_obj.kind in (
|
|
145
|
+
Parameter.POSITIONAL_ONLY,
|
|
146
|
+
Parameter.POSITIONAL_OR_KEYWORD,
|
|
147
|
+
Parameter.VAR_POSITIONAL,
|
|
148
|
+
)
|
|
149
|
+
position = i + 1 if is_positional else None
|
|
150
|
+
|
|
151
|
+
info = FuncParam(
|
|
152
|
+
name=param_name,
|
|
153
|
+
kind=param_obj.kind,
|
|
154
|
+
annotation=param_obj.annotation, # Store raw annotation
|
|
155
|
+
default=param_obj.default, # Store raw default
|
|
156
|
+
position=position,
|
|
157
|
+
effective_type=effective_type,
|
|
158
|
+
inner_type=inner_type,
|
|
159
|
+
is_explicitly_optional=is_optional,
|
|
160
|
+
)
|
|
161
|
+
param_infos.append(info)
|
|
102
162
|
|
|
103
|
-
return
|
|
163
|
+
return param_infos
|
|
104
164
|
|
|
105
165
|
|
|
106
166
|
## Tests
|
|
107
167
|
|
|
108
168
|
|
|
109
|
-
def
|
|
169
|
+
def test_inspect_function_parameters_updated():
|
|
170
|
+
# Test functions from your original example
|
|
110
171
|
def func0(path: str | None = None) -> list:
|
|
111
172
|
return [path]
|
|
112
173
|
|
|
@@ -124,55 +185,244 @@ def test_inspect_function_params():
|
|
|
124
185
|
def func4() -> list:
|
|
125
186
|
return []
|
|
126
187
|
|
|
127
|
-
def func5(x: int, y: int = 3, *, z: int = 4, **kwargs):
|
|
128
|
-
|
|
188
|
+
def func5(x: int, y: int = 3, *, z: int = 4, **kwargs):
|
|
189
|
+
return [x, y, z, kwargs]
|
|
129
190
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
191
|
+
class MyEnum(Enum):
|
|
192
|
+
ITEM1 = "item1"
|
|
193
|
+
ITEM2 = "item2"
|
|
194
|
+
|
|
195
|
+
def func6(opt_enum: MyEnum | None = MyEnum.ITEM1):
|
|
196
|
+
return [opt_enum]
|
|
136
197
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
print()
|
|
140
|
-
print(repr(params1))
|
|
141
|
-
print()
|
|
142
|
-
print(repr(params2))
|
|
143
|
-
print()
|
|
144
|
-
print(repr(params3))
|
|
145
|
-
print()
|
|
146
|
-
print(repr(params4))
|
|
147
|
-
print()
|
|
148
|
-
print(repr(params5))
|
|
149
|
-
|
|
150
|
-
assert params0 == [FuncParam(name="path", type=str, default=None, position=1, is_varargs=False)]
|
|
198
|
+
def func7(numbers: list[int]):
|
|
199
|
+
return [numbers]
|
|
151
200
|
|
|
201
|
+
def func8(maybe_list: list[str] | None = None):
|
|
202
|
+
return [maybe_list]
|
|
203
|
+
|
|
204
|
+
params0 = inspect_function_params(func0)
|
|
205
|
+
print("\ninspect_function_parameters results:")
|
|
206
|
+
print(f"func0: {params0}")
|
|
207
|
+
assert params0 == [
|
|
208
|
+
FuncParam(
|
|
209
|
+
name="path",
|
|
210
|
+
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
|
211
|
+
annotation=(str | None),
|
|
212
|
+
default=None,
|
|
213
|
+
position=1,
|
|
214
|
+
effective_type=str,
|
|
215
|
+
inner_type=None,
|
|
216
|
+
is_explicitly_optional=True,
|
|
217
|
+
)
|
|
218
|
+
]
|
|
219
|
+
|
|
220
|
+
params1 = inspect_function_params(func1)
|
|
221
|
+
print(f"func1: {params1}")
|
|
152
222
|
assert params1 == [
|
|
153
|
-
FuncParam(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
223
|
+
FuncParam(
|
|
224
|
+
name="arg1",
|
|
225
|
+
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
|
226
|
+
annotation=str,
|
|
227
|
+
default=NO_DEFAULT,
|
|
228
|
+
position=1,
|
|
229
|
+
effective_type=str,
|
|
230
|
+
inner_type=None,
|
|
231
|
+
is_explicitly_optional=False,
|
|
232
|
+
),
|
|
233
|
+
FuncParam(
|
|
234
|
+
name="arg2",
|
|
235
|
+
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
|
236
|
+
annotation=str,
|
|
237
|
+
default=NO_DEFAULT,
|
|
238
|
+
position=2,
|
|
239
|
+
effective_type=str,
|
|
240
|
+
inner_type=None,
|
|
241
|
+
is_explicitly_optional=False,
|
|
242
|
+
),
|
|
243
|
+
FuncParam(
|
|
244
|
+
name="arg3",
|
|
245
|
+
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
|
246
|
+
annotation=int,
|
|
247
|
+
default=NO_DEFAULT,
|
|
248
|
+
position=3,
|
|
249
|
+
effective_type=int,
|
|
250
|
+
inner_type=None,
|
|
251
|
+
is_explicitly_optional=False,
|
|
252
|
+
),
|
|
253
|
+
FuncParam(
|
|
254
|
+
name="option_one",
|
|
255
|
+
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
|
256
|
+
annotation=bool,
|
|
257
|
+
default=False,
|
|
258
|
+
position=4,
|
|
259
|
+
effective_type=bool,
|
|
260
|
+
inner_type=None,
|
|
261
|
+
is_explicitly_optional=False,
|
|
262
|
+
), # bool default makes it not explicitly Optional from type
|
|
263
|
+
FuncParam(
|
|
264
|
+
name="option_two",
|
|
265
|
+
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
|
266
|
+
annotation=(str | None),
|
|
267
|
+
default=None,
|
|
268
|
+
position=5,
|
|
269
|
+
effective_type=str,
|
|
270
|
+
inner_type=None,
|
|
271
|
+
is_explicitly_optional=True,
|
|
272
|
+
),
|
|
158
273
|
]
|
|
159
274
|
|
|
275
|
+
params2 = inspect_function_params(func2)
|
|
276
|
+
print(f"func2: {params2}")
|
|
160
277
|
assert params2 == [
|
|
161
|
-
FuncParam(
|
|
162
|
-
|
|
163
|
-
|
|
278
|
+
FuncParam(
|
|
279
|
+
name="paths",
|
|
280
|
+
kind=Parameter.VAR_POSITIONAL,
|
|
281
|
+
annotation=str,
|
|
282
|
+
default=NO_DEFAULT,
|
|
283
|
+
position=1,
|
|
284
|
+
effective_type=str,
|
|
285
|
+
inner_type=None,
|
|
286
|
+
is_explicitly_optional=False,
|
|
287
|
+
), # For *args: T, effective_type is T
|
|
288
|
+
FuncParam(
|
|
289
|
+
name="summary",
|
|
290
|
+
kind=Parameter.KEYWORD_ONLY,
|
|
291
|
+
annotation=(bool | None),
|
|
292
|
+
default=False,
|
|
293
|
+
position=None,
|
|
294
|
+
effective_type=bool,
|
|
295
|
+
inner_type=None,
|
|
296
|
+
is_explicitly_optional=True,
|
|
297
|
+
),
|
|
298
|
+
FuncParam(
|
|
299
|
+
name="iso_time",
|
|
300
|
+
kind=Parameter.KEYWORD_ONLY,
|
|
301
|
+
annotation=bool,
|
|
302
|
+
default=False,
|
|
303
|
+
position=None,
|
|
304
|
+
effective_type=bool,
|
|
305
|
+
inner_type=None,
|
|
306
|
+
is_explicitly_optional=False,
|
|
307
|
+
),
|
|
164
308
|
]
|
|
165
309
|
|
|
310
|
+
params3 = inspect_function_params(func3)
|
|
311
|
+
print(f"func3: {params3}")
|
|
166
312
|
assert params3 == [
|
|
167
|
-
FuncParam(
|
|
168
|
-
|
|
313
|
+
FuncParam(
|
|
314
|
+
name="arg1",
|
|
315
|
+
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
|
316
|
+
annotation=str,
|
|
317
|
+
default=NO_DEFAULT,
|
|
318
|
+
position=1,
|
|
319
|
+
effective_type=str,
|
|
320
|
+
inner_type=None,
|
|
321
|
+
is_explicitly_optional=False,
|
|
322
|
+
),
|
|
323
|
+
FuncParam(
|
|
324
|
+
name="keywords",
|
|
325
|
+
kind=Parameter.VAR_KEYWORD,
|
|
326
|
+
annotation=Parameter.empty,
|
|
327
|
+
default=NO_DEFAULT,
|
|
328
|
+
position=None,
|
|
329
|
+
effective_type=None,
|
|
330
|
+
inner_type=None,
|
|
331
|
+
is_explicitly_optional=False,
|
|
332
|
+
),
|
|
169
333
|
]
|
|
170
334
|
|
|
335
|
+
params4 = inspect_function_params(func4)
|
|
336
|
+
print(f"func4: {params4}")
|
|
171
337
|
assert params4 == []
|
|
172
338
|
|
|
339
|
+
params5 = inspect_function_params(func5)
|
|
340
|
+
print(f"func5: {params5}")
|
|
173
341
|
assert params5 == [
|
|
174
|
-
FuncParam(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
342
|
+
FuncParam(
|
|
343
|
+
name="x",
|
|
344
|
+
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
|
345
|
+
annotation=int,
|
|
346
|
+
default=NO_DEFAULT,
|
|
347
|
+
position=1,
|
|
348
|
+
effective_type=int,
|
|
349
|
+
inner_type=None,
|
|
350
|
+
is_explicitly_optional=False,
|
|
351
|
+
),
|
|
352
|
+
FuncParam(
|
|
353
|
+
name="y",
|
|
354
|
+
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
|
355
|
+
annotation=int,
|
|
356
|
+
default=3,
|
|
357
|
+
position=2,
|
|
358
|
+
effective_type=int,
|
|
359
|
+
inner_type=None,
|
|
360
|
+
is_explicitly_optional=False,
|
|
361
|
+
),
|
|
362
|
+
FuncParam(
|
|
363
|
+
name="z",
|
|
364
|
+
kind=Parameter.KEYWORD_ONLY,
|
|
365
|
+
annotation=int,
|
|
366
|
+
default=4,
|
|
367
|
+
position=None,
|
|
368
|
+
effective_type=int,
|
|
369
|
+
inner_type=None,
|
|
370
|
+
is_explicitly_optional=False,
|
|
371
|
+
),
|
|
372
|
+
FuncParam(
|
|
373
|
+
name="kwargs",
|
|
374
|
+
kind=Parameter.VAR_KEYWORD,
|
|
375
|
+
annotation=Parameter.empty,
|
|
376
|
+
default=NO_DEFAULT,
|
|
377
|
+
position=None,
|
|
378
|
+
effective_type=None,
|
|
379
|
+
inner_type=None,
|
|
380
|
+
is_explicitly_optional=False,
|
|
381
|
+
),
|
|
382
|
+
]
|
|
383
|
+
|
|
384
|
+
params6 = inspect_function_params(func6)
|
|
385
|
+
print(f"func6: {params6}")
|
|
386
|
+
|
|
387
|
+
assert params6 == [
|
|
388
|
+
FuncParam(
|
|
389
|
+
name="opt_enum",
|
|
390
|
+
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
|
391
|
+
annotation=(MyEnum | None),
|
|
392
|
+
default=MyEnum.ITEM1,
|
|
393
|
+
position=1,
|
|
394
|
+
effective_type=MyEnum,
|
|
395
|
+
inner_type=None,
|
|
396
|
+
is_explicitly_optional=True,
|
|
397
|
+
)
|
|
398
|
+
]
|
|
399
|
+
|
|
400
|
+
params7 = inspect_function_params(func7)
|
|
401
|
+
print(f"func7: {params7}")
|
|
402
|
+
assert params7 == [
|
|
403
|
+
FuncParam(
|
|
404
|
+
name="numbers",
|
|
405
|
+
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
|
406
|
+
annotation=list[int],
|
|
407
|
+
default=NO_DEFAULT,
|
|
408
|
+
position=1,
|
|
409
|
+
effective_type=list,
|
|
410
|
+
inner_type=int,
|
|
411
|
+
is_explicitly_optional=False,
|
|
412
|
+
)
|
|
413
|
+
]
|
|
414
|
+
|
|
415
|
+
params8 = inspect_function_params(func8)
|
|
416
|
+
print(f"func8: {params8}")
|
|
417
|
+
assert params8 == [
|
|
418
|
+
FuncParam(
|
|
419
|
+
name="maybe_list",
|
|
420
|
+
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
|
421
|
+
annotation=(list[str] | None),
|
|
422
|
+
default=None,
|
|
423
|
+
position=1,
|
|
424
|
+
effective_type=list,
|
|
425
|
+
inner_type=str,
|
|
426
|
+
is_explicitly_optional=True,
|
|
427
|
+
)
|
|
178
428
|
]
|
|
@@ -20,6 +20,7 @@ class FileExt(Enum):
|
|
|
20
20
|
diff = "diff"
|
|
21
21
|
json = "json"
|
|
22
22
|
csv = "csv"
|
|
23
|
+
xlsx = "xlsx"
|
|
23
24
|
npz = "npz"
|
|
24
25
|
log = "log"
|
|
25
26
|
py = "py"
|
|
@@ -34,6 +35,8 @@ class FileExt(Enum):
|
|
|
34
35
|
mp3 = "mp3"
|
|
35
36
|
m4a = "m4a"
|
|
36
37
|
mp4 = "mp4"
|
|
38
|
+
pptx = "pptx"
|
|
39
|
+
epub = "epub"
|
|
37
40
|
|
|
38
41
|
@property
|
|
39
42
|
def dot_ext(self) -> str:
|
|
@@ -50,6 +53,7 @@ class FileExt(Enum):
|
|
|
50
53
|
self.py,
|
|
51
54
|
self.sh,
|
|
52
55
|
self.xsh,
|
|
56
|
+
self.epub,
|
|
53
57
|
]
|
|
54
58
|
|
|
55
59
|
@property
|
|
@@ -48,6 +48,7 @@ class Format(Enum):
|
|
|
48
48
|
"""`md_html` is Markdown with HTML, used for example when we structure Markdown with divs."""
|
|
49
49
|
html = "html"
|
|
50
50
|
"""`markdown` should be simple and clean Markdown that we can use with LLMs."""
|
|
51
|
+
epub = "epub"
|
|
51
52
|
yaml = "yaml"
|
|
52
53
|
diff = "diff"
|
|
53
54
|
python = "python"
|
|
@@ -56,12 +57,14 @@ class Format(Enum):
|
|
|
56
57
|
xonsh = "xonsh"
|
|
57
58
|
json = "json"
|
|
58
59
|
csv = "csv"
|
|
60
|
+
xlsx = "xlsx"
|
|
59
61
|
npz = "npz"
|
|
60
62
|
log = "log"
|
|
61
63
|
|
|
62
64
|
# Media formats.
|
|
63
65
|
pdf = "pdf"
|
|
64
66
|
docx = "docx"
|
|
67
|
+
pptx = "pptx"
|
|
65
68
|
jpeg = "jpeg"
|
|
66
69
|
png = "png"
|
|
67
70
|
gif = "gif"
|
|
@@ -108,6 +111,7 @@ class Format(Enum):
|
|
|
108
111
|
self.html,
|
|
109
112
|
self.pdf,
|
|
110
113
|
self.docx,
|
|
114
|
+
self.pptx,
|
|
111
115
|
]
|
|
112
116
|
|
|
113
117
|
@property
|
|
@@ -128,7 +132,7 @@ class Format(Enum):
|
|
|
128
132
|
|
|
129
133
|
@property
|
|
130
134
|
def is_data(self) -> bool:
|
|
131
|
-
return self in [self.csv, self.npz]
|
|
135
|
+
return self in [self.csv, self.xlsx, self.npz]
|
|
132
136
|
|
|
133
137
|
@property
|
|
134
138
|
def is_binary(self) -> bool:
|
|
@@ -166,6 +170,7 @@ class Format(Enum):
|
|
|
166
170
|
Format.markdown: MediaType.text,
|
|
167
171
|
Format.md_html: MediaType.text,
|
|
168
172
|
Format.html: MediaType.webpage,
|
|
173
|
+
Format.epub: MediaType.text,
|
|
169
174
|
Format.yaml: MediaType.text,
|
|
170
175
|
Format.diff: MediaType.text,
|
|
171
176
|
Format.python: MediaType.text,
|
|
@@ -175,11 +180,13 @@ class Format(Enum):
|
|
|
175
180
|
Format.csv: MediaType.text,
|
|
176
181
|
Format.log: MediaType.text,
|
|
177
182
|
Format.pdf: MediaType.text,
|
|
183
|
+
Format.xlsx: MediaType.text,
|
|
178
184
|
Format.jpeg: MediaType.image,
|
|
179
185
|
Format.png: MediaType.image,
|
|
180
186
|
Format.gif: MediaType.image,
|
|
181
187
|
Format.svg: MediaType.image,
|
|
182
188
|
Format.docx: MediaType.text,
|
|
189
|
+
Format.pptx: MediaType.text,
|
|
183
190
|
Format.mp3: MediaType.audio,
|
|
184
191
|
Format.m4a: MediaType.audio,
|
|
185
192
|
Format.mp4: MediaType.video,
|
|
@@ -200,6 +207,7 @@ class Format(Enum):
|
|
|
200
207
|
FileExt.diff.value: Format.diff,
|
|
201
208
|
FileExt.json.value: Format.json,
|
|
202
209
|
FileExt.csv.value: Format.csv,
|
|
210
|
+
FileExt.xlsx.value: Format.xlsx,
|
|
203
211
|
FileExt.npz.value: Format.npz,
|
|
204
212
|
FileExt.log.value: Format.log,
|
|
205
213
|
FileExt.py.value: Format.python,
|
|
@@ -207,6 +215,7 @@ class Format(Enum):
|
|
|
207
215
|
FileExt.xsh.value: Format.xonsh,
|
|
208
216
|
FileExt.pdf.value: Format.pdf,
|
|
209
217
|
FileExt.docx.value: Format.docx,
|
|
218
|
+
FileExt.pptx.value: Format.pptx,
|
|
210
219
|
FileExt.jpg.value: Format.jpeg,
|
|
211
220
|
FileExt.png.value: Format.png,
|
|
212
221
|
FileExt.gif.value: Format.gif,
|
|
@@ -214,6 +223,7 @@ class Format(Enum):
|
|
|
214
223
|
FileExt.mp3.value: Format.mp3,
|
|
215
224
|
FileExt.m4a.value: Format.m4a,
|
|
216
225
|
FileExt.mp4.value: Format.mp4,
|
|
226
|
+
FileExt.epub.value: Format.epub,
|
|
217
227
|
}
|
|
218
228
|
return ext_to_format.get(file_ext.value, None)
|
|
219
229
|
|
|
@@ -228,10 +238,12 @@ class Format(Enum):
|
|
|
228
238
|
Format.md_html: FileExt.md,
|
|
229
239
|
Format.html: FileExt.html,
|
|
230
240
|
Format.plaintext: FileExt.txt,
|
|
241
|
+
Format.epub: FileExt.epub,
|
|
231
242
|
Format.yaml: FileExt.yml,
|
|
232
243
|
Format.diff: FileExt.diff,
|
|
233
244
|
Format.json: FileExt.json,
|
|
234
245
|
Format.csv: FileExt.csv,
|
|
246
|
+
Format.xlsx: FileExt.xlsx,
|
|
235
247
|
Format.npz: FileExt.npz,
|
|
236
248
|
Format.log: FileExt.log,
|
|
237
249
|
Format.python: FileExt.py,
|
|
@@ -239,6 +251,7 @@ class Format(Enum):
|
|
|
239
251
|
Format.xonsh: FileExt.xsh,
|
|
240
252
|
Format.pdf: FileExt.pdf,
|
|
241
253
|
Format.docx: FileExt.docx,
|
|
254
|
+
Format.pptx: FileExt.pptx,
|
|
242
255
|
Format.jpeg: FileExt.jpg,
|
|
243
256
|
Format.png: FileExt.png,
|
|
244
257
|
Format.gif: FileExt.gif,
|
|
@@ -260,6 +273,7 @@ class Format(Enum):
|
|
|
260
273
|
"text/html": Format.html,
|
|
261
274
|
"text/diff": Format.diff,
|
|
262
275
|
"text/x-diff": Format.diff,
|
|
276
|
+
"application/epub+zip": Format.epub,
|
|
263
277
|
"application/yaml": Format.yaml,
|
|
264
278
|
"application/x-yaml": Format.yaml,
|
|
265
279
|
"text/x-python": Format.python,
|
|
@@ -269,9 +283,11 @@ class Format(Enum):
|
|
|
269
283
|
"text/x-xonsh": Format.xonsh,
|
|
270
284
|
"application/json": Format.json,
|
|
271
285
|
"text/csv": Format.csv,
|
|
286
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": Format.xlsx,
|
|
272
287
|
"application/x-npz": Format.npz,
|
|
273
288
|
"application/pdf": Format.pdf,
|
|
274
289
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": Format.docx,
|
|
290
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation": Format.pptx,
|
|
275
291
|
"image/jpeg": Format.jpeg,
|
|
276
292
|
"image/png": Format.png,
|
|
277
293
|
"image/gif": Format.gif,
|
kash/web_gen/__init__.py
CHANGED