falyx 0.1.40__tar.gz → 0.1.42__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.
Files changed (61) hide show
  1. {falyx-0.1.40 → falyx-0.1.42}/PKG-INFO +1 -1
  2. {falyx-0.1.40 → falyx-0.1.42}/falyx/__main__.py +27 -33
  3. {falyx-0.1.40 → falyx-0.1.42}/falyx/command.py +10 -0
  4. {falyx-0.1.40 → falyx-0.1.42}/falyx/config.py +12 -0
  5. {falyx-0.1.40 → falyx-0.1.42}/falyx/falyx.py +70 -9
  6. {falyx-0.1.40 → falyx-0.1.42}/falyx/init.py +1 -1
  7. {falyx-0.1.40 → falyx-0.1.42}/falyx/parsers/argparse.py +38 -15
  8. {falyx-0.1.40 → falyx-0.1.42}/falyx/parsers/parsers.py +28 -3
  9. falyx-0.1.42/falyx/version.py +1 -0
  10. {falyx-0.1.40 → falyx-0.1.42}/pyproject.toml +1 -1
  11. falyx-0.1.40/falyx/version.py +0 -1
  12. {falyx-0.1.40 → falyx-0.1.42}/LICENSE +0 -0
  13. {falyx-0.1.40 → falyx-0.1.42}/README.md +0 -0
  14. {falyx-0.1.40 → falyx-0.1.42}/falyx/.pytyped +0 -0
  15. {falyx-0.1.40 → falyx-0.1.42}/falyx/__init__.py +0 -0
  16. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/.pytyped +0 -0
  17. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/__init__.py +0 -0
  18. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/action.py +0 -0
  19. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/action_factory.py +0 -0
  20. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/action_group.py +0 -0
  21. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/base.py +0 -0
  22. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/chained_action.py +0 -0
  23. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/fallback_action.py +0 -0
  24. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/http_action.py +0 -0
  25. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/io_action.py +0 -0
  26. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/literal_input_action.py +0 -0
  27. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/menu_action.py +0 -0
  28. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/mixins.py +0 -0
  29. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/process_action.py +0 -0
  30. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/process_pool_action.py +0 -0
  31. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/prompt_menu_action.py +0 -0
  32. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/select_file_action.py +0 -0
  33. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/selection_action.py +0 -0
  34. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/signal_action.py +0 -0
  35. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/types.py +0 -0
  36. {falyx-0.1.40 → falyx-0.1.42}/falyx/action/user_input_action.py +0 -0
  37. {falyx-0.1.40 → falyx-0.1.42}/falyx/bottom_bar.py +0 -0
  38. {falyx-0.1.40 → falyx-0.1.42}/falyx/context.py +0 -0
  39. {falyx-0.1.40 → falyx-0.1.42}/falyx/debug.py +0 -0
  40. {falyx-0.1.40 → falyx-0.1.42}/falyx/exceptions.py +0 -0
  41. {falyx-0.1.40 → falyx-0.1.42}/falyx/execution_registry.py +0 -0
  42. {falyx-0.1.40 → falyx-0.1.42}/falyx/hook_manager.py +0 -0
  43. {falyx-0.1.40 → falyx-0.1.42}/falyx/hooks.py +0 -0
  44. {falyx-0.1.40 → falyx-0.1.42}/falyx/logger.py +0 -0
  45. {falyx-0.1.40 → falyx-0.1.42}/falyx/menu.py +0 -0
  46. {falyx-0.1.40 → falyx-0.1.42}/falyx/options_manager.py +0 -0
  47. {falyx-0.1.40 → falyx-0.1.42}/falyx/parsers/.pytyped +0 -0
  48. {falyx-0.1.40 → falyx-0.1.42}/falyx/parsers/__init__.py +0 -0
  49. {falyx-0.1.40 → falyx-0.1.42}/falyx/parsers/signature.py +0 -0
  50. {falyx-0.1.40 → falyx-0.1.42}/falyx/parsers/utils.py +0 -0
  51. {falyx-0.1.40 → falyx-0.1.42}/falyx/prompt_utils.py +0 -0
  52. {falyx-0.1.40 → falyx-0.1.42}/falyx/protocols.py +0 -0
  53. {falyx-0.1.40 → falyx-0.1.42}/falyx/retry.py +0 -0
  54. {falyx-0.1.40 → falyx-0.1.42}/falyx/retry_utils.py +0 -0
  55. {falyx-0.1.40 → falyx-0.1.42}/falyx/selection.py +0 -0
  56. {falyx-0.1.40 → falyx-0.1.42}/falyx/signals.py +0 -0
  57. {falyx-0.1.40 → falyx-0.1.42}/falyx/tagged_table.py +0 -0
  58. {falyx-0.1.40 → falyx-0.1.42}/falyx/themes/__init__.py +0 -0
  59. {falyx-0.1.40 → falyx-0.1.42}/falyx/themes/colors.py +0 -0
  60. {falyx-0.1.40 → falyx-0.1.42}/falyx/utils.py +0 -0
  61. {falyx-0.1.40 → falyx-0.1.42}/falyx/validators.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: falyx
