falyx 0.1.18__py3-none-any.whl → 0.1.20__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.
- falyx/action.py +40 -24
- falyx/action_factory.py +95 -0
- falyx/falyx.py +52 -21
- falyx/http_action.py +8 -5
- falyx/init.py +4 -2
- falyx/io_action.py +3 -3
- falyx/menu_action.py +4 -6
- falyx/prompt_utils.py +1 -2
- falyx/protocols.py +9 -0
- falyx/select_files_action.py +3 -3
- falyx/selection.py +17 -17
- falyx/selection_action.py +12 -10
- falyx/version.py +1 -1
- {falyx-0.1.18.dist-info → falyx-0.1.20.dist-info}/METADATA +1 -1
- {falyx-0.1.18.dist-info → falyx-0.1.20.dist-info}/RECORD +18 -17
- falyx/.coverage +0 -0
- {falyx-0.1.18.dist-info → falyx-0.1.20.dist-info}/LICENSE +0 -0
- {falyx-0.1.18.dist-info → falyx-0.1.20.dist-info}/WHEEL +0 -0
- {falyx-0.1.18.dist-info → falyx-0.1.20.dist-info}/entry_points.txt +0 -0
falyx/action.py
CHANGED
@@ -56,7 +56,7 @@ class BaseAction(ABC):
|
|
56
56
|
be run independently or as part of Falyx.
|
57
57
|
|
58
58
|
inject_last_result (bool): Whether to inject the previous action's result into kwargs.
|
59
|
-
|
59
|
+
inject_into (str): The name of the kwarg key to inject the result as
|
60
60
|
(default: 'last_result').
|
61
61
|
_requires_injection (bool): Whether the action requires input injection.
|
62
62
|
"""
|
@@ -66,7 +66,7 @@ class BaseAction(ABC):
|
|
66
66
|
name: str,
|
67
67
|
hooks: HookManager | None = None,
|
68
68
|
inject_last_result: bool = False,
|
69
|
-
|
69
|
+
inject_into: str = "last_result",
|
70
70
|
never_prompt: bool = False,
|
71
71
|
logging_hooks: bool = False,
|
72
72
|
) -> None:
|
@@ -75,7 +75,7 @@ class BaseAction(ABC):
|
|
75
75
|
self.is_retryable: bool = False
|
76
76
|
self.shared_context: SharedContext | None = None
|
77
77
|
self.inject_last_result: bool = inject_last_result
|
78
|
-
self.
|
78
|
+
self.inject_into: str = inject_into
|
79
79
|
self._never_prompt: bool = never_prompt
|
80
80
|
self._requires_injection: bool = False
|
81
81
|
self._skip_in_chain: bool = False
|
@@ -133,7 +133,7 @@ class BaseAction(ABC):
|
|
133
133
|
|
134
134
|
def _maybe_inject_last_result(self, kwargs: dict[str, Any]) -> dict[str, Any]:
|
135
135
|
if self.inject_last_result and self.shared_context:
|
136
|
-
key = self.
|
136
|
+
key = self.inject_into
|
137
137
|
if key in kwargs:
|
138
138
|
logger.warning("[%s] ⚠️ Overriding '%s' with last_result", self.name, key)
|
139
139
|
kwargs = dict(kwargs)
|
@@ -173,7 +173,7 @@ class Action(BaseAction):
|
|
173
173
|
kwargs (dict, optional): Static keyword arguments.
|
174
174
|
hooks (HookManager, optional): Hook manager for lifecycle events.
|
175
175
|
inject_last_result (bool, optional): Enable last_result injection.
|
176
|
-
|
176
|
+
inject_into (str, optional): Name of injected key.
|
177
177
|
retry (bool, optional): Enable retry logic.
|
178
178
|
retry_policy (RetryPolicy, optional): Retry settings.
|
179
179
|
"""
|
@@ -187,11 +187,11 @@ class Action(BaseAction):
|
|
187
187
|
kwargs: dict[str, Any] | None = None,
|
188
188
|
hooks: HookManager | None = None,
|
189
189
|
inject_last_result: bool = False,
|
190
|
-
|
190
|
+
inject_into: str = "last_result",
|
191
191
|
retry: bool = False,
|
192
192
|
retry_policy: RetryPolicy | None = None,
|
193
193
|
) -> None:
|
194
|
-
super().__init__(name, hooks, inject_last_result,
|
194
|
+
super().__init__(name, hooks, inject_last_result, inject_into)
|
195
195
|
self.action = action
|
196
196
|
self.rollback = rollback
|
197
197
|
self.args = args
|
@@ -257,7 +257,7 @@ class Action(BaseAction):
|
|
257
257
|
if context.result is not None:
|
258
258
|
logger.info("[%s] ✅ Recovered: %s", self.name, self.name)
|
259
259
|
return context.result
|
260
|
-
raise
|
260
|
+
raise
|
261
261
|
finally:
|
262
262
|
context.stop_timer()
|
263
263
|
await self.hooks.trigger(HookType.AFTER, context)
|
@@ -267,7 +267,7 @@ class Action(BaseAction):
|
|
267
267
|
async def preview(self, parent: Tree | None = None):
|
268
268
|
label = [f"[{OneColors.GREEN_b}]⚙ Action[/] '{self.name}'"]
|
269
269
|
if self.inject_last_result:
|
270
|
-
label.append(f" [dim](injects '{self.
|
270
|
+
label.append(f" [dim](injects '{self.inject_into}')[/dim]")
|
271
271
|
if self.retry_policy.enabled:
|
272
272
|
label.append(
|
273
273
|
f"\n[dim]↻ Retries:[/] {self.retry_policy.max_retries}x, "
|
@@ -413,7 +413,7 @@ class ChainedAction(BaseAction, ActionListMixin):
|
|
413
413
|
actions (list): List of actions or literals to execute.
|
414
414
|
hooks (HookManager, optional): Hooks for lifecycle events.
|
415
415
|
inject_last_result (bool, optional): Whether to inject last results into kwargs by default.
|
416
|
-
|
416
|
+
inject_into (str, optional): Key name for injection.
|
417
417
|
auto_inject (bool, optional): Auto-enable injection for subsequent actions.
|
418
418
|
return_list (bool, optional): Whether to return a list of all results. False returns the last result.
|
419
419
|
"""
|
@@ -424,11 +424,11 @@ class ChainedAction(BaseAction, ActionListMixin):
|
|
424
424
|
actions: list[BaseAction | Any] | None = None,
|
425
425
|
hooks: HookManager | None = None,
|
426
426
|
inject_last_result: bool = False,
|
427
|
-
|
427
|
+
inject_into: str = "last_result",
|
428
428
|
auto_inject: bool = False,
|
429
429
|
return_list: bool = False,
|
430
430
|
) -> None:
|
431
|
-
super().__init__(name, hooks, inject_last_result,
|
431
|
+
super().__init__(name, hooks, inject_last_result, inject_into)
|
432
432
|
ActionListMixin.__init__(self)
|
433
433
|
self.auto_inject = auto_inject
|
434
434
|
self.return_list = return_list
|
@@ -448,6 +448,8 @@ class ChainedAction(BaseAction, ActionListMixin):
|
|
448
448
|
if self.actions and self.auto_inject and not action.inject_last_result:
|
449
449
|
action.inject_last_result = True
|
450
450
|
super().add_action(action)
|
451
|
+
if hasattr(action, "register_teardown") and callable(action.register_teardown):
|
452
|
+
action.register_teardown(self.hooks)
|
451
453
|
|
452
454
|
async def _run(self, *args, **kwargs) -> list[Any]:
|
453
455
|
if not self.actions:
|
@@ -480,9 +482,7 @@ class ChainedAction(BaseAction, ActionListMixin):
|
|
480
482
|
last_result = shared_context.last_result()
|
481
483
|
try:
|
482
484
|
if self.requires_io_injection() and last_result is not None:
|
483
|
-
result = await prepared(
|
484
|
-
**{prepared.inject_last_result_as: last_result}
|
485
|
-
)
|
485
|
+
result = await prepared(**{prepared.inject_into: last_result})
|
486
486
|
else:
|
487
487
|
result = await prepared(*args, **updated_kwargs)
|
488
488
|
except Exception as error:
|
@@ -557,7 +557,7 @@ class ChainedAction(BaseAction, ActionListMixin):
|
|
557
557
|
async def preview(self, parent: Tree | None = None):
|
558
558
|
label = [f"[{OneColors.CYAN_b}]⛓ ChainedAction[/] '{self.name}'"]
|
559
559
|
if self.inject_last_result:
|
560
|
-
label.append(f" [dim](injects '{self.
|
560
|
+
label.append(f" [dim](injects '{self.inject_into}')[/dim]")
|
561
561
|
tree = parent.add("".join(label)) if parent else Tree("".join(label))
|
562
562
|
for action in self.actions:
|
563
563
|
await action.preview(parent=tree)
|
@@ -601,7 +601,7 @@ class ActionGroup(BaseAction, ActionListMixin):
|
|
601
601
|
actions (list): List of actions or literals to execute.
|
602
602
|
hooks (HookManager, optional): Hooks for lifecycle events.
|
603
603
|
inject_last_result (bool, optional): Whether to inject last results into kwargs by default.
|
604
|
-
|
604
|
+
inject_into (str, optional): Key name for injection.
|
605
605
|
"""
|
606
606
|
|
607
607
|
def __init__(
|
@@ -610,13 +610,29 @@ class ActionGroup(BaseAction, ActionListMixin):
|
|
610
610
|
actions: list[BaseAction] | None = None,
|
611
611
|
hooks: HookManager | None = None,
|
612
612
|
inject_last_result: bool = False,
|
613
|
-
|
613
|
+
inject_into: str = "last_result",
|
614
614
|
):
|
615
|
-
super().__init__(name, hooks, inject_last_result,
|
615
|
+
super().__init__(name, hooks, inject_last_result, inject_into)
|
616
616
|
ActionListMixin.__init__(self)
|
617
617
|
if actions:
|
618
618
|
self.set_actions(actions)
|
619
619
|
|
620
|
+
def _wrap_if_needed(self, action: BaseAction | Any) -> BaseAction:
|
621
|
+
if isinstance(action, BaseAction):
|
622
|
+
return action
|
623
|
+
elif callable(action):
|
624
|
+
return Action(name=action.__name__, action=action)
|
625
|
+
else:
|
626
|
+
raise TypeError(
|
627
|
+
f"ActionGroup only accepts BaseAction or callable, got {type(action).__name__}"
|
628
|
+
)
|
629
|
+
|
630
|
+
def add_action(self, action: BaseAction | Any) -> None:
|
631
|
+
action = self._wrap_if_needed(action)
|
632
|
+
super().add_action(action)
|
633
|
+
if hasattr(action, "register_teardown") and callable(action.register_teardown):
|
634
|
+
action.register_teardown(self.hooks)
|
635
|
+
|
620
636
|
async def _run(self, *args, **kwargs) -> list[tuple[str, Any]]:
|
621
637
|
shared_context = SharedContext(name=self.name, is_parallel=True)
|
622
638
|
if self.shared_context:
|
@@ -676,7 +692,7 @@ class ActionGroup(BaseAction, ActionListMixin):
|
|
676
692
|
async def preview(self, parent: Tree | None = None):
|
677
693
|
label = [f"[{OneColors.MAGENTA_b}]⏩ ActionGroup (parallel)[/] '{self.name}'"]
|
678
694
|
if self.inject_last_result:
|
679
|
-
label.append(f" [dim](receives '{self.
|
695
|
+
label.append(f" [dim](receives '{self.inject_into}')[/dim]")
|
680
696
|
tree = parent.add("".join(label)) if parent else Tree("".join(label))
|
681
697
|
actions = self.actions.copy()
|
682
698
|
random.shuffle(actions)
|
@@ -708,7 +724,7 @@ class ProcessAction(BaseAction):
|
|
708
724
|
hooks (HookManager, optional): Hook manager for lifecycle events.
|
709
725
|
executor (ProcessPoolExecutor, optional): Custom executor if desired.
|
710
726
|
inject_last_result (bool, optional): Inject last result into the function.
|
711
|
-
|
727
|
+
inject_into (str, optional): Name of the injected key.
|
712
728
|
"""
|
713
729
|
|
714
730
|
def __init__(
|
@@ -720,9 +736,9 @@ class ProcessAction(BaseAction):
|
|
720
736
|
hooks: HookManager | None = None,
|
721
737
|
executor: ProcessPoolExecutor | None = None,
|
722
738
|
inject_last_result: bool = False,
|
723
|
-
|
739
|
+
inject_into: str = "last_result",
|
724
740
|
):
|
725
|
-
super().__init__(name, hooks, inject_last_result,
|
741
|
+
super().__init__(name, hooks, inject_last_result, inject_into)
|
726
742
|
self.func = func
|
727
743
|
self.args = args
|
728
744
|
self.kwargs = kwargs or {}
|
@@ -782,7 +798,7 @@ class ProcessAction(BaseAction):
|
|
782
798
|
f"[{OneColors.DARK_YELLOW_b}]🧠 ProcessAction (new process)[/] '{self.name}'"
|
783
799
|
]
|
784
800
|
if self.inject_last_result:
|
785
|
-
label.append(f" [dim](injects '{self.
|
801
|
+
label.append(f" [dim](injects '{self.inject_into}')[/dim]")
|
786
802
|
if parent:
|
787
803
|
parent.add("".join(label))
|
788
804
|
else:
|
falyx/action_factory.py
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
from typing import Any
|
2
|
+
|
3
|
+
from rich.tree import Tree
|
4
|
+
|
5
|
+
from falyx.action import BaseAction
|
6
|
+
from falyx.context import ExecutionContext
|
7
|
+
from falyx.execution_registry import ExecutionRegistry as er
|
8
|
+
from falyx.hook_manager import HookType
|
9
|
+
from falyx.protocols import ActionFactoryProtocol
|
10
|
+
from falyx.themes.colors import OneColors
|
11
|
+
|
12
|
+
|
13
|
+
class ActionFactoryAction(BaseAction):
|
14
|
+
"""
|
15
|
+
Dynamically creates and runs another Action at runtime using a factory function.
|
16
|
+
|
17
|
+
This is useful for generating context-specific behavior (e.g., dynamic HTTPActions)
|
18
|
+
where the structure of the next action depends on runtime values.
|
19
|
+
|
20
|
+
Args:
|
21
|
+
name (str): Name of the action.
|
22
|
+
factory (Callable): A function that returns a BaseAction given args/kwargs.
|
23
|
+
inject_last_result (bool): Whether to inject last_result into the factory.
|
24
|
+
inject_into (str): The name of the kwarg to inject last_result as.
|
25
|
+
"""
|
26
|
+
|
27
|
+
def __init__(
|
28
|
+
self,
|
29
|
+
name: str,
|
30
|
+
factory: ActionFactoryProtocol,
|
31
|
+
*,
|
32
|
+
inject_last_result: bool = False,
|
33
|
+
inject_into: str = "last_result",
|
34
|
+
preview_args: tuple[Any, ...] = (),
|
35
|
+
preview_kwargs: dict[str, Any] = {},
|
36
|
+
):
|
37
|
+
super().__init__(
|
38
|
+
name=name,
|
39
|
+
inject_last_result=inject_last_result,
|
40
|
+
inject_into=inject_into,
|
41
|
+
)
|
42
|
+
self.factory = factory
|
43
|
+
self.preview_args = preview_args
|
44
|
+
self.preview_kwargs = preview_kwargs
|
45
|
+
|
46
|
+
async def _run(self, *args, **kwargs) -> Any:
|
47
|
+
updated_kwargs = self._maybe_inject_last_result(kwargs)
|
48
|
+
context = ExecutionContext(
|
49
|
+
name=f"{self.name} (factory)",
|
50
|
+
args=args,
|
51
|
+
kwargs=updated_kwargs,
|
52
|
+
action=self,
|
53
|
+
)
|
54
|
+
context.start_timer()
|
55
|
+
try:
|
56
|
+
await self.hooks.trigger(HookType.BEFORE, context)
|
57
|
+
generated_action = self.factory(*args, **updated_kwargs)
|
58
|
+
if not isinstance(generated_action, BaseAction):
|
59
|
+
raise TypeError(
|
60
|
+
f"[{self.name}] Factory must return a BaseAction, got {type(generated_action).__name__}"
|
61
|
+
)
|
62
|
+
if self.shared_context:
|
63
|
+
generated_action.set_shared_context(self.shared_context)
|
64
|
+
if self.options_manager:
|
65
|
+
generated_action.set_options_manager(self.options_manager)
|
66
|
+
context.result = await generated_action(*args, **kwargs)
|
67
|
+
await self.hooks.trigger(HookType.ON_SUCCESS, context)
|
68
|
+
return context.result
|
69
|
+
except Exception as error:
|
70
|
+
context.exception = error
|
71
|
+
await self.hooks.trigger(HookType.ON_ERROR, context)
|
72
|
+
raise
|
73
|
+
finally:
|
74
|
+
context.stop_timer()
|
75
|
+
await self.hooks.trigger(HookType.AFTER, context)
|
76
|
+
await self.hooks.trigger(HookType.ON_TEARDOWN, context)
|
77
|
+
er.record(context)
|
78
|
+
|
79
|
+
async def preview(self, parent: Tree | None = None):
|
80
|
+
label = f"[{OneColors.CYAN_b}]🏗️ ActionFactory[/] '{self.name}'"
|
81
|
+
tree = parent.add(label) if parent else Tree(label)
|
82
|
+
|
83
|
+
try:
|
84
|
+
generated = self.factory(*self.preview_args, **self.preview_kwargs)
|
85
|
+
if isinstance(generated, BaseAction):
|
86
|
+
await generated.preview(parent=tree)
|
87
|
+
else:
|
88
|
+
tree.add(
|
89
|
+
f"[{OneColors.DARK_RED}]⚠️ Factory did not return a BaseAction[/]"
|
90
|
+
)
|
91
|
+
except Exception as error:
|
92
|
+
tree.add(f"[{OneColors.DARK_RED}]⚠️ Preview failed: {error}[/]")
|
93
|
+
|
94
|
+
if not parent:
|
95
|
+
self.console.print(tree)
|
falyx/falyx.py
CHANGED
@@ -24,6 +24,7 @@ import logging
|
|
24
24
|
import sys
|
25
25
|
from argparse import Namespace
|
26
26
|
from difflib import get_close_matches
|
27
|
+
from enum import Enum
|
27
28
|
from functools import cached_property
|
28
29
|
from typing import Any, Callable
|
29
30
|
|
@@ -59,6 +60,13 @@ from falyx.utils import CaseInsensitiveDict, chunks, get_program_invocation, log
|
|
59
60
|
from falyx.version import __version__
|
60
61
|
|
61
62
|
|
63
|
+
class FalyxMode(str, Enum):
|
64
|
+
MENU = "menu"
|
65
|
+
RUN = "run"
|
66
|
+
PREVIEW = "preview"
|
67
|
+
RUN_ALL = "run-all"
|
68
|
+
|
69
|
+
|
62
70
|
class Falyx:
|
63
71
|
"""
|
64
72
|
Main menu controller for Falyx CLI applications.
|
@@ -148,7 +156,8 @@ class Falyx:
|
|
148
156
|
self.render_menu: Callable[["Falyx"], None] | None = render_menu
|
149
157
|
self.custom_table: Callable[["Falyx"], Table] | Table | None = custom_table
|
150
158
|
self.validate_options(cli_args, options)
|
151
|
-
self.
|
159
|
+
self._prompt_session: PromptSession | None = None
|
160
|
+
self.mode = FalyxMode.MENU
|
152
161
|
|
153
162
|
def validate_options(
|
154
163
|
self,
|
@@ -272,6 +281,11 @@ class Falyx:
|
|
272
281
|
)
|
273
282
|
|
274
283
|
self.console.print(table, justify="center")
|
284
|
+
if self.mode == FalyxMode.MENU:
|
285
|
+
self.console.print(
|
286
|
+
f"📦 Tip: Type '[{OneColors.LIGHT_YELLOW}]?[KEY][/]' to preview a command before running it.\n",
|
287
|
+
justify="center",
|
288
|
+
)
|
275
289
|
|
276
290
|
def _get_help_command(self) -> Command:
|
277
291
|
"""Returns the help command for the menu."""
|
@@ -329,7 +343,8 @@ class Falyx:
|
|
329
343
|
error_message = " ".join(message_lines)
|
330
344
|
|
331
345
|
def validator(text):
|
332
|
-
|
346
|
+
_, choice = self.get_command(text, from_validate=True)
|
347
|
+
return True if choice else False
|
333
348
|
|
334
349
|
return Validator.from_callable(
|
335
350
|
validator,
|
@@ -337,11 +352,11 @@ class Falyx:
|
|
337
352
|
move_cursor_to_end=True,
|
338
353
|
)
|
339
354
|
|
340
|
-
def
|
341
|
-
"""Forces the session to be recreated on the next access."""
|
342
|
-
if hasattr(self, "
|
343
|
-
del self.
|
344
|
-
self.
|
355
|
+
def _invalidate_prompt_session_cache(self):
|
356
|
+
"""Forces the prompt session to be recreated on the next access."""
|
357
|
+
if hasattr(self, "prompt_session"):
|
358
|
+
del self.prompt_session
|
359
|
+
self._prompt_session = None
|
345
360
|
|
346
361
|
def add_help_command(self):
|
347
362
|
"""Adds a help command to the menu if it doesn't already exist."""
|
@@ -375,7 +390,7 @@ class Falyx:
|
|
375
390
|
raise FalyxError(
|
376
391
|
"Bottom bar must be a string, callable, or BottomBar instance."
|
377
392
|
)
|
378
|
-
self.
|
393
|
+
self._invalidate_prompt_session_cache()
|
379
394
|
|
380
395
|
def _get_bottom_bar_render(self) -> Callable[[], Any] | str | None:
|
381
396
|
"""Returns the bottom bar for the menu."""
|
@@ -390,10 +405,10 @@ class Falyx:
|
|
390
405
|
return None
|
391
406
|
|
392
407
|
@cached_property
|
393
|
-
def
|
408
|
+
def prompt_session(self) -> PromptSession:
|
394
409
|
"""Returns the prompt session for the menu."""
|
395
|
-
if self.
|
396
|
-
self.
|
410
|
+
if self._prompt_session is None:
|
411
|
+
self._prompt_session = PromptSession(
|
397
412
|
message=self.prompt,
|
398
413
|
multiline=False,
|
399
414
|
completer=self._get_completer(),
|
@@ -402,7 +417,7 @@ class Falyx:
|
|
402
417
|
bottom_toolbar=self._get_bottom_bar_render(),
|
403
418
|
key_bindings=self.key_bindings,
|
404
419
|
)
|
405
|
-
return self.
|
420
|
+
return self._prompt_session
|
406
421
|
|
407
422
|
def register_all_hooks(self, hook_type: HookType, hooks: Hook | list[Hook]) -> None:
|
408
423
|
"""Registers hooks for all commands in the menu and actions recursively."""
|
@@ -668,17 +683,25 @@ class Falyx:
|
|
668
683
|
else:
|
669
684
|
return self.build_default_table()
|
670
685
|
|
671
|
-
def
|
686
|
+
def parse_preview_command(self, input_str: str) -> tuple[bool, str]:
|
687
|
+
if input_str.startswith("?"):
|
688
|
+
return True, input_str[1:].strip()
|
689
|
+
return False, input_str.strip()
|
690
|
+
|
691
|
+
def get_command(
|
692
|
+
self, choice: str, from_validate=False
|
693
|
+
) -> tuple[bool, Command | None]:
|
672
694
|
"""Returns the selected command based on user input. Supports keys, aliases, and abbreviations."""
|
695
|
+
is_preview, choice = self.parse_preview_command(choice)
|
673
696
|
choice = choice.upper()
|
674
697
|
name_map = self._name_map
|
675
698
|
|
676
699
|
if choice in name_map:
|
677
|
-
return name_map[choice]
|
700
|
+
return is_preview, name_map[choice]
|
678
701
|
|
679
702
|
prefix_matches = [cmd for key, cmd in name_map.items() if key.startswith(choice)]
|
680
703
|
if len(prefix_matches) == 1:
|
681
|
-
return prefix_matches[0]
|
704
|
+
return is_preview, prefix_matches[0]
|
682
705
|
|
683
706
|
fuzzy_matches = get_close_matches(choice, list(name_map.keys()), n=3, cutoff=0.7)
|
684
707
|
if fuzzy_matches:
|
@@ -694,7 +717,7 @@ class Falyx:
|
|
694
717
|
self.console.print(
|
695
718
|
f"[{OneColors.LIGHT_YELLOW}]⚠️ Unknown command '{choice}'[/]"
|
696
719
|
)
|
697
|
-
return None
|
720
|
+
return is_preview, None
|
698
721
|
|
699
722
|
def _create_context(self, selected_command: Command) -> ExecutionContext:
|
700
723
|
"""Creates a context dictionary for the selected command."""
|
@@ -717,12 +740,17 @@ class Falyx:
|
|
717
740
|
|
718
741
|
async def process_command(self) -> bool:
|
719
742
|
"""Processes the action of the selected command."""
|
720
|
-
choice = await self.
|
721
|
-
selected_command = self.get_command(choice)
|
743
|
+
choice = await self.prompt_session.prompt_async()
|
744
|
+
is_preview, selected_command = self.get_command(choice)
|
722
745
|
if not selected_command:
|
723
746
|
logger.info(f"Invalid command '{choice}'.")
|
724
747
|
return True
|
725
748
|
|
749
|
+
if is_preview:
|
750
|
+
logger.info(f"Preview command '{selected_command.key}' selected.")
|
751
|
+
await selected_command.preview()
|
752
|
+
return True
|
753
|
+
|
726
754
|
if selected_command.requires_input:
|
727
755
|
program = get_program_invocation()
|
728
756
|
self.console.print(
|
@@ -759,7 +787,7 @@ class Falyx:
|
|
759
787
|
async def run_key(self, command_key: str, return_context: bool = False) -> Any:
|
760
788
|
"""Run a command by key without displaying the menu (non-interactive mode)."""
|
761
789
|
self.debug_hooks()
|
762
|
-
selected_command = self.get_command(command_key)
|
790
|
+
_, selected_command = self.get_command(command_key)
|
763
791
|
self.last_run_command = selected_command
|
764
792
|
|
765
793
|
if not selected_command:
|
@@ -899,7 +927,8 @@ class Falyx:
|
|
899
927
|
sys.exit(0)
|
900
928
|
|
901
929
|
if self.cli_args.command == "preview":
|
902
|
-
|
930
|
+
self.mode = FalyxMode.PREVIEW
|
931
|
+
_, command = self.get_command(self.cli_args.name)
|
903
932
|
if not command:
|
904
933
|
self.console.print(
|
905
934
|
f"[{OneColors.DARK_RED}]❌ Command '{self.cli_args.name}' not found.[/]"
|
@@ -912,7 +941,8 @@ class Falyx:
|
|
912
941
|
sys.exit(0)
|
913
942
|
|
914
943
|
if self.cli_args.command == "run":
|
915
|
-
|
944
|
+
self.mode = FalyxMode.RUN
|
945
|
+
_, command = self.get_command(self.cli_args.name)
|
916
946
|
if not command:
|
917
947
|
self.console.print(
|
918
948
|
f"[{OneColors.DARK_RED}]❌ Command '{self.cli_args.name}' not found.[/]"
|
@@ -927,6 +957,7 @@ class Falyx:
|
|
927
957
|
sys.exit(0)
|
928
958
|
|
929
959
|
if self.cli_args.command == "run-all":
|
960
|
+
self.mode = FalyxMode.RUN_ALL
|
930
961
|
matching = [
|
931
962
|
cmd
|
932
963
|
for cmd in self.commands.values()
|
falyx/http_action.py
CHANGED
@@ -15,6 +15,7 @@ from rich.tree import Tree
|
|
15
15
|
|
16
16
|
from falyx.action import Action
|
17
17
|
from falyx.context import ExecutionContext, SharedContext
|
18
|
+
from falyx.hook_manager import HookManager, HookType
|
18
19
|
from falyx.themes.colors import OneColors
|
19
20
|
from falyx.utils import logger
|
20
21
|
|
@@ -55,7 +56,7 @@ class HTTPAction(Action):
|
|
55
56
|
data (Any, optional): Raw data or form-encoded body.
|
56
57
|
hooks (HookManager, optional): Hook manager for lifecycle events.
|
57
58
|
inject_last_result (bool): Enable last_result injection.
|
58
|
-
|
59
|
+
inject_into (str): Name of injected key.
|
59
60
|
retry (bool): Enable retry logic.
|
60
61
|
retry_policy (RetryPolicy): Retry settings.
|
61
62
|
"""
|
@@ -73,7 +74,7 @@ class HTTPAction(Action):
|
|
73
74
|
data: Any = None,
|
74
75
|
hooks=None,
|
75
76
|
inject_last_result: bool = False,
|
76
|
-
|
77
|
+
inject_into: str = "last_result",
|
77
78
|
retry: bool = False,
|
78
79
|
retry_policy=None,
|
79
80
|
):
|
@@ -91,13 +92,12 @@ class HTTPAction(Action):
|
|
91
92
|
kwargs={},
|
92
93
|
hooks=hooks,
|
93
94
|
inject_last_result=inject_last_result,
|
94
|
-
|
95
|
+
inject_into=inject_into,
|
95
96
|
retry=retry,
|
96
97
|
retry_policy=retry_policy,
|
97
98
|
)
|
98
99
|
|
99
100
|
async def _request(self, *args, **kwargs) -> dict[str, Any]:
|
100
|
-
# TODO: Add check for HOOK registration
|
101
101
|
if self.shared_context:
|
102
102
|
context: SharedContext = self.shared_context
|
103
103
|
session = context.get("http_session")
|
@@ -128,6 +128,9 @@ class HTTPAction(Action):
|
|
128
128
|
if not self.shared_context:
|
129
129
|
await session.close()
|
130
130
|
|
131
|
+
def register_teardown(self, hooks: HookManager):
|
132
|
+
hooks.register(HookType.ON_TEARDOWN, close_shared_http_session)
|
133
|
+
|
131
134
|
async def preview(self, parent: Tree | None = None):
|
132
135
|
label = [
|
133
136
|
f"[{OneColors.CYAN_b}]🌐 HTTPAction[/] '{self.name}'",
|
@@ -135,7 +138,7 @@ class HTTPAction(Action):
|
|
135
138
|
f"\n[dim]URL:[/] {self.url}",
|
136
139
|
]
|
137
140
|
if self.inject_last_result:
|
138
|
-
label.append(f"\n[dim]Injects:[/] '{self.
|
141
|
+
label.append(f"\n[dim]Injects:[/] '{self.inject_into}'")
|
139
142
|
if self.retry_policy and self.retry_policy.enabled:
|
140
143
|
label.append(
|
141
144
|
f"\n[dim]↻ Retries:[/] {self.retry_policy.max_retries}x, "
|
falyx/init.py
CHANGED
@@ -33,8 +33,10 @@ async def cleanup():
|
|
33
33
|
"""
|
34
34
|
|
35
35
|
GLOBAL_CONFIG = """\
|
36
|
-
|
37
|
-
|
36
|
+
- key: C
|
37
|
+
description: Cleanup temp files
|
38
|
+
action: tasks.cleanup
|
39
|
+
aliases: [clean, cleanup]
|
38
40
|
"""
|
39
41
|
|
40
42
|
console = Console(color_system="auto")
|
falyx/io_action.py
CHANGED
@@ -83,7 +83,7 @@ class BaseIOAction(BaseAction):
|
|
83
83
|
raise NotImplementedError
|
84
84
|
|
85
85
|
async def _resolve_input(self, kwargs: dict[str, Any]) -> str | bytes:
|
86
|
-
last_result = kwargs.pop(self.
|
86
|
+
last_result = kwargs.pop(self.inject_into, None)
|
87
87
|
|
88
88
|
data = await self._read_stdin()
|
89
89
|
if data:
|
@@ -168,7 +168,7 @@ class BaseIOAction(BaseAction):
|
|
168
168
|
async def preview(self, parent: Tree | None = None):
|
169
169
|
label = [f"[{OneColors.GREEN_b}]⚙ IOAction[/] '{self.name}'"]
|
170
170
|
if self.inject_last_result:
|
171
|
-
label.append(f" [dim](injects '{self.
|
171
|
+
label.append(f" [dim](injects '{self.inject_into}')[/dim]")
|
172
172
|
if parent:
|
173
173
|
parent.add("".join(label))
|
174
174
|
else:
|
@@ -243,7 +243,7 @@ class ShellAction(BaseIOAction):
|
|
243
243
|
async def preview(self, parent: Tree | None = None):
|
244
244
|
label = [f"[{OneColors.GREEN_b}]⚙ ShellAction[/] '{self.name}'"]
|
245
245
|
if self.inject_last_result:
|
246
|
-
label.append(f" [dim](injects '{self.
|
246
|
+
label.append(f" [dim](injects '{self.inject_into}')[/dim]")
|
247
247
|
if parent:
|
248
248
|
parent.add("".join(label))
|
249
249
|
else:
|
falyx/menu_action.py
CHANGED
@@ -101,7 +101,7 @@ class MenuAction(BaseAction):
|
|
101
101
|
prompt_message: str = "Select > ",
|
102
102
|
default_selection: str = "",
|
103
103
|
inject_last_result: bool = False,
|
104
|
-
|
104
|
+
inject_into: str = "last_result",
|
105
105
|
console: Console | None = None,
|
106
106
|
prompt_session: PromptSession | None = None,
|
107
107
|
never_prompt: bool = False,
|
@@ -111,7 +111,7 @@ class MenuAction(BaseAction):
|
|
111
111
|
super().__init__(
|
112
112
|
name,
|
113
113
|
inject_last_result=inject_last_result,
|
114
|
-
|
114
|
+
inject_into=inject_into,
|
115
115
|
never_prompt=never_prompt,
|
116
116
|
)
|
117
117
|
self.menu_options = menu_options
|
@@ -168,15 +168,13 @@ class MenuAction(BaseAction):
|
|
168
168
|
await self.hooks.trigger(HookType.BEFORE, context)
|
169
169
|
key = effective_default
|
170
170
|
if not self.never_prompt:
|
171
|
-
console = self.console
|
172
|
-
session = self.prompt_session
|
173
171
|
table = self._build_table()
|
174
172
|
key = await prompt_for_selection(
|
175
173
|
self.menu_options.keys(),
|
176
174
|
table,
|
177
175
|
default_selection=self.default_selection,
|
178
|
-
console=console,
|
179
|
-
|
176
|
+
console=self.console,
|
177
|
+
prompt_session=self.prompt_session,
|
180
178
|
prompt_message=self.prompt_message,
|
181
179
|
show_table=self.show_table,
|
182
180
|
)
|
falyx/prompt_utils.py
CHANGED
@@ -9,11 +9,10 @@ def should_prompt_user(
|
|
9
9
|
):
|
10
10
|
"""Determine whether to prompt the user for confirmation based on command and global options."""
|
11
11
|
never_prompt = options.get("never_prompt", False, namespace)
|
12
|
-
always_confirm = options.get("always_confirm", False, namespace)
|
13
12
|
force_confirm = options.get("force_confirm", False, namespace)
|
14
13
|
skip_confirm = options.get("skip_confirm", False, namespace)
|
15
14
|
|
16
15
|
if never_prompt or skip_confirm:
|
17
16
|
return False
|
18
17
|
|
19
|
-
return confirm or
|
18
|
+
return confirm or force_confirm
|
falyx/protocols.py
ADDED
falyx/select_files_action.py
CHANGED
@@ -10,7 +10,7 @@ class SelectFilesAction(BaseAction):
|
|
10
10
|
suffix_filter: str | None = None,
|
11
11
|
return_path: bool = True,
|
12
12
|
console: Console | None = None,
|
13
|
-
|
13
|
+
prompt_session: PromptSession | None = None,
|
14
14
|
):
|
15
15
|
super().__init__(name)
|
16
16
|
self.directory = Path(directory).resolve()
|
@@ -20,7 +20,7 @@ class SelectFilesAction(BaseAction):
|
|
20
20
|
self.style = style
|
21
21
|
self.return_path = return_path
|
22
22
|
self.console = console or Console()
|
23
|
-
self.
|
23
|
+
self.prompt_session = prompt_session or PromptSession()
|
24
24
|
|
25
25
|
async def _run(self, *args, **kwargs) -> Any:
|
26
26
|
context = ExecutionContext(name=self.name, args=args, kwargs=kwargs, action=self)
|
@@ -49,7 +49,7 @@ class SelectFilesAction(BaseAction):
|
|
49
49
|
options.keys(),
|
50
50
|
table,
|
51
51
|
console=self.console,
|
52
|
-
|
52
|
+
prompt_session=self.prompt_session,
|
53
53
|
prompt_message=self.prompt_message,
|
54
54
|
)
|
55
55
|
|
falyx/selection.py
CHANGED
@@ -203,17 +203,17 @@ async def prompt_for_index(
|
|
203
203
|
min_index: int = 0,
|
204
204
|
default_selection: str = "",
|
205
205
|
console: Console | None = None,
|
206
|
-
|
206
|
+
prompt_session: PromptSession | None = None,
|
207
207
|
prompt_message: str = "Select an option > ",
|
208
208
|
show_table: bool = True,
|
209
209
|
):
|
210
|
-
|
210
|
+
prompt_session = prompt_session or PromptSession()
|
211
211
|
console = console or Console(color_system="auto")
|
212
212
|
|
213
213
|
if show_table:
|
214
214
|
console.print(table)
|
215
215
|
|
216
|
-
selection = await
|
216
|
+
selection = await prompt_session.prompt_async(
|
217
217
|
message=prompt_message,
|
218
218
|
validator=int_range_validator(min_index, max_index),
|
219
219
|
default=default_selection,
|
@@ -226,18 +226,18 @@ async def prompt_for_selection(
|
|
226
226
|
table: Table,
|
227
227
|
default_selection: str = "",
|
228
228
|
console: Console | None = None,
|
229
|
-
|
229
|
+
prompt_session: PromptSession | None = None,
|
230
230
|
prompt_message: str = "Select an option > ",
|
231
231
|
show_table: bool = True,
|
232
232
|
) -> str:
|
233
233
|
"""Prompt the user to select a key from a set of options. Return the selected key."""
|
234
|
-
|
234
|
+
prompt_session = prompt_session or PromptSession()
|
235
235
|
console = console or Console(color_system="auto")
|
236
236
|
|
237
237
|
if show_table:
|
238
238
|
console.print(table, justify="center")
|
239
239
|
|
240
|
-
selected = await
|
240
|
+
selected = await prompt_session.prompt_async(
|
241
241
|
message=prompt_message,
|
242
242
|
validator=key_validator(keys),
|
243
243
|
default=default_selection,
|
@@ -250,7 +250,7 @@ async def select_value_from_list(
|
|
250
250
|
title: str,
|
251
251
|
selections: Sequence[str],
|
252
252
|
console: Console | None = None,
|
253
|
-
|
253
|
+
prompt_session: PromptSession | None = None,
|
254
254
|
prompt_message: str = "Select an option > ",
|
255
255
|
default_selection: str = "",
|
256
256
|
columns: int = 4,
|
@@ -283,7 +283,7 @@ async def select_value_from_list(
|
|
283
283
|
caption_style,
|
284
284
|
highlight,
|
285
285
|
)
|
286
|
-
|
286
|
+
prompt_session = prompt_session or PromptSession()
|
287
287
|
console = console or Console(color_system="auto")
|
288
288
|
|
289
289
|
selection_index = await prompt_for_index(
|
@@ -291,7 +291,7 @@ async def select_value_from_list(
|
|
291
291
|
table,
|
292
292
|
default_selection=default_selection,
|
293
293
|
console=console,
|
294
|
-
|
294
|
+
prompt_session=prompt_session,
|
295
295
|
prompt_message=prompt_message,
|
296
296
|
)
|
297
297
|
|
@@ -302,12 +302,12 @@ async def select_key_from_dict(
|
|
302
302
|
selections: dict[str, SelectionOption],
|
303
303
|
table: Table,
|
304
304
|
console: Console | None = None,
|
305
|
-
|
305
|
+
prompt_session: PromptSession | None = None,
|
306
306
|
prompt_message: str = "Select an option > ",
|
307
307
|
default_selection: str = "",
|
308
308
|
) -> Any:
|
309
309
|
"""Prompt for a key from a dict, returns the key."""
|
310
|
-
|
310
|
+
prompt_session = prompt_session or PromptSession()
|
311
311
|
console = console or Console(color_system="auto")
|
312
312
|
|
313
313
|
console.print(table)
|
@@ -317,7 +317,7 @@ async def select_key_from_dict(
|
|
317
317
|
table,
|
318
318
|
default_selection=default_selection,
|
319
319
|
console=console,
|
320
|
-
|
320
|
+
prompt_session=prompt_session,
|
321
321
|
prompt_message=prompt_message,
|
322
322
|
)
|
323
323
|
|
@@ -326,12 +326,12 @@ async def select_value_from_dict(
|
|
326
326
|
selections: dict[str, SelectionOption],
|
327
327
|
table: Table,
|
328
328
|
console: Console | None = None,
|
329
|
-
|
329
|
+
prompt_session: PromptSession | None = None,
|
330
330
|
prompt_message: str = "Select an option > ",
|
331
331
|
default_selection: str = "",
|
332
332
|
) -> Any:
|
333
333
|
"""Prompt for a key from a dict, but return the value."""
|
334
|
-
|
334
|
+
prompt_session = prompt_session or PromptSession()
|
335
335
|
console = console or Console(color_system="auto")
|
336
336
|
|
337
337
|
console.print(table)
|
@@ -341,7 +341,7 @@ async def select_value_from_dict(
|
|
341
341
|
table,
|
342
342
|
default_selection=default_selection,
|
343
343
|
console=console,
|
344
|
-
|
344
|
+
prompt_session=prompt_session,
|
345
345
|
prompt_message=prompt_message,
|
346
346
|
)
|
347
347
|
|
@@ -352,7 +352,7 @@ async def get_selection_from_dict_menu(
|
|
352
352
|
title: str,
|
353
353
|
selections: dict[str, SelectionOption],
|
354
354
|
console: Console | None = None,
|
355
|
-
|
355
|
+
prompt_session: PromptSession | None = None,
|
356
356
|
prompt_message: str = "Select an option > ",
|
357
357
|
default_selection: str = "",
|
358
358
|
):
|
@@ -366,7 +366,7 @@ async def get_selection_from_dict_menu(
|
|
366
366
|
selections,
|
367
367
|
table,
|
368
368
|
console,
|
369
|
-
|
369
|
+
prompt_session,
|
370
370
|
prompt_message,
|
371
371
|
default_selection,
|
372
372
|
)
|
falyx/selection_action.py
CHANGED
@@ -26,24 +26,24 @@ class SelectionAction(BaseAction):
|
|
26
26
|
def __init__(
|
27
27
|
self,
|
28
28
|
name: str,
|
29
|
-
selections: list[str] | dict[str, SelectionOption],
|
29
|
+
selections: list[str] | set[str] | tuple[str, ...] | dict[str, SelectionOption],
|
30
30
|
*,
|
31
31
|
title: str = "Select an option",
|
32
32
|
columns: int = 2,
|
33
33
|
prompt_message: str = "Select > ",
|
34
34
|
default_selection: str = "",
|
35
35
|
inject_last_result: bool = False,
|
36
|
-
|
36
|
+
inject_into: str = "last_result",
|
37
37
|
return_key: bool = False,
|
38
38
|
console: Console | None = None,
|
39
|
-
|
39
|
+
prompt_session: PromptSession | None = None,
|
40
40
|
never_prompt: bool = False,
|
41
41
|
show_table: bool = True,
|
42
42
|
):
|
43
43
|
super().__init__(
|
44
44
|
name,
|
45
45
|
inject_last_result=inject_last_result,
|
46
|
-
|
46
|
+
inject_into=inject_into,
|
47
47
|
never_prompt=never_prompt,
|
48
48
|
)
|
49
49
|
self.selections: list[str] | CaseInsensitiveDict = selections
|
@@ -51,7 +51,7 @@ class SelectionAction(BaseAction):
|
|
51
51
|
self.title = title
|
52
52
|
self.columns = columns
|
53
53
|
self.console = console or Console(color_system="auto")
|
54
|
-
self.
|
54
|
+
self.prompt_session = prompt_session or PromptSession()
|
55
55
|
self.default_selection = default_selection
|
56
56
|
self.prompt_message = prompt_message
|
57
57
|
self.show_table = show_table
|
@@ -61,9 +61,11 @@ class SelectionAction(BaseAction):
|
|
61
61
|
return self._selections
|
62
62
|
|
63
63
|
@selections.setter
|
64
|
-
def selections(
|
65
|
-
|
66
|
-
|
64
|
+
def selections(
|
65
|
+
self, value: list[str] | set[str] | tuple[str, ...] | dict[str, SelectionOption]
|
66
|
+
):
|
67
|
+
if isinstance(value, (list, tuple, set)):
|
68
|
+
self._selections: list[str] | CaseInsensitiveDict = list(value)
|
67
69
|
elif isinstance(value, dict):
|
68
70
|
cid = CaseInsensitiveDict()
|
69
71
|
cid.update(value)
|
@@ -123,7 +125,7 @@ class SelectionAction(BaseAction):
|
|
123
125
|
table,
|
124
126
|
default_selection=effective_default,
|
125
127
|
console=self.console,
|
126
|
-
|
128
|
+
prompt_session=self.prompt_session,
|
127
129
|
prompt_message=self.prompt_message,
|
128
130
|
show_table=self.show_table,
|
129
131
|
)
|
@@ -140,7 +142,7 @@ class SelectionAction(BaseAction):
|
|
140
142
|
table,
|
141
143
|
default_selection=effective_default,
|
142
144
|
console=self.console,
|
143
|
-
|
145
|
+
prompt_session=self.prompt_session,
|
144
146
|
prompt_message=self.prompt_message,
|
145
147
|
show_table=self.show_table,
|
146
148
|
)
|
falyx/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.1.
|
1
|
+
__version__ = "0.1.20"
|
@@ -1,8 +1,8 @@
|
|
1
|
-
falyx/.coverage,sha256=DNx1Ew1vSvuIcKko7httsyL62erJxVQ6CKtuJKxRVj4,53248
|
2
1
|
falyx/.pytyped,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
2
|
falyx/__init__.py,sha256=dYRamQJlT1Zoy5Uu1uG4NCV05Xk98nN1LAQrSR1CT2A,643
|
4
3
|
falyx/__main__.py,sha256=pXxXLlDot33dc4mR11Njpr4M_xbSTdKEqKWMS2aUqfk,2195
|
5
|
-
falyx/action.py,sha256=
|
4
|
+
falyx/action.py,sha256=vqWJfdywTQZyWgplbm1ilMtEh3DpOGlx2-pawe-hl7U,31694
|
5
|
+
falyx/action_factory.py,sha256=SMucCBuigKk3rlKXCEN69Sew4dVaBUxQqxyUUAHMZeo,3629
|
6
6
|
falyx/bottom_bar.py,sha256=83KSElBU7sFJqUhKyfef6gYfPnNDM8V7bph60cY5ARQ,7384
|
7
7
|
falyx/command.py,sha256=8Db_A3WDxmFNuZUb4_PO0UlpnfZFAUUEFkgC7B8v1Jk,11891
|
8
8
|
falyx/config.py,sha256=czt_EjOCT0lzWcoRE2F-oS2k1AVBFdiNuTcQXHlUVD0,4534
|
@@ -10,30 +10,31 @@ falyx/context.py,sha256=Dm7HV-eigU-aTv5ERah6Ow9fIRdrOsB1G6ETPIu42Gw,10070
|
|
10
10
|
falyx/debug.py,sha256=-jbTti29UC5zP9qQlWs3TbkOQR2f3zKSuNluh-r56wY,1551
|
11
11
|
falyx/exceptions.py,sha256=YVbhPp2BNvZoO_xqeGSRKHVQ2rdLOLf1HCjH4JTj9w8,776
|
12
12
|
falyx/execution_registry.py,sha256=xB2SJuEoDxxfwUmKXLAZQSrVoNPXwnVML98sTgwBqRI,2869
|
13
|
-
falyx/falyx.py,sha256=
|
13
|
+
falyx/falyx.py,sha256=xXRvl3TzfmtRIEdDj-xesmu0Y5Txf57pUAYpq40UYRo,39682
|
14
14
|
falyx/hook_manager.py,sha256=E9Vk4bdoUTeXPQ_BQEvY2Jt-jUAusc40LI8JDy3NLUw,2381
|
15
15
|
falyx/hooks.py,sha256=9zXk62DsJLJrmwTdyeNy5s-rVRvl8feuYRrfMmz6cVQ,2802
|
16
|
-
falyx/http_action.py,sha256=
|
17
|
-
falyx/init.py,sha256
|
18
|
-
falyx/io_action.py,sha256=
|
19
|
-
falyx/menu_action.py,sha256=
|
16
|
+
falyx/http_action.py,sha256=JfopEleXJ0goVHi0VCn983c22GrmJhobnPIP7sTRqzU,5796
|
17
|
+
falyx/init.py,sha256=jP4ZNw7ycDMKw4n1HDifxWSa0NYHaGLq7_LiFt85NpA,1832
|
18
|
+
falyx/io_action.py,sha256=IT7jDbucZbMxqcIotb1X4GmYXt6uXGMszy1hxAK_e90,10632
|
19
|
+
falyx/menu_action.py,sha256=UfJStuOM8LMauTRFcZfKLvornfYBuZZza-EK9CQ0edE,7969
|
20
20
|
falyx/options_manager.py,sha256=yYpn-moYN-bRYgMLccmi_de4mUzhTT7cv_bR2FFWZ8c,2798
|
21
21
|
falyx/parsers.py,sha256=Ki0rn2wryPDmMI9WUNBLQ5J5Y64BNten0POMZM8wPKU,5189
|
22
|
-
falyx/prompt_utils.py,sha256=
|
22
|
+
falyx/prompt_utils.py,sha256=JOg3p8Juv6ZdY1srfy_HlMNYfE-ajggDWLqNsjZq87I,560
|
23
|
+
falyx/protocols.py,sha256=yNtQEugq9poN-SbOJf5LL_j6HBWdglbTNghpyopLpTs,216
|
23
24
|
falyx/retry.py,sha256=GncBUiDDfDHUvLsWsWQw2Nq2XYL0TR0Fne3iXPzvQ48,3551
|
24
25
|
falyx/retry_utils.py,sha256=SN5apcsg71IG2-KylysqdJd-PkPBLoCVwsgrSTF9wrQ,666
|
25
|
-
falyx/select_files_action.py,sha256=
|
26
|
-
falyx/selection.py,sha256=
|
27
|
-
falyx/selection_action.py,sha256=
|
26
|
+
falyx/select_files_action.py,sha256=aqh7Ezb0TVfvwskY3p_OtUjfN06KF8jRHGuNuq5RpUQ,2444
|
27
|
+
falyx/selection.py,sha256=Hi8vfu6IuKdZ7URLiavb3uD1_Gb50D8XoKpZwAHLjmE,9859
|
28
|
+
falyx/selection_action.py,sha256=hWsfyRO0cn6Z-sBeDYNTJKZq8CCBxY2GY917U7a8Uo0,8258
|
28
29
|
falyx/signal_action.py,sha256=wfhW9miSUj9MUoc1WOyk4tU9CtYKAXusHxQdBPYLoyQ,829
|
29
30
|
falyx/signals.py,sha256=tlUbz3x6z3rYlUggan_Ntoy4bU5RbOd8UfR4cNcV6kQ,694
|
30
31
|
falyx/tagged_table.py,sha256=sn2kosRRpcpeMB8vKk47c9yjpffSz_9FXH_e6kw15mA,1019
|
31
32
|
falyx/themes/colors.py,sha256=4aaeAHJetmeNInI0Zytg4E3YqKfPFelpf04vtjSvsS8,19776
|
32
33
|
falyx/utils.py,sha256=b1GQ3ooz4Io3zPE7MsoDm7j42AioTG-ZcWH-N2TRpbI,7710
|
33
34
|
falyx/validators.py,sha256=NMxqCk8Fr8HQGVDYpg8B_JRk5SKR41E_G9gj1YfQnxg,1316
|
34
|
-
falyx/version.py,sha256=
|
35
|
-
falyx-0.1.
|
36
|
-
falyx-0.1.
|
37
|
-
falyx-0.1.
|
38
|
-
falyx-0.1.
|
39
|
-
falyx-0.1.
|
35
|
+
falyx/version.py,sha256=8XalsVoLEfXslFvdtUEmkNOuYShzOzYOcFbgmOz1oSk,23
|
36
|
+
falyx-0.1.20.dist-info/LICENSE,sha256=B0yqgaHuSdhN7T3OBmgQSiDTy8HqT5Oe_dLypRe4Ra4,1073
|
37
|
+
falyx-0.1.20.dist-info/METADATA,sha256=zSkzjuSPukAX2JukaxG18mqDOSzQlb9vAEW-E2QH8Ds,5484
|
38
|
+
falyx-0.1.20.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
39
|
+
falyx-0.1.20.dist-info/entry_points.txt,sha256=j8owOSl2j1Ss8DtGMnKfgehKaolqnIPhVFHaUBLUnMs,45
|
40
|
+
falyx-0.1.20.dist-info/RECORD,,
|
falyx/.coverage
DELETED
Binary file
|
File without changes
|
File without changes
|
File without changes
|