falyx 0.1.29__tar.gz → 0.1.30__tar.gz
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.
- {falyx-0.1.29 → falyx-0.1.30}/PKG-INFO +1 -1
- {falyx-0.1.29 → falyx-0.1.30}/falyx/action/action.py +41 -7
- {falyx-0.1.29 → falyx-0.1.30}/falyx/action/action_factory.py +4 -1
- {falyx-0.1.29 → falyx-0.1.30}/falyx/action/io_action.py +16 -8
- {falyx-0.1.29 → falyx-0.1.30}/falyx/action/menu_action.py +3 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/action/select_file_action.py +3 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/action/selection_action.py +3 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/action/user_input_action.py +3 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/command.py +8 -32
- {falyx-0.1.29 → falyx-0.1.30}/falyx/falyx.py +8 -17
- {falyx-0.1.29 → falyx-0.1.30}/falyx/parsers/__init__.py +0 -4
- {falyx-0.1.29 → falyx-0.1.30}/falyx/parsers/signature.py +5 -2
- {falyx-0.1.29 → falyx-0.1.30}/falyx/parsers/utils.py +4 -10
- falyx-0.1.30/falyx/version.py +1 -0
- {falyx-0.1.29 → falyx-0.1.30}/pyproject.toml +1 -1
- falyx-0.1.29/falyx/version.py +0 -1
- {falyx-0.1.29 → falyx-0.1.30}/LICENSE +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/README.md +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/.pytyped +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/__init__.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/__main__.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/action/.pytyped +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/action/__init__.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/action/http_action.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/action/signal_action.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/action/types.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/bottom_bar.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/config.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/context.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/debug.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/exceptions.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/execution_registry.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/hook_manager.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/hooks.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/init.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/logger.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/menu.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/options_manager.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/parsers/.pytyped +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/parsers/argparse.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/parsers/parsers.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/prompt_utils.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/protocols.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/retry.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/retry_utils.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/selection.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/signals.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/tagged_table.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/themes/__init__.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/themes/colors.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/utils.py +0 -0
- {falyx-0.1.29 → falyx-0.1.30}/falyx/validators.py +0 -0
@@ -47,6 +47,7 @@ from falyx.execution_registry import ExecutionRegistry as er
|
|
47
47
|
from falyx.hook_manager import Hook, HookManager, HookType
|
48
48
|
from falyx.logger import logger
|
49
49
|
from falyx.options_manager import OptionsManager
|
50
|
+
from falyx.parsers.utils import same_argument_definitions
|
50
51
|
from falyx.retry import RetryHandler, RetryPolicy
|
51
52
|
from falyx.themes import OneColors
|
52
53
|
from falyx.utils import ensure_async
|
@@ -101,6 +102,14 @@ class BaseAction(ABC):
|
|
101
102
|
async def preview(self, parent: Tree | None = None):
|
102
103
|
raise NotImplementedError("preview must be implemented by subclasses")
|
103
104
|
|
105
|
+
@abstractmethod
|
106
|
+
def get_infer_target(self) -> Callable[..., Any] | None:
|
107
|
+
"""
|
108
|
+
Returns the callable to be used for argument inference.
|
109
|
+
By default, it returns None.
|
110
|
+
"""
|
111
|
+
raise NotImplementedError("get_infer_target must be implemented by subclasses")
|
112
|
+
|
104
113
|
def set_options_manager(self, options_manager: OptionsManager) -> None:
|
105
114
|
self.options_manager = options_manager
|
106
115
|
|
@@ -246,6 +255,13 @@ class Action(BaseAction):
|
|
246
255
|
if policy.enabled:
|
247
256
|
self.enable_retry()
|
248
257
|
|
258
|
+
def get_infer_target(self) -> Callable[..., Any]:
|
259
|
+
"""
|
260
|
+
Returns the callable to be used for argument inference.
|
261
|
+
By default, it returns the action itself.
|
262
|
+
"""
|
263
|
+
return self.action
|
264
|
+
|
249
265
|
async def _run(self, *args, **kwargs) -> Any:
|
250
266
|
combined_args = args + self.args
|
251
267
|
combined_kwargs = self._maybe_inject_last_result({**self.kwargs, **kwargs})
|
@@ -477,6 +493,14 @@ class ChainedAction(BaseAction, ActionListMixin):
|
|
477
493
|
if hasattr(action, "register_teardown") and callable(action.register_teardown):
|
478
494
|
action.register_teardown(self.hooks)
|
479
495
|
|
496
|
+
def get_infer_target(self) -> Callable[..., Any] | None:
|
497
|
+
if self.actions:
|
498
|
+
return self.actions[0].get_infer_target()
|
499
|
+
return None
|
500
|
+
|
501
|
+
def _clear_args(self):
|
502
|
+
return (), {}
|
503
|
+
|
480
504
|
async def _run(self, *args, **kwargs) -> list[Any]:
|
481
505
|
if not self.actions:
|
482
506
|
raise EmptyChainError(f"[{self.name}] No actions to execute.")
|
@@ -505,12 +529,8 @@ class ChainedAction(BaseAction, ActionListMixin):
|
|
505
529
|
continue
|
506
530
|
shared_context.current_index = index
|
507
531
|
prepared = action.prepare(shared_context, self.options_manager)
|
508
|
-
last_result = shared_context.last_result()
|
509
532
|
try:
|
510
|
-
|
511
|
-
result = await prepared(**{prepared.inject_into: last_result})
|
512
|
-
else:
|
513
|
-
result = await prepared(*args, **updated_kwargs)
|
533
|
+
result = await prepared(*args, **updated_kwargs)
|
514
534
|
except Exception as error:
|
515
535
|
if index + 1 < len(self.actions) and isinstance(
|
516
536
|
self.actions[index + 1], FallbackAction
|
@@ -529,6 +549,7 @@ class ChainedAction(BaseAction, ActionListMixin):
|
|
529
549
|
fallback._skip_in_chain = True
|
530
550
|
else:
|
531
551
|
raise
|
552
|
+
args, updated_kwargs = self._clear_args()
|
532
553
|
shared_context.add_result(result)
|
533
554
|
context.extra["results"].append(result)
|
534
555
|
context.extra["rollback_stack"].append(prepared)
|
@@ -669,6 +690,16 @@ class ActionGroup(BaseAction, ActionListMixin):
|
|
669
690
|
if hasattr(action, "register_teardown") and callable(action.register_teardown):
|
670
691
|
action.register_teardown(self.hooks)
|
671
692
|
|
693
|
+
def get_infer_target(self) -> Callable[..., Any] | None:
|
694
|
+
arg_defs = same_argument_definitions(self.actions)
|
695
|
+
if arg_defs:
|
696
|
+
return self.actions[0].get_infer_target()
|
697
|
+
logger.debug(
|
698
|
+
"[%s] auto_args disabled: mismatched ActionGroup arguments",
|
699
|
+
self.name,
|
700
|
+
)
|
701
|
+
return None
|
702
|
+
|
672
703
|
async def _run(self, *args, **kwargs) -> list[tuple[str, Any]]:
|
673
704
|
shared_context = SharedContext(name=self.name, action=self, is_parallel=True)
|
674
705
|
if self.shared_context:
|
@@ -787,8 +818,11 @@ class ProcessAction(BaseAction):
|
|
787
818
|
self.executor = executor or ProcessPoolExecutor()
|
788
819
|
self.is_retryable = True
|
789
820
|
|
790
|
-
|
791
|
-
|
821
|
+
def get_infer_target(self) -> Callable[..., Any] | None:
|
822
|
+
return self.action
|
823
|
+
|
824
|
+
async def _run(self, *args, **kwargs) -> Any:
|
825
|
+
if self.inject_last_result and self.shared_context:
|
792
826
|
last_result = self.shared_context.last_result()
|
793
827
|
if not self._validate_pickleable(last_result):
|
794
828
|
raise ValueError(
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
|
2
2
|
"""action_factory.py"""
|
3
|
-
from typing import Any
|
3
|
+
from typing import Any, Callable
|
4
4
|
|
5
5
|
from rich.tree import Tree
|
6
6
|
|
@@ -55,6 +55,9 @@ class ActionFactoryAction(BaseAction):
|
|
55
55
|
def factory(self, value: ActionFactoryProtocol):
|
56
56
|
self._factory = ensure_async(value)
|
57
57
|
|
58
|
+
def get_infer_target(self) -> Callable[..., Any]:
|
59
|
+
return self.factory
|
60
|
+
|
58
61
|
async def _run(self, *args, **kwargs) -> Any:
|
59
62
|
updated_kwargs = self._maybe_inject_last_result(kwargs)
|
60
63
|
context = ExecutionContext(
|
@@ -19,7 +19,7 @@ import asyncio
|
|
19
19
|
import shlex
|
20
20
|
import subprocess
|
21
21
|
import sys
|
22
|
-
from typing import Any
|
22
|
+
from typing import Any, Callable
|
23
23
|
|
24
24
|
from rich.tree import Tree
|
25
25
|
|
@@ -81,15 +81,15 @@ class BaseIOAction(BaseAction):
|
|
81
81
|
def to_output(self, result: Any) -> str | bytes:
|
82
82
|
raise NotImplementedError
|
83
83
|
|
84
|
-
async def _resolve_input(
|
85
|
-
|
86
|
-
|
84
|
+
async def _resolve_input(
|
85
|
+
self, args: tuple[Any], kwargs: dict[str, Any]
|
86
|
+
) -> str | bytes:
|
87
87
|
data = await self._read_stdin()
|
88
88
|
if data:
|
89
89
|
return self.from_input(data)
|
90
90
|
|
91
|
-
if
|
92
|
-
return
|
91
|
+
if len(args) == 1:
|
92
|
+
return self.from_input(args[0])
|
93
93
|
|
94
94
|
if self.inject_last_result and self.shared_context:
|
95
95
|
return self.shared_context.last_result()
|
@@ -99,6 +99,9 @@ class BaseIOAction(BaseAction):
|
|
99
99
|
)
|
100
100
|
raise FalyxError("No input provided and no last result to inject.")
|
101
101
|
|
102
|
+
def get_infer_target(self) -> Callable[..., Any] | None:
|
103
|
+
return None
|
104
|
+
|
102
105
|
async def __call__(self, *args, **kwargs):
|
103
106
|
context = ExecutionContext(
|
104
107
|
name=self.name,
|
@@ -117,8 +120,8 @@ class BaseIOAction(BaseAction):
|
|
117
120
|
pass
|
118
121
|
result = getattr(self, "_last_result", None)
|
119
122
|
else:
|
120
|
-
parsed_input = await self._resolve_input(kwargs)
|
121
|
-
result = await self._run(parsed_input
|
123
|
+
parsed_input = await self._resolve_input(args, kwargs)
|
124
|
+
result = await self._run(parsed_input)
|
122
125
|
output = self.to_output(result)
|
123
126
|
await self._write_stdout(output)
|
124
127
|
context.result = result
|
@@ -220,6 +223,11 @@ class ShellAction(BaseIOAction):
|
|
220
223
|
)
|
221
224
|
return raw.strip() if isinstance(raw, str) else raw.decode("utf-8").strip()
|
222
225
|
|
226
|
+
def get_infer_target(self) -> Callable[..., Any] | None:
|
227
|
+
if sys.stdin.isatty():
|
228
|
+
return self._run
|
229
|
+
return None
|
230
|
+
|
223
231
|
async def _run(self, parsed_input: str) -> str:
|
224
232
|
# Replace placeholder in template, or use raw input as full command
|
225
233
|
command = self.command_template.format(parsed_input)
|
@@ -73,6 +73,9 @@ class MenuAction(BaseAction):
|
|
73
73
|
table.add_row(*row)
|
74
74
|
return table
|
75
75
|
|
76
|
+
def get_infer_target(self) -> None:
|
77
|
+
return None
|
78
|
+
|
76
79
|
async def _run(self, *args, **kwargs) -> Any:
|
77
80
|
kwargs = self._maybe_inject_last_result(kwargs)
|
78
81
|
context = ExecutionContext(
|
@@ -121,6 +121,9 @@ class SelectFileAction(BaseAction):
|
|
121
121
|
logger.warning("[ERROR] Failed to parse %s: %s", file.name, error)
|
122
122
|
return options
|
123
123
|
|
124
|
+
def get_infer_target(self) -> None:
|
125
|
+
return None
|
126
|
+
|
124
127
|
async def _run(self, *args, **kwargs) -> Any:
|
125
128
|
context = ExecutionContext(name=self.name, args=args, kwargs=kwargs, action=self)
|
126
129
|
context.start_timer()
|
@@ -85,6 +85,9 @@ class SelectionAction(BaseAction):
|
|
85
85
|
f"got {type(value).__name__}"
|
86
86
|
)
|
87
87
|
|
88
|
+
def get_infer_target(self) -> None:
|
89
|
+
return None
|
90
|
+
|
88
91
|
async def _run(self, *args, **kwargs) -> Any:
|
89
92
|
kwargs = self._maybe_inject_last_result(kwargs)
|
90
93
|
context = ExecutionContext(
|
@@ -43,6 +43,9 @@ class UserInputAction(BaseAction):
|
|
43
43
|
self.console = console or Console(color_system="auto")
|
44
44
|
self.prompt_session = prompt_session or PromptSession()
|
45
45
|
|
46
|
+
def get_infer_target(self) -> None:
|
47
|
+
return None
|
48
|
+
|
46
49
|
async def _run(self, *args, **kwargs) -> str:
|
47
50
|
context = ExecutionContext(
|
48
51
|
name=self.name,
|
@@ -27,13 +27,7 @@ from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, field_validator
|
|
27
27
|
from rich.console import Console
|
28
28
|
from rich.tree import Tree
|
29
29
|
|
30
|
-
from falyx.action.action import
|
31
|
-
Action,
|
32
|
-
ActionGroup,
|
33
|
-
BaseAction,
|
34
|
-
ChainedAction,
|
35
|
-
ProcessAction,
|
36
|
-
)
|
30
|
+
from falyx.action.action import Action, ActionGroup, BaseAction, ChainedAction
|
37
31
|
from falyx.action.io_action import BaseIOAction
|
38
32
|
from falyx.context import ExecutionContext
|
39
33
|
from falyx.debug import register_debug_hooks
|
@@ -41,11 +35,8 @@ from falyx.execution_registry import ExecutionRegistry as er
|
|
41
35
|
from falyx.hook_manager import HookManager, HookType
|
42
36
|
from falyx.logger import logger
|
43
37
|
from falyx.options_manager import OptionsManager
|
44
|
-
from falyx.parsers import
|
45
|
-
|
46
|
-
infer_args_from_func,
|
47
|
-
same_argument_definitions,
|
48
|
-
)
|
38
|
+
from falyx.parsers.argparse import CommandArgumentParser
|
39
|
+
from falyx.parsers.signature import infer_args_from_func
|
49
40
|
from falyx.prompt_utils import confirm_async, should_prompt_user
|
50
41
|
from falyx.protocols import ArgParserProtocol
|
51
42
|
from falyx.retry import RetryPolicy
|
@@ -116,7 +107,7 @@ class Command(BaseModel):
|
|
116
107
|
|
117
108
|
key: str
|
118
109
|
description: str
|
119
|
-
action: BaseAction | Callable[
|
110
|
+
action: BaseAction | Callable[..., Any]
|
120
111
|
args: tuple = ()
|
121
112
|
kwargs: dict[str, Any] = Field(default_factory=dict)
|
122
113
|
hidden: bool = False
|
@@ -145,7 +136,7 @@ class Command(BaseModel):
|
|
145
136
|
argument_config: Callable[[CommandArgumentParser], None] | None = None
|
146
137
|
custom_parser: ArgParserProtocol | None = None
|
147
138
|
custom_help: Callable[[], str | None] | None = None
|
148
|
-
auto_args: bool =
|
139
|
+
auto_args: bool = True
|
149
140
|
arg_metadata: dict[str, str | dict[str, Any]] = Field(default_factory=dict)
|
150
141
|
|
151
142
|
_context: ExecutionContext | None = PrivateAttr(default=None)
|
@@ -195,24 +186,9 @@ class Command(BaseModel):
|
|
195
186
|
elif self.argument_config:
|
196
187
|
self.argument_config(self.arg_parser)
|
197
188
|
elif self.auto_args:
|
198
|
-
if isinstance(self.action,
|
199
|
-
return infer_args_from_func(
|
200
|
-
|
201
|
-
if self.action.actions:
|
202
|
-
action = self.action.actions[0]
|
203
|
-
if isinstance(action, Action):
|
204
|
-
return infer_args_from_func(action.action, self.arg_metadata)
|
205
|
-
elif callable(action):
|
206
|
-
return infer_args_from_func(action, self.arg_metadata)
|
207
|
-
elif isinstance(self.action, ActionGroup):
|
208
|
-
arg_defs = same_argument_definitions(
|
209
|
-
self.action.actions, self.arg_metadata
|
210
|
-
)
|
211
|
-
if arg_defs:
|
212
|
-
return arg_defs
|
213
|
-
logger.debug(
|
214
|
-
"[Command:%s] auto_args disabled: mismatched ActionGroup arguments",
|
215
|
-
self.key,
|
189
|
+
if isinstance(self.action, BaseAction):
|
190
|
+
return infer_args_from_func(
|
191
|
+
self.action.get_infer_target(), self.arg_metadata
|
216
192
|
)
|
217
193
|
elif callable(self.action):
|
218
194
|
return infer_args_from_func(self.action, self.arg_metadata)
|
@@ -63,7 +63,7 @@ from falyx.protocols import ArgParserProtocol
|
|
63
63
|
from falyx.retry import RetryPolicy
|
64
64
|
from falyx.signals import BackSignal, CancelSignal, FlowSignal, HelpSignal, QuitSignal
|
65
65
|
from falyx.themes import OneColors, get_nord_theme
|
66
|
-
from falyx.utils import CaseInsensitiveDict, _noop, chunks
|
66
|
+
from falyx.utils import CaseInsensitiveDict, _noop, chunks
|
67
67
|
from falyx.version import __version__
|
68
68
|
|
69
69
|
|
@@ -158,8 +158,8 @@ class Falyx:
|
|
158
158
|
force_confirm: bool = False,
|
159
159
|
cli_args: Namespace | None = None,
|
160
160
|
options: OptionsManager | None = None,
|
161
|
-
render_menu: Callable[[
|
162
|
-
custom_table: Callable[[
|
161
|
+
render_menu: Callable[[Falyx], None] | None = None,
|
162
|
+
custom_table: Callable[[Falyx], Table] | Table | None = None,
|
163
163
|
) -> None:
|
164
164
|
"""Initializes the Falyx object."""
|
165
165
|
self.title: str | Markdown = title
|
@@ -183,8 +183,8 @@ class Falyx:
|
|
183
183
|
self._never_prompt: bool = never_prompt
|
184
184
|
self._force_confirm: bool = force_confirm
|
185
185
|
self.cli_args: Namespace | None = cli_args
|
186
|
-
self.render_menu: Callable[[
|
187
|
-
self.custom_table: Callable[[
|
186
|
+
self.render_menu: Callable[[Falyx], None] | None = render_menu
|
187
|
+
self.custom_table: Callable[[Falyx], Table] | Table | None = custom_table
|
188
188
|
self.validate_options(cli_args, options)
|
189
189
|
self._prompt_session: PromptSession | None = None
|
190
190
|
self.mode = FalyxMode.MENU
|
@@ -526,7 +526,7 @@ class Falyx:
|
|
526
526
|
key: str = "X",
|
527
527
|
description: str = "Exit",
|
528
528
|
aliases: list[str] | None = None,
|
529
|
-
action: Callable[
|
529
|
+
action: Callable[..., Any] | None = None,
|
530
530
|
style: str = OneColors.DARK_RED,
|
531
531
|
confirm: bool = False,
|
532
532
|
confirm_message: str = "Are you sure?",
|
@@ -580,7 +580,7 @@ class Falyx:
|
|
580
580
|
self,
|
581
581
|
key: str,
|
582
582
|
description: str,
|
583
|
-
action: BaseAction | Callable[
|
583
|
+
action: BaseAction | Callable[..., Any],
|
584
584
|
*,
|
585
585
|
args: tuple = (),
|
586
586
|
kwargs: dict[str, Any] | None = None,
|
@@ -614,7 +614,7 @@ class Falyx:
|
|
614
614
|
argument_config: Callable[[CommandArgumentParser], None] | None = None,
|
615
615
|
custom_parser: ArgParserProtocol | None = None,
|
616
616
|
custom_help: Callable[[], str | None] | None = None,
|
617
|
-
auto_args: bool =
|
617
|
+
auto_args: bool = True,
|
618
618
|
arg_metadata: dict[str, str | dict[str, Any]] | None = None,
|
619
619
|
) -> Command:
|
620
620
|
"""Adds an command to the menu, preventing duplicates."""
|
@@ -844,15 +844,6 @@ class Falyx:
|
|
844
844
|
await selected_command.preview()
|
845
845
|
return True
|
846
846
|
|
847
|
-
if selected_command.requires_input:
|
848
|
-
program = get_program_invocation()
|
849
|
-
self.console.print(
|
850
|
-
f"[{OneColors.LIGHT_YELLOW}]⚠️ Command '{selected_command.key}' requires"
|
851
|
-
f" input and must be run via [{OneColors.MAGENTA}]'{program} run"
|
852
|
-
f"'[{OneColors.LIGHT_YELLOW}] with proper piping or arguments.[/]"
|
853
|
-
)
|
854
|
-
return True
|
855
|
-
|
856
847
|
self.last_run_command = selected_command
|
857
848
|
|
858
849
|
if selected_command == self.exit_command:
|
@@ -7,8 +7,6 @@ Licensed under the MIT License. See LICENSE file for details.
|
|
7
7
|
|
8
8
|
from .argparse import Argument, ArgumentAction, CommandArgumentParser
|
9
9
|
from .parsers import FalyxParsers, get_arg_parsers
|
10
|
-
from .signature import infer_args_from_func
|
11
|
-
from .utils import same_argument_definitions
|
12
10
|
|
13
11
|
__all__ = [
|
14
12
|
"Argument",
|
@@ -16,6 +14,4 @@ __all__ = [
|
|
16
14
|
"CommandArgumentParser",
|
17
15
|
"get_arg_parsers",
|
18
16
|
"FalyxParsers",
|
19
|
-
"infer_args_from_func",
|
20
|
-
"same_argument_definitions",
|
21
17
|
]
|
@@ -1,17 +1,20 @@
|
|
1
1
|
import inspect
|
2
2
|
from typing import Any, Callable
|
3
3
|
|
4
|
-
from falyx import logger
|
4
|
+
from falyx.logger import logger
|
5
5
|
|
6
6
|
|
7
7
|
def infer_args_from_func(
|
8
|
-
func: Callable[[Any], Any],
|
8
|
+
func: Callable[[Any], Any] | None,
|
9
9
|
arg_metadata: dict[str, str | dict[str, Any]] | None = None,
|
10
10
|
) -> list[dict[str, Any]]:
|
11
11
|
"""
|
12
12
|
Infer argument definitions from a callable's signature.
|
13
13
|
Returns a list of kwargs suitable for CommandArgumentParser.add_argument.
|
14
14
|
"""
|
15
|
+
if not callable(func):
|
16
|
+
logger.debug("Provided argument is not callable: %s", func)
|
17
|
+
return []
|
15
18
|
arg_metadata = arg_metadata or {}
|
16
19
|
signature = inspect.signature(func)
|
17
20
|
arg_defs = []
|
@@ -1,7 +1,6 @@
|
|
1
1
|
from typing import Any
|
2
2
|
|
3
3
|
from falyx import logger
|
4
|
-
from falyx.action.action import Action, ChainedAction, ProcessAction
|
5
4
|
from falyx.parsers.signature import infer_args_from_func
|
6
5
|
|
7
6
|
|
@@ -9,17 +8,12 @@ def same_argument_definitions(
|
|
9
8
|
actions: list[Any],
|
10
9
|
arg_metadata: dict[str, str | dict[str, Any]] | None = None,
|
11
10
|
) -> list[dict[str, Any]] | None:
|
11
|
+
from falyx.action.action import BaseAction
|
12
|
+
|
12
13
|
arg_sets = []
|
13
14
|
for action in actions:
|
14
|
-
if isinstance(action,
|
15
|
-
arg_defs = infer_args_from_func(action.
|
16
|
-
elif isinstance(action, ChainedAction):
|
17
|
-
if action.actions:
|
18
|
-
action = action.actions[0]
|
19
|
-
if isinstance(action, Action):
|
20
|
-
arg_defs = infer_args_from_func(action.action, arg_metadata)
|
21
|
-
elif callable(action):
|
22
|
-
arg_defs = infer_args_from_func(action, arg_metadata)
|
15
|
+
if isinstance(action, BaseAction):
|
16
|
+
arg_defs = infer_args_from_func(action.get_infer_target(), arg_metadata)
|
23
17
|
elif callable(action):
|
24
18
|
arg_defs = infer_args_from_func(action, arg_metadata)
|
25
19
|
else:
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.1.30"
|
falyx-0.1.29/falyx/version.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
__version__ = "0.1.29"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|