3
- Version: 0.1.40
3
+ Version: 0.1.42
4
4
  Summary: Reliable and introspectable async CLI action framework.
5
5
  License: MIT
6
6
  Author: Roland Thomas Jr
@@ -8,13 +8,12 @@ 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 Namespace
12
11
  from pathlib import Path
13
12
  from typing import Any
14
13
 
15
14
  from falyx.config import loader
16
15
  from falyx.falyx import Falyx
17
- from falyx.parsers import FalyxParsers, get_arg_parsers
16
+ from falyx.parsers import CommandArgumentParser
18
17
 
19
18
 
20
19
  def find_falyx_config() -> Path | None:
@@ -39,45 +38,40 @@ def bootstrap() -> Path | None:
39
38
  return config_path
40
39
 
41
40
 
42
- def get_falyx_parsers() -> FalyxParsers:
43
- falyx_parsers: FalyxParsers = get_arg_parsers()
44
- init_parser = falyx_parsers.subparsers.add_parser(
45
- "init", help="Create a new Falyx CLI project"
41
+ def init_config(parser: CommandArgumentParser) -> None:
42
+ parser.add_argument(
43
+ "name",
44
+ type=str,
45
+ help="Name of the new Falyx project",
46
+ default=".",
47
+ nargs="?",
46
48
  )
47
- init_parser.add_argument("name", nargs="?", default=".", help="Project directory")
48
- falyx_parsers.subparsers.add_parser(
49
- "init-global", help="Set up ~/.config/falyx with example tasks"
50
- )
51
- return falyx_parsers
52
-
53
-
54
- def run(args: Namespace) -> Any:
55
- if args.command == "init":
56
- from falyx.init import init_project
57
-
58
- init_project(args.name)
59
- return
60
49
 
61
- if args.command == "init-global":
62
- from falyx.init import init_global
63
-
64
- init_global()
65
- return
66
50
 
51
+ def main() -> Any:
67
52
  bootstrap_path = bootstrap()
68
53
  if not bootstrap_path:
69
- print("No Falyx config file found. Exiting.")
70
- return None
54
+ from falyx.init import init_global, init_project
55
+
56
+ flx: Falyx = Falyx()
57
+ flx.add_command(
58
+ "I",
59
+ "Initialize a new Falyx project",
60
+ init_project,
61
+ aliases=["init"],
62
+ argument_config=init_config,
63
+ )
64
+ flx.add_command(
65
+ "G",
66
+ "Initialize Falyx global configuration",
67
+ init_global,
68
+ aliases=["init-global"],
69
+ )
70
+ else:
71
+ flx = loader(bootstrap_path)
71
72
 
72
- flx: Falyx = loader(bootstrap_path)
73
73
  return asyncio.run(flx.run())
74
74
 
75
75
 
76
- def main():
77
- parsers = get_falyx_parsers()
78
- args = parsers.parse_args()
79
- run(args)
80
-
81
-
82
76
  if __name__ == "__main__":
83
77
  main()
@@ -307,6 +307,16 @@ class Command(BaseModel):
307
307
 
308
308
  return FormattedText(prompt)
309
309
 
310
+ @property
311
+ def usage(self) -> str:
312
+ """Generate a help string for the command arguments."""
313
+ if not self.arg_parser:
314
+ return "No arguments defined."
315
+
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} "
319
+
310
320
  def log_summary(self) -> None:
