falyx 0.1.42__py3-none-any.whl → 0.1.43__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/__main__.py CHANGED
@@ -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
- return asyncio.run(flx.run())
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__":
falyx/falyx.py CHANGED
@@ -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
@@ -1029,6 +1029,8 @@ class Falyx:
1029
1029
  async def run(
1030
1030
  self,
1031
1031
  falyx_parsers: FalyxParsers | None = None,
1032
+ root_parser: ArgumentParser | None = None,
1033
+ subparsers: _SubParsersAction | None = None,
1032
1034
  callback: Callable[..., Any] | None = None,
1033
1035
  ) -> None:
1034
1036
  """Run Falyx CLI with structured subcommands."""
@@ -1046,6 +1048,8 @@ class Falyx:
1046
1048
  self.description,
1047
1049
  self.epilog,
1048
1050
  commands=self.commands,
1051
+ root_parser=root_parser,
1052
+ subparsers=subparsers,
1049
1053
  )
1050
1054
  self.cli_args = falyx_parsers.parse_args()
1051
1055
  self.options.from_namespace(self.cli_args, "cli_args")
falyx/parsers/__init__.py CHANGED
@@ -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
  ]
falyx/parsers/parsers.py CHANGED
@@ -40,7 +40,7 @@ class FalyxParsers:
40
40
  return self.as_dict().get(name)
41
41
 
42
42
 
