falyx 0.1.41__tar.gz → 0.1.43__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.41 → falyx-0.1.43}/PKG-INFO +1 -1
- {falyx-0.1.41 → falyx-0.1.43}/falyx/__main__.py +45 -2
- {falyx-0.1.41 → falyx-0.1.43}/falyx/command.py +3 -1
- {falyx-0.1.41 → falyx-0.1.43}/falyx/falyx.py +25 -6
- {falyx-0.1.41 → falyx-0.1.43}/falyx/parsers/__init__.py +3 -1
- {falyx-0.1.41 → falyx-0.1.43}/falyx/parsers/parsers.py +77 -14
- falyx-0.1.43/falyx/version.py +1 -0
- {falyx-0.1.41 → falyx-0.1.43}/pyproject.toml +1 -1
- falyx-0.1.41/falyx/version.py +0 -1
- {falyx-0.1.41 → falyx-0.1.43}/LICENSE +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/README.md +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/.pytyped +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/__init__.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/.pytyped +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/__init__.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/action.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/action_factory.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/action_group.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/base.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/chained_action.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/fallback_action.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/http_action.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/io_action.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/literal_input_action.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/menu_action.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/mixins.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/process_action.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/process_pool_action.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/prompt_menu_action.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/select_file_action.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/selection_action.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/signal_action.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/types.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/action/user_input_action.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/bottom_bar.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/config.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/context.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/debug.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/exceptions.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/execution_registry.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/hook_manager.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/hooks.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/init.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/logger.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/menu.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/options_manager.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/parsers/.pytyped +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/parsers/argparse.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/parsers/signature.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/parsers/utils.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/prompt_utils.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/protocols.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/retry.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/retry_utils.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/selection.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/signals.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/tagged_table.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/themes/__init__.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/themes/colors.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/utils.py +0 -0
- {falyx-0.1.41 → falyx-0.1.43}/falyx/validators.py +0 -0
@@ -8,12 +8,13 @@ Licensed under the MIT License. See LICENSE file for details.
|
|
8
8
|
import asyncio
|
9
9
|
import os
|
10
10
|
import sys
|
11
|
+
from argparse import ArgumentParser, Namespace, _SubParsersAction
|
11
12
|
from pathlib import Path
|
12
13
|
from typing import Any
|
13
14
|
|
14
15
|
from falyx.config import loader
|
15
16
|
from falyx.falyx import Falyx
|
16
|
-
from falyx.parsers import CommandArgumentParser
|
17
|
+
from falyx.parsers import CommandArgumentParser, get_root_parser, get_subparsers
|
17
18
|
|
18
19
|
|
19
20
|
def find_falyx_config() -> Path | None:
|
@@ -48,6 +49,42 @@ def init_config(parser: CommandArgumentParser) -> None:
|
|
48
49
|
)
|
49
50
|
|
50
51
|
|
52
|
+
def init_callback(args: Namespace) -> None:
|
53
|
+
"""Callback for the init command."""
|
54
|
+
if args.command == "init":
|
55
|
+
from falyx.init import init_project
|
56
|
+
|
57
|
+
init_project(args.name)
|
58
|
+
elif args.command == "init_global":
|
59
|
+
from falyx.init import init_global
|
60
|
+
|
61
|
+
init_global()
|
62
|
+
|
63
|
+
|
64
|
+
def get_parsers() -> tuple[ArgumentParser, _SubParsersAction]:
|
65
|
+
root_parser: ArgumentParser = get_root_parser()
|
66
|
+
subparsers = get_subparsers(root_parser)
|
67
|
+
init_parser = subparsers.add_parser(
|
68
|
+
"init",
|
69
|
+
help="Initialize a new Falyx project",
|
70
|
+
description="Create a new Falyx project with mock configuration files.",
|
71
|
+
epilog="If no name is provided, the current directory will be used.",
|
72
|
+
)
|
73
|
+
init_parser.add_argument(
|
74
|
+
"name",
|
75
|
+
type=str,
|
76
|
+
help="Name of the new Falyx project",
|
77
|
+
default=".",
|
78
|
+
nargs="?",
|
79
|
+
)
|
80
|
+
subparsers.add_parser(
|
81
|
+
"init-global",
|
82
|
+
help="Initialize Falyx global configuration",
|
83
|
+
description="Create a global Falyx configuration at ~/.config/falyx/.",
|
84
|
+
)
|
85
|
+
return root_parser, subparsers
|
86
|
+
|
87
|
+
|
51
88
|
def main() -> Any:
|
52
89
|
bootstrap_path = bootstrap()
|
53
90
|
if not bootstrap_path:
|
@@ -60,17 +97,23 @@ def main() -> Any:
|
|
60
97
|
init_project,
|
61
98
|
aliases=["init"],
|
62
99
|
argument_config=init_config,
|
100
|
+
help_epilogue="If no name is provided, the current directory will be used.",
|
63
101
|
)
|
64
102
|
flx.add_command(
|
65
103
|
"G",
|
66
104
|
"Initialize Falyx global configuration",
|
67
105
|
init_global,
|
68
106
|
aliases=["init-global"],
|
107
|
+
help_text="Create a global Falyx configuration at ~/.config/falyx/.",
|
69
108
|
)
|
70
109
|
else:
|
71
110
|
flx = loader(bootstrap_path)
|
72
111
|
|
73
|
-
|
112
|
+
root_parser, subparsers = get_parsers()
|
113
|
+
|
114
|
+
return asyncio.run(
|
115
|
+
flx.run(root_parser=root_parser, subparsers=subparsers, callback=init_callback)
|
116
|
+
)
|
74
117
|
|
75
118
|
|
76
119
|
if __name__ == "__main__":
|
@@ -313,7 +313,9 @@ class Command(BaseModel):
|
|
313
313
|
if not self.arg_parser:
|
314
314
|
return "No arguments defined."
|
315
315
|
|
316
|
-
|
316
|
+
command_keys_text = self.arg_parser.get_command_keys_text(plain_text=True)
|
317
|
+
options_text = self.arg_parser.get_options_text(plain_text=True)
|
318
|
+
return f" {command_keys_text:<20} {options_text} "
|
317
319
|
|
318
320
|
def log_summary(self) -> None:
|
319
321
|
if self._context:
|
@@ -25,7 +25,7 @@ import asyncio
|
|
25
25
|
import logging
|
26
26
|
import shlex
|
27
27
|
import sys
|
28
|
-
from argparse import Namespace
|
28
|
+
from argparse import ArgumentParser, Namespace, _SubParsersAction
|
29
29
|
from difflib import get_close_matches
|
30
30
|
from enum import Enum
|
31
31
|
from functools import cached_property
|
@@ -830,10 +830,11 @@ class Falyx:
|
|
830
830
|
self.console.print(
|
831
831
|
f"[{OneColors.LIGHT_YELLOW}]⚠️ Unknown command '{choice}'[/]"
|
832
832
|
)
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
833
|
+
else:
|
834
|
+
raise ValidationError(
|
835
|
+
message=f"Unknown command '{choice}'.",
|
836
|
+
cursor_position=len(raw_choices),
|
837
|
+
)
|
837
838
|
return is_preview, None, args, kwargs
|
838
839
|
|
839
840
|
def _create_context(self, selected_command: Command) -> ExecutionContext:
|
@@ -1028,6 +1029,8 @@ class Falyx:
|
|
1028
1029
|
async def run(
|
1029
1030
|
self,
|
1030
1031
|
falyx_parsers: FalyxParsers | None = None,
|
1032
|
+
root_parser: ArgumentParser | None = None,
|
1033
|
+
subparsers: _SubParsersAction | None = None,
|
1031
1034
|
callback: Callable[..., Any] | None = None,
|
1032
1035
|
) -> None:
|
1033
1036
|
"""Run Falyx CLI with structured subcommands."""
|
@@ -1045,6 +1048,8 @@ class Falyx:
|
|
1045
1048
|
self.description,
|
1046
1049
|
self.epilog,
|
1047
1050
|
commands=self.commands,
|
1051
|
+
root_parser=root_parser,
|
1052
|
+
subparsers=subparsers,
|
1048
1053
|
)
|
1049
1054
|
self.cli_args = falyx_parsers.parse_args()
|
1050
1055
|
self.options.from_namespace(self.cli_args, "cli_args")
|
@@ -1149,9 +1154,23 @@ class Falyx:
|
|
1149
1154
|
f"[{OneColors.CYAN_b}]🚀 Running all commands with tag:[/] "
|
1150
1155
|
f"{self.cli_args.tag}"
|
1151
1156
|
)
|
1157
|
+
|
1152
1158
|
for cmd in matching:
|
1153
1159
|
self._set_retry_policy(cmd)
|
1154
|
-
|
1160
|
+
try:
|
1161
|
+
await self.run_key(cmd.key)
|
1162
|
+
except FalyxError as error:
|
1163
|
+
self.console.print(f"[{OneColors.DARK_RED}]❌ Error: {error}[/]")
|
1164
|
+
sys.exit(1)
|
1165
|
+
except QuitSignal:
|
1166
|
+
logger.info("[QuitSignal]. <- Exiting run.")
|
1167
|
+
sys.exit(0)
|
1168
|
+
except BackSignal:
|
1169
|
+
logger.info("[BackSignal]. <- Exiting run.")
|
1170
|
+
sys.exit(0)
|
1171
|
+
except CancelSignal:
|
1172
|
+
logger.info("[CancelSignal]. <- Exiting run.")
|
1173
|
+
sys.exit(0)
|
1155
1174
|
|
1156
1175
|
if self.cli_args.summary:
|
1157
1176
|
er.summary()
|
@@ -6,12 +6,14 @@ Licensed under the MIT License. See LICENSE file for details.
|
|
6
6
|
"""
|
7
7
|
|
8
8
|
from .argparse import Argument, ArgumentAction, CommandArgumentParser
|
9
|
-
from .parsers import FalyxParsers, get_arg_parsers
|
9
|
+
from .parsers import FalyxParsers, get_arg_parsers, get_root_parser, get_subparsers
|
10
10
|
|
11
11
|
__all__ = [
|
12
12
|
"Argument",
|
13
13
|
"ArgumentAction",
|
14
14
|
"CommandArgumentParser",
|
15
15
|
"get_arg_parsers",
|
16
|
+
"get_root_parser",
|
17
|
+
"get_subparsers",
|
16
18
|
"FalyxParsers",
|
17
19
|
]
|
@@ -40,7 +40,7 @@ class FalyxParsers:
|
|
40
40
|
return self.as_dict().get(name)
|
41
41
|
|
42
42
|
|
43
|
-
def
|
43
|
+
def get_root_parser(
|
44
44
|
prog: str | None = "falyx",
|
45
45
|
usage: str | None = None,
|
46
46
|
description: str | None = "Falyx CLI - Run structured async command workflows.",
|
@@ -55,9 +55,7 @@ def get_arg_parsers(
|
|
55
55
|
add_help: bool = True,
|
56
56
|
allow_abbrev: bool = True,
|
57
57
|
exit_on_error: bool = True,
|
58
|
-
|
59
|
-
) -> FalyxParsers:
|
60
|
-
"""Returns the argument parser for the CLI."""
|
58
|
+
) -> ArgumentParser:
|
61
59
|
parser = ArgumentParser(
|
62
60
|
prog=prog,
|
63
61
|
usage=usage,
|
@@ -86,27 +84,91 @@ def get_arg_parsers(
|
|
86
84
|
help="Enable default lifecycle debug logging",
|
87
85
|
)
|
88
86
|
parser.add_argument("--version", action="store_true", help="Show Falyx version")
|
89
|
-
|
87
|
+
return parser
|
88
|
+
|
89
|
+
|
90
|
+
def get_subparsers(
|
91
|
+
parser: ArgumentParser,
|
92
|
+
title: str = "Falyx Commands",
|
93
|
+
description: str | None = "Available commands for the Falyx CLI.",
|
94
|
+
) -> _SubParsersAction:
|
95
|
+
"""Create and return a subparsers action for the given parser."""
|
96
|
+
if not isinstance(parser, ArgumentParser):
|
97
|
+
raise TypeError("parser must be an instance of ArgumentParser")
|
98
|
+
subparsers = parser.add_subparsers(
|
99
|
+
title=title,
|
100
|
+
description=description,
|
101
|
+
metavar="COMMAND",
|
102
|
+
dest="command",
|
103
|
+
)
|
104
|
+
return subparsers
|
90
105
|
|
91
|
-
|
92
|
-
|
106
|
+
|
107
|
+
def get_arg_parsers(
|
108
|
+
prog: str | None = "falyx",
|
109
|
+
usage: str | None = None,
|
110
|
+
description: str | None = "Falyx CLI - Run structured async command workflows.",
|
111
|
+
epilog: (
|
112
|
+
str | None
|
113
|
+
) = "Tip: Use 'falyx run ?[COMMAND]' to preview any command from the CLI.",
|
114
|
+
parents: Sequence[ArgumentParser] | None = None,
|
115
|
+
prefix_chars: str = "-",
|
116
|
+
fromfile_prefix_chars: str | None = None,
|
117
|
+
argument_default: Any = None,
|
118
|
+
conflict_handler: str = "error",
|
119
|
+
add_help: bool = True,
|
120
|
+
allow_abbrev: bool = True,
|
121
|
+
exit_on_error: bool = True,
|
122
|
+
commands: dict[str, Command] | None = None,
|
123
|
+
root_parser: ArgumentParser | None = None,
|
124
|
+
subparsers: _SubParsersAction | None = None,
|
125
|
+
) -> FalyxParsers:
|
126
|
+
"""Returns the argument parser for the CLI."""
|
127
|
+
if root_parser is None:
|
128
|
+
parser = get_root_parser(
|
129
|
+
prog=prog,
|
130
|
+
usage=usage,
|
131
|
+
description=description,
|
132
|
+
epilog=epilog,
|
133
|
+
parents=parents,
|
134
|
+
prefix_chars=prefix_chars,
|
135
|
+
fromfile_prefix_chars=fromfile_prefix_chars,
|
136
|
+
argument_default=argument_default,
|
137
|
+
conflict_handler=conflict_handler,
|
138
|
+
add_help=add_help,
|
139
|
+
allow_abbrev=allow_abbrev,
|
140
|
+
exit_on_error=exit_on_error,
|
141
|
+
)
|
142
|
+
else:
|
143
|
+
if not isinstance(root_parser, ArgumentParser):
|
144
|
+
raise TypeError("root_parser must be an instance of ArgumentParser")
|
145
|
+
parser = root_parser
|
146
|
+
|
147
|
+
if subparsers is None:
|
148
|
+
subparsers = get_subparsers(parser)
|
149
|
+
if not isinstance(subparsers, _SubParsersAction):
|
150
|
+
raise TypeError("subparsers must be an instance of _SubParsersAction")
|
151
|
+
|
152
|
+
run_description = ["Run a command by its key or alias.\n"]
|
153
|
+
run_description.append("commands:")
|
93
154
|
if isinstance(commands, dict):
|
94
155
|
for command in commands.values():
|
95
|
-
|
156
|
+
run_description.append(command.usage)
|
96
157
|
command_description = command.description or command.help_text
|
97
|
-
|
98
|
-
|
99
|
-
run_epilog.append(
|
158
|
+
run_description.append(f"{' '*24}{command_description}")
|
159
|
+
run_epilog = (
|
100
160
|
"Tip: Use 'falyx run ?[COMMAND]' to preview commands by their key or alias."
|
101
161
|
)
|
102
162
|
run_parser = subparsers.add_parser(
|
103
163
|
"run",
|
104
164
|
help="Run a specific command",
|
105
|
-
description=run_description,
|
106
|
-
epilog=
|
165
|
+
description="\n".join(run_description),
|
166
|
+
epilog=run_epilog,
|
107
167
|
formatter_class=RawDescriptionHelpFormatter,
|
108
168
|
)
|
109
|
-
run_parser.add_argument(
|
169
|
+
run_parser.add_argument(
|
170
|
+
"name", help="Run a command by its key or alias", metavar="COMMAND"
|
171
|
+
)
|
110
172
|
run_parser.add_argument(
|
111
173
|
"--summary",
|
112
174
|
action="store_true",
|
@@ -144,6 +206,7 @@ def get_arg_parsers(
|
|
144
206
|
"command_args",
|
145
207
|
nargs=REMAINDER,
|
146
208
|
help="Arguments to pass to the command (if applicable)",
|
209
|
+
metavar="ARGS",
|
147
210
|
)
|
148
211
|
|
149
212
|
run_all_parser = subparsers.add_parser(
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.1.43"
|
falyx-0.1.41/falyx/version.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
__version__ = "0.1.41"
|
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
|
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
|