311
321
  if self._context:
312
322
  self._context.log_summary()
@@ -18,6 +18,7 @@ from falyx.action.base import BaseAction
18
18
  from falyx.command import Command
19
19
  from falyx.falyx import Falyx
20
20
  from falyx.logger import logger
21
+ from falyx.parsers import CommandArgumentParser
21
22
  from falyx.retry import RetryPolicy
22
23
  from falyx.themes import OneColors
23
24
 
@@ -101,6 +102,7 @@ class RawCommand(BaseModel):
101
102
  retry_policy: RetryPolicy = Field(default_factory=RetryPolicy)
102
103
  hidden: bool = False
103
104
  help_text: str = ""
105
+ help_epilogue: str = ""
104
106
 
105
107
  @field_validator("retry_policy")
106
108
  @classmethod
@@ -116,6 +118,14 @@ def convert_commands(raw_commands: list[dict[str, Any]]) -> list[Command]:
116
118
  commands = []
117
119
  for entry in raw_commands:
118
120
  raw_command = RawCommand(**entry)
121
+ parser = CommandArgumentParser(
122
+ command_key=raw_command.key,
123
+ command_description=raw_command.description,
124
+ command_style=raw_command.style,
125
+ help_text=raw_command.help_text,
126
+ help_epilogue=raw_command.help_epilogue,
127
+ aliases=raw_command.aliases,
128
+ )
119
129
  commands.append(
120
130
  Command.model_validate(
121
131
  {
@@ -123,9 +133,11 @@ def convert_commands(raw_commands: list[dict[str, Any]]) -> list[Command]:
123
133
  "action": wrap_if_needed(
124
134
  import_action(raw_command.action), name=raw_command.description
125
135
  ),
136
+ "arg_parser": parser,
126
137
  }
127
138
  )
128
139
  )
140
+
129
141
  return commands
130
142
 
131
143
 
@@ -59,7 +59,7 @@ from falyx.execution_registry import ExecutionRegistry as er
59
59
  from falyx.hook_manager import Hook, HookManager, HookType
60
60
  from falyx.logger import logger
61
61
  from falyx.options_manager import OptionsManager
62
- from falyx.parsers import CommandArgumentParser, get_arg_parsers
62
+ from falyx.parsers import CommandArgumentParser, FalyxParsers, get_arg_parsers
63
63
  from falyx.protocols import ArgParserProtocol
64
64
  from falyx.retry import RetryPolicy
65
65
  from falyx.signals import BackSignal, CancelSignal, HelpSignal, QuitSignal
@@ -152,6 +152,11 @@ class Falyx:
152
152
  self,
153
153
  title: str | Markdown = "Menu",
154
154
  *,
155
+ program: str | None = "falyx",
156
+ usage: str | None = None,
157
+ description: str | None = "Falyx CLI - Run structured async command workflows.",
158
+ epilog: str | None = None,
159
+ version: str = __version__,
155
160
  prompt: str | AnyFormattedText = "> ",
156
161
  columns: int = 3,
157
162
  bottom_bar: BottomBar | str | Callable[[], Any] | None = None,
@@ -170,6 +175,11 @@ class Falyx:
170
175
  ) -> None:
171
176
  """Initializes the Falyx object."""
172
177
  self.title: str | Markdown = title
178
+ self.program: str | None = program
179
+ self.usage: str | None = usage
180
+ self.description: str | None = description
181
+ self.epilog: str | None = epilog
182
+ self.version: str = version
173
183
  self.prompt: str | AnyFormattedText = prompt
174
184
  self.columns: int = columns
175
185
  self.commands: dict[str, Command] = CaseInsensitiveDict()