43
- def get_arg_parsers(
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
- commands: dict[str, Command] | None = None,
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,7 +84,70 @@ 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
- subparsers = parser.add_subparsers(dest="command")
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
105
+
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")
90
151
 
91
152
  run_description = ["Run a command by its key or alias.\n"]
92
153
  run_description.append("commands:")
@@ -105,7 +166,9 @@ def get_arg_parsers(
105
166
  epilog=run_epilog,
106
167
  formatter_class=RawDescriptionHelpFormatter,
107
168
  )
108
- run_parser.add_argument("name", help="Run a command by its key or alias")
169
+ run_parser.add_argument(
170
+ "name", help="Run a command by its key or alias", metavar="COMMAND"
171
+ )
109
172
  run_parser.add_argument(
110
173
  "--summary",
111
174
  action="store_true",
@@ -143,6 +206,7 @@ def get_arg_parsers(
143
206
  "command_args",
144
207
  nargs=REMAINDER,
145
208
  help="Arguments to pass to the command (if applicable)",
209
+ metavar="ARGS",
146
210
  )
147
211
 
148
212
  run_all_parser = subparsers.add_parser(
falyx/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.42"
1
+ __version__ = "0.1.43"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: falyx
3
- Version: 0.1.42
3
+ Version: 0.1.43
4
4
  Summary: Reliable and introspectable async CLI action framework.
5
5
  License: MIT
6
6
  Author: Roland Thomas Jr
@@ -1,6 +1,6 @@
1
1
  falyx/.pytyped,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  falyx/__init__.py,sha256=Gh88lQ5pbD7xbGWrBgslE2kSTZKY9TkvKSa53rZ3l8U,305
3
- falyx/__main__.py,sha256=8abZbfytyFcSccyEZzlX3E2Krto1tVr1pRI_ep9KcUs,1911
3
+ falyx/__main__.py,sha256=yrNF4m7kwKX9dFn-Q_ci1N6BJCC_ltw2p0HcUDqEuas,3423
4
4
  falyx/action/.pytyped,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  falyx/action/__init__.py,sha256=4E3Rb0GgGcmggrPJh0YFiwbVgN_PQjIzL06-Z3qMReo,1247
6
6
  falyx/action/action.py,sha256=w6xDbsB1SlMPSvpo2Dh0e11lRGP6a4E3K6AdfjlEqGY,5759
@@ -29,7 +29,7 @@ falyx/context.py,sha256=NfBpxzFzn-dYP6I3wrtGFucqm__UZo4SSBLmM8yYayE,10330
29
29
  falyx/debug.py,sha256=IRpYtdH8yeXJEsfP5rASALmBQb2U_EwrTudF2GIDdZY,1545
30
30
  falyx/exceptions.py,sha256=kK9k1v7LVNjJSwYztRa9Krhr3ZOI-6Htq2ZjlYICPKg,922
31
31
  falyx/execution_registry.py,sha256=rctsz0mrIHPToLZqylblVjDdKWdq1x_JBc8GwMP5sJ8,4710
32
- falyx/falyx.py,sha256=kMQWAd_uL8M5hkzRy7k1KgNe5wBzkWCyHvqwFjykvdI,47340
32
+ falyx/falyx.py,sha256=X4f0O5wgUID0HjlwuH0I88HBLGhlQ1chNeOt1TlDJqw,47559
33
33
  falyx/hook_manager.py,sha256=TFuHQnAncS_rk6vuw-VSx8bnAppLuHfrZCrzLwqcO9o,2979
34
34
  falyx/hooks.py,sha256=xMfQROib0BNsaQF4AXJpmCiGePoE1f1xpcdibgnVZWM,2913
35
35
  falyx/init.py,sha256=VZ3rYMxo7g01EraYATdl_pRN4ZqrsVueo2ZFx54gojo,3326
@@ -37,9 +37,9 @@ falyx/logger.py,sha256=1Mfb_vJFJ1tQwziuyU2p-cSMi2Js8N2byniFEnI6vOQ,132
37
37
  falyx/menu.py,sha256=E580qZsx08bnWcqRVjJuD2Fy8Zh_1zIexp5f0lC7L2c,3745
38
38
  falyx/options_manager.py,sha256=dFAnQw543tQ6Xupvh1PwBrhiSWlSACHw8K-sHP_lUh4,2842
39
39
  falyx/parsers/.pytyped,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
- falyx/parsers/__init__.py,sha256=l0QMf89uJHhTpOqQfiV3tx7aAHvELqDFWAyjCbwEgBQ,370
40
+ falyx/parsers/__init__.py,sha256=ZfPmbtEUechDvgl99-lWhTXmFnXS_FMXJ_xb8KGEJLo,448
41
41
  falyx/parsers/argparse.py,sha256=WB8InZJ_WOaqi6J80IfnxInRyJ7aBCP0sv0zalo8al0,36924
42
- falyx/parsers/parsers.py,sha256=RQdfK_347TeTMYWZ_7WqZxGaslC-fRZeuir4kdHjvFM,6527
42
+ falyx/parsers/parsers.py,sha256=iCFOcNXuYLzmOzv63CPi8mWh7udi-Ok1ZJB80ASe12M,8673
43
43
  falyx/parsers/signature.py,sha256=i4iOiJxv70sxQYivKKXC_YOsShRUYfcI8Cjq8yVZvMo,2262
44
44
  falyx/parsers/utils.py,sha256=Z4qLu8NVIprcHK2RDXoISpcDKBUii3n05G9mlgiPDgw,889
45
45
  falyx/prompt_utils.py,sha256=qgk0bXs7mwzflqzWyFhEOTpKQ_ZtMIqGhKeg-ocwNnE,1542
@@ -53,9 +53,9 @@ falyx/themes/__init__.py,sha256=1CZhEUCin9cUk8IGYBUFkVvdHRNNJBEFXccHwpUKZCA,284
53
53
  falyx/themes/colors.py,sha256=4aaeAHJetmeNInI0Zytg4E3YqKfPFelpf04vtjSvsS8,19776
54
54
  falyx/utils.py,sha256=U45xnZFUdoFC4xiji_9S1jHS5V7MvxSDtufP8EgB0SM,6732
55
55
  falyx/validators.py,sha256=t5iyzVpY8tdC4rfhr4isEfWpD5gNTzjeX_Hbi_Uq6sA,1328
56
- falyx/version.py,sha256=a0ON039K5sX117g1thh7kP35cYMBjBhhhU9A-PERuT0,23
57
- falyx-0.1.42.dist-info/LICENSE,sha256=B0yqgaHuSdhN7T3OBmgQSiDTy8HqT5Oe_dLypRe4Ra4,1073
58
- falyx-0.1.42.dist-info/METADATA,sha256=8L4CG1zpDFOwepLhP9oji_1UGmTkM24p6_QcHRQDY8c,5517
59
- falyx-0.1.42.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
60
- falyx-0.1.42.dist-info/entry_points.txt,sha256=j8owOSl2j1Ss8DtGMnKfgehKaolqnIPhVFHaUBLUnMs,45
61
- falyx-0.1.42.dist-info/RECORD,,
56
+ falyx/version.py,sha256=PwEipAcIgfEks4UpVgOERoR8Az-FCfCGocVnb0rkncM,23
57
+ falyx-0.1.43.dist-info/LICENSE,sha256=B0yqgaHuSdhN7T3OBmgQSiDTy8HqT5Oe_dLypRe4Ra4,1073
58
+ falyx-0.1.43.dist-info/METADATA,sha256=qHVTRg3y4xhC6cxIDvkkZ5YuJsm98DEhOOi485g-HUE,5517
59
+ falyx-0.1.43.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
60
+ falyx-0.1.43.dist-info/entry_points.txt,sha256=j8owOSl2j1Ss8DtGMnKfgehKaolqnIPhVFHaUBLUnMs,45
61
+ falyx-0.1.43.dist-info/RECORD,,
File without changes