@@ -820,10 +830,11 @@ class Falyx:
820
830
  self.console.print(
821
831
  f"[{OneColors.LIGHT_YELLOW}]⚠️ Unknown command '{choice}'[/]"
822
832
  )
823
- raise ValidationError(
824
- message=f"Unknown command '{choice}'.",
825
- cursor_position=len(raw_choices),
826
- )
833
+ else:
834
+ raise ValidationError(
835
+ message=f"Unknown command '{choice}'.",
836
+ cursor_position=len(raw_choices),
837
+ )
827
838
  return is_preview, None, args, kwargs
828
839
 
829
840
  def _create_context(self, selected_command: Command) -> ExecutionContext:
@@ -1015,12 +1026,35 @@ class Falyx:
1015
1026
  if self.exit_message:
1016
1027
  self.print_message(self.exit_message)
1017
1028
 
1018
- async def run(self) -> None:
1029
+ async def run(
1030
+ self,
1031
+ falyx_parsers: FalyxParsers | None = None,
1032
+ callback: Callable[..., Any] | None = None,
1033
+ ) -> None:
1019
1034
  """Run Falyx CLI with structured subcommands."""
1020
- if not self.cli_args:
1021
- self.cli_args = get_arg_parsers().root.parse_args()
1035
+ if self.cli_args:
1036
+ raise FalyxError(
1037
+ "Run is incompatible with CLI arguments. Use 'run_key' instead."
1038
+ )
1039
+ if falyx_parsers:
1040
+ if not isinstance(falyx_parsers, FalyxParsers):
1041
+ raise FalyxError("falyx_parsers must be an instance of FalyxParsers.")
1042
+ else:
1043
+ falyx_parsers = get_arg_parsers(
1044
+ self.program,
1045
+ self.usage,
1046
+ self.description,
1047
+ self.epilog,
1048
+ commands=self.commands,
1049
+ )
1050
+ self.cli_args = falyx_parsers.parse_args()
1022
1051
  self.options.from_namespace(self.cli_args, "cli_args")
1023
1052
 
1053
+ if callback:
1054
+ if not callable(callback):
1055
+ raise FalyxError("Callback must be a callable function.")
1056
+ callback(self.cli_args)
1057
+
1024
1058
  if not self.options.get("never_prompt"):
1025
1059
  self.options.set("never_prompt", self._never_prompt)
1026
1060
 
@@ -1075,11 +1109,24 @@ class Falyx:
1075
1109
  args, kwargs = await command.parse_args(self.cli_args.command_args)
1076
1110
  except HelpSignal:
1077
1111
  sys.exit(0)
1112
+ except CommandArgumentError as error:
1113
+ self.console.print(f"[{OneColors.DARK_RED}]❌ ['{command.key}'] {error}")
1114
+ command.show_help()
1115
+ sys.exit(1)
1078
1116
  try:
1079
1117
  await self.run_key(self.cli_args.name, args=args, kwargs=kwargs)
1080
1118
  except FalyxError as error:
1081
1119
  self.console.print(f"[{OneColors.DARK_RED}]❌ Error: {error}[/]")
1082
1120
  sys.exit(1)
1121
+ except QuitSignal:
1122
+ logger.info("[QuitSignal]. <- Exiting run.")
1123
+ sys.exit(0)
1124
+ except BackSignal:
1125
+ logger.info("[BackSignal]. <- Exiting run.")
1126
+ sys.exit(0)
1127
+ except CancelSignal:
1128
+ logger.info("[CancelSignal]. <- Exiting run.")
1129
+ sys.exit(0)
1083
1130
 
1084
1131
  if self.cli_args.summary:
1085
1132
  er.summary()
@@ -1103,9 +1150,23 @@ class Falyx:
1103
1150
  f"[{OneColors.CYAN_b}]🚀 Running all commands with tag:[/] "
1104
1151
  f"{self.cli_args.tag}"
1105
1152
  )
1153
+
1106
1154
  for cmd in matching:
1107
1155
  self._set_retry_policy(cmd)
1108
- await self.run_key(cmd.key)
1156
+ try:
1157
+ await self.run_key(cmd.key)
1158
+ except FalyxError as error:
1159
+ self.console.print(f"[{OneColors.DARK_RED}]❌ Error: {error}[/]")
1160
+ sys.exit(1)
1161
+ except QuitSignal:
1162
+ logger.info("[QuitSignal]. <- Exiting run.")
1163
+ sys.exit(0)
1164
+ except BackSignal:
1165
+ logger.info("[BackSignal]. <- Exiting run.")
1166
+ sys.exit(0)
1167
+ except CancelSignal:
1168
+ logger.info("[CancelSignal]. <- Exiting run.")
1169
+ sys.exit(0)
1109
1170
 
1110
1171
  if self.cli_args.summary:
1111
1172
  er.summary()
@@ -101,7 +101,7 @@ commands:
101
101
  console = Console(color_system="auto")
102
102
 
103
103
 
104
- def init_project(name: str = ".") -> None:
104
+ def init_project(name: str) -> None:
105
105
  target = Path(name).resolve()
106
106
  target.mkdir(parents=True, exist_ok=True)
107
107
 
@@ -168,6 +168,7 @@ class CommandArgumentParser:
168
168
  self._arguments: list[Argument] = []
169
169
  self._positional: dict[str, Argument] = {}
170
170
  self._keyword: dict[str, Argument] = {}
171
+ self._keyword_list: list[Argument] = []
171
172
  self._flag_map: dict[str, Argument] = {}
172
173
  self._dest_set: set[str] = set()
173
174
  self._add_help()
@@ -488,6 +489,8 @@ class CommandArgumentParser:
488
489
  self._arguments.append(argument)
489
490
  if positional:
490
491
  self._positional[dest] = argument
492
+ else:
493
+ self._keyword_list.append(argument)
491
494
 
492
495
  def get_argument(self, dest: str) -> Argument | None:
493
496
  return next((a for a in self._arguments if a.dest == dest), None)
@@ -832,11 +835,11 @@ class CommandArgumentParser:
832
835
  kwargs_dict[arg.dest] = parsed[arg.dest]
833
836
  return tuple(args_list), kwargs_dict
834
837
 
835
- def render_help(self) -> None:
838
+ def get_options_text(self, plain_text=False) -> str:
836
839
  # Options
837
840
  # Add all keyword arguments to the options list
838
841
  options_list = []
839
- for arg in self._keyword.values():
842
+ for arg in self._keyword_list:
840
843
  choice_text = arg.get_choice_text()
841
844
  if choice_text:
842
845
  options_list.extend([f"[{arg.flags[0]} {choice_text}]"])
@@ -848,19 +851,39 @@ class CommandArgumentParser:
848
851
  choice_text = arg.get_choice_text()
849
852
  if isinstance(arg.nargs, int):
850
853
  choice_text = " ".join([choice_text] * arg.nargs)
851
- options_list.append(escape(choice_text))
852
-
853
- options_text = " ".join(options_list)
854
- command_keys = " | ".join(
855
- [f"[{self.command_style}]{self.command_key}[/{self.command_style}]"]
856
- + [
857
- f"[{self.command_style}]{alias}[/{self.command_style}]"
858
- for alias in self.aliases
859
- ]
860
- )
854
+ if plain_text:
855
+ options_list.append(choice_text)
856
+ else:
857
+ options_list.append(escape(choice_text))
858
+
859
+ return " ".join(options_list)
861
860
 
862
- usage = f"usage: {command_keys} {options_text}"
863
- self.console.print(f"[bold]{usage}[/bold]\n")
861
+ def get_command_keys_text(self, plain_text=False) -> str:
862
+ if plain_text:
863
+ command_keys = " | ".join(
864
+ [f"{self.command_key}"] + [f"{alias}" for alias in self.aliases]
865
+ )
866
+ else:
867
+ command_keys = " | ".join(
868
+ [f"[{self.command_style}]{self.command_key}[/{self.command_style}]"]
869
+ + [
870
+ f"[{self.command_style}]{alias}[/{self.command_style}]"
871
+ for alias in self.aliases
872
+ ]
873
+ )
874
+ return command_keys
875
+
876
+ def get_usage(self, plain_text=False) -> str:
877
+ """Get the usage text for the command."""
878
+ command_keys = self.get_command_keys_text(plain_text)
879
+ options_text = self.get_options_text(plain_text)
880
+ if options_text:
881
+ return f"{command_keys} {options_text}"
882
+ return command_keys
883
+
884
+ def render_help(self) -> None:
885
+ usage = self.get_usage()
886
+ self.console.print(f"[bold]usage: {usage}[/bold]\n")
864
887
 
865
888
  # Description
866
889
  if self.help_text:
@@ -877,7 +900,7 @@ class CommandArgumentParser:
877
900
  arg_line.append(help_text)
878
901
  self.console.print(arg_line)
879
902
  self.console.print("[bold]options:[/bold]")
880
- for arg in self._keyword.values():
903
+ for arg in self._keyword_list:
881
904
  flags = ", ".join(arg.flags)
882
905
  flags_choice = f"{flags} {arg.get_choice_text()}"
883
906
  arg_line = Text(f" {flags_choice:<30} ")
@@ -2,10 +2,18 @@
2
2
  """parsers.py
3
3
  This module contains the argument parsers used for the Falyx CLI.
4
4
  """
5
- from argparse import REMAINDER, ArgumentParser, Namespace, _SubParsersAction
5
+ from argparse import (
6
+ REMAINDER,
7
+ ArgumentParser,
8
+ Namespace,
9
+ RawDescriptionHelpFormatter,
10
+ _SubParsersAction,
11
+ )
6
12
  from dataclasses import asdict, dataclass
7
13
  from typing import Any, Sequence
8
14
 
15
+ from falyx.command import Command
16
+
9
17
 
10
18
  @dataclass
11
19
  class FalyxParsers:
@@ -47,6 +55,7 @@ def get_arg_parsers(
47
55
  add_help: bool = True,
48
56
  allow_abbrev: bool = True,
49
57
  exit_on_error: bool = True,
58
+ commands: dict[str, Command] | None = None,
50
59
  ) -> FalyxParsers:
51
60
  """Returns the argument parser for the CLI."""
52
61
  parser = ArgumentParser(
@@ -79,8 +88,24 @@ def get_arg_parsers(
79
88
  parser.add_argument("--version", action="store_true", help="Show Falyx version")
80
89
  subparsers = parser.add_subparsers(dest="command")
81
90
 
82
- run_parser = subparsers.add_parser("run", help="Run a specific command")
83
- run_parser.add_argument("name", help="Key, alias, or description of the command")
91
+ run_description = ["Run a command by its key or alias.\n"]
92
+ run_description.append("commands:")
93
+ if isinstance(commands, dict):
94
+ for command in commands.values():
95
+ run_description.append(command.usage)
96
+ command_description = command.description or command.help_text
97
+ run_description.append(f"{' '*24}{command_description}")
98
+ run_epilog = (
99
+ "Tip: Use 'falyx run ?[COMMAND]' to preview commands by their key or alias."
100
+ )
101
+ run_parser = subparsers.add_parser(
102
+ "run",
103
+ help="Run a specific command",
104
+ description="\n".join(run_description),
105
+ epilog=run_epilog,
106
+ formatter_class=RawDescriptionHelpFormatter,
107
+ )
108
+ run_parser.add_argument("name", help="Run a command by its key or alias")
84
109
  run_parser.add_argument(
85
110
  "--summary",
86
111
  action="store_true",
@@ -0,0 +1 @@
1
+ __version__ = "0.1.42"
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "falyx"
3
- version = "0.1.40"
3
+ version = "0.1.42"
4
4
  description = "Reliable and introspectable async CLI action framework."
5
5
  authors = ["Roland Thomas Jr <roland@rtj.dev>"]
6
6
  license = "MIT"
@@ -1 +0,0 @@
1
- __version__ = "0.1.40"
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