falyx 0.1.49__py3-none-any.whl → 0.1.50__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/.coverage ADDED
Binary file
falyx/context.py CHANGED
@@ -70,7 +70,7 @@ class ExecutionContext(BaseModel):
70
70
 
71
71
  name: str
72
72
  args: tuple = ()
73
- kwargs: dict = {}
73
+ kwargs: dict = Field(default_factory=dict)
74
74
  action: Any
75
75
  result: Any | None = None
76
76
  exception: Exception | None = None
@@ -120,6 +120,17 @@ class ExecutionContext(BaseModel):
120
120
  def status(self) -> str:
121
121
  return "OK" if self.success else "ERROR"
122
122
 
123
+ @property
124
+ def signature(self) -> str:
125
+ """
126
+ Returns a string representation of the action signature, including
127
+ its name and arguments.
128
+ """
129
+ args = ", ".join(map(repr, self.args))
130
+ kwargs = ", ".join(f"{key}={value!r}" for key, value in self.kwargs.items())
131
+ signature = ", ".join(filter(None, [args, kwargs]))
132
+ return f"{self.name} ({signature})"
133
+
123
134
  def as_dict(self) -> dict:
124
135
  return {
125
136
  "name": self.name,
falyx/debug.py CHANGED
@@ -8,7 +8,7 @@ from falyx.logger import logger
8
8
  def log_before(context: ExecutionContext):
9
9
  """Log the start of an action."""
10
10
  args = ", ".join(map(repr, context.args))
11
- kwargs = ", ".join(f"{k}={v!r}" for k, v in context.kwargs.items())
11
+ kwargs = ", ".join(f"{key}={value!r}" for key, value in context.kwargs.items())
12
12
  signature = ", ".join(filter(None, [args, kwargs]))
13
13
  logger.info("[%s] Starting -> %s(%s)", context.name, context.action, signature)
14
14
 
@@ -30,7 +30,7 @@ from __future__ import annotations
30
30
  from collections import defaultdict
31
31
  from datetime import datetime
32
32
  from threading import Lock
33
- from typing import Any, Literal
33
+ from typing import Literal
34
34
 
35
35
  from rich import box
36
36
  from rich.console import Console
@@ -111,8 +111,8 @@ class ExecutionRegistry:
111
111
  def summary(
112
112
  cls,
113
113
  name: str = "",
114
- index: int = -1,
115
- result: int = -1,
114
+ index: int | None = None,
115
+ result: int | None = None,
116
116
  clear: bool = False,
117
117
  last_result: bool = False,
118
118
  status: Literal["all", "success", "error"] = "all",
@@ -138,7 +138,7 @@ class ExecutionRegistry:
138
138
  )
139
139
  return
140
140
 
141
- if result and result >= 0:
141
+ if result is not None and result >= 0:
142
142
  try:
143
143
  result_context = cls._store_by_index[result]
144
144
  except KeyError:
@@ -146,7 +146,11 @@ class ExecutionRegistry:
146
146
  f"[{OneColors.DARK_RED}]❌ No execution found for index {index}."
147
147
  )
148
148
  return
149
- cls._console.print(result_context.result)
149
+ cls._console.print(f"{result_context.signature}:")
150
+ if result_context.exception:
151
+ cls._console.print(result_context.exception)
152
+ else:
153
+ cls._console.print(result_context.result)
150
154
  return
151
155
 
152
156
  if name:
@@ -157,9 +161,10 @@ class ExecutionRegistry:
157
161
  )
158
162
  return
159
163
  title = f"📊 Execution History for '{contexts[0].name}'"
160
- elif index and index >= 0:
164
+ elif index is not None and index >= 0:
161
165
  try:
162
166
  contexts = [cls._store_by_index[index]]
167
+ print(contexts)
163
168
  except KeyError:
164
169
  cls._console.print(
165
170
  f"[{OneColors.DARK_RED}]❌ No execution found for index {index}."
falyx/falyx.py CHANGED
@@ -796,7 +796,12 @@ class Falyx:
796
796
  def table(self) -> Table:
797
797
  """Creates or returns a custom table to display the menu commands."""
798
798
  if callable(self.custom_table):
799
- return self.custom_table(self)
799
+ custom_table = self.custom_table(self)
800
+ if not isinstance(custom_table, Table):
801
+ raise FalyxError(
802
+ "custom_table must return an instance of rich.table.Table."
803
+ )
804
+ return custom_table
800
805
  elif isinstance(self.custom_table, Table):
801
806
  return self.custom_table
802
807
  else:
@@ -834,21 +839,31 @@ class Falyx:
834
839
 
835
840
  choice = choice.upper()
836
841
  name_map = self._name_map
842
+ run_command = None
837
843
  if name_map.get(choice):
844
+ run_command = name_map[choice]
845
+ else:
846
+ prefix_matches = [
847
+ cmd for key, cmd in name_map.items() if key.startswith(choice)
848
+ ]
849
+ if len(prefix_matches) == 1:
850
+ run_command = prefix_matches[0]
851
+
852
+ if run_command:
838
853
  if not from_validate:
839
- logger.info("Command '%s' selected.", choice)
854
+ logger.info("Command '%s' selected.", run_command.key)
840
855
  if is_preview:
841
- return True, name_map[choice], args, kwargs
856
+ return True, run_command, args, kwargs
842
857
  elif self.mode in {FalyxMode.RUN, FalyxMode.RUN_ALL, FalyxMode.PREVIEW}:
843
- return False, name_map[choice], args, kwargs
858
+ return False, run_command, args, kwargs
844
859
  try:
845
- args, kwargs = await name_map[choice].parse_args(
846
- input_args, from_validate
847
- )
860
+ args, kwargs = await run_command.parse_args(input_args, from_validate)
848
861
  except (CommandArgumentError, Exception) as error:
849
862
  if not from_validate:
850
- name_map[choice].show_help()
851
- self.console.print(f"[{OneColors.DARK_RED}]❌ [{choice}]: {error}")
863
+ run_command.show_help()
864
+ self.console.print(
865
+ f"[{OneColors.DARK_RED}]❌ [{run_command.key}]: {error}"
866
+ )
852
867
  else:
853
868
  raise ValidationError(
854
869
  message=str(error), cursor_position=len(raw_choices)
@@ -856,11 +871,7 @@ class Falyx:
856
871
  return is_preview, None, args, kwargs
857
872
  except HelpSignal:
858
873
  return True, None, args, kwargs
859
- return is_preview, name_map[choice], args, kwargs
860
-
861
- prefix_matches = [cmd for key, cmd in name_map.items() if key.startswith(choice)]
862
- if len(prefix_matches) == 1:
863
- return is_preview, prefix_matches[0], args, kwargs
874
+ return is_preview, run_command, args, kwargs
864
875
 
865
876
  fuzzy_matches = get_close_matches(choice, list(name_map.keys()), n=3, cutoff=0.7)
866
877
  if fuzzy_matches:
@@ -890,12 +901,14 @@ class Falyx:
890
901
  )
891
902
  return is_preview, None, args, kwargs
892
903
 
893
- def _create_context(self, selected_command: Command) -> ExecutionContext:
894
- """Creates a context dictionary for the selected command."""
904
+ def _create_context(
905
+ self, selected_command: Command, args: tuple, kwargs: dict[str, Any]
906
+ ) -> ExecutionContext:
907
+ """Creates an ExecutionContext object for the selected command."""
895
908
  return ExecutionContext(
896
909
  name=selected_command.description,
897
- args=tuple(),
898
- kwargs={},
910
+ args=args,
911
+ kwargs=kwargs,
899
912
  action=selected_command,
900
913
  )
901
914
 
@@ -929,7 +942,7 @@ class Falyx:
929
942
  logger.info("Back selected: exiting %s", self.get_title())
930
943
  return False
931
944
 
932
- context = self._create_context(selected_command)
945
+ context = self._create_context(selected_command, args, kwargs)
933
946
  context.start_timer()
934
947
  try:
935
948
  await self.hooks.trigger(HookType.BEFORE, context)
@@ -974,7 +987,7 @@ class Falyx:
974
987
  selected_command.description,
975
988
  )
976
989
 
977
- context = self._create_context(selected_command)
990
+ context = self._create_context(selected_command, args, kwargs)
978
991
  context.start_timer()
979
992
  try:
980
993
  await self.hooks.trigger(HookType.BEFORE, context)
falyx/parsers/argparse.py CHANGED
@@ -629,7 +629,10 @@ class CommandArgumentParser:
629
629
  consumed_positional_indicies.add(j)
630
630
 
631
631
  if i < len(args):
632
- raise CommandArgumentError(f"Unexpected positional argument: {args[i:]}")
632
+ plural = "s" if len(args[i:]) > 1 else ""
633
+ raise CommandArgumentError(
634
+ f"Unexpected positional argument{plural}: {', '.join(args[i:])}"
635
+ )
633
636
 
634
637
  return i
635
638
 
falyx/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.49"
1
+ __version__ = "0.1.50"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: falyx
3
- Version: 0.1.49
3
+ Version: 0.1.50
4
4
  Summary: Reliable and introspectable async CLI action framework.
5
5
  License: MIT
6
6
  Author: Roland Thomas Jr
@@ -1,3 +1,4 @@
1
+ falyx/.coverage,sha256=DNx1Ew1vSvuIcKko7httsyL62erJxVQ6CKtuJKxRVj4,53248
1
2
  falyx/.pytyped,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
3
  falyx/__init__.py,sha256=Gh88lQ5pbD7xbGWrBgslE2kSTZKY9TkvKSa53rZ3l8U,305
3
4
  falyx/__main__.py,sha256=186MGZUMtx-hCH7QsBqcN-68hYg747LOSk3rlc_23_c,3421
@@ -25,11 +26,11 @@ falyx/action/user_input_action.py,sha256=w9QTjKbdPmhXleX_XxUKS9VvNyKpwTtcuXBX706
25
26
  falyx/bottom_bar.py,sha256=KPACb9VC0I3dv_pYZLqy7e4uA_KT5dSfwnvuknyV0FI,7388
26
27
  falyx/command.py,sha256=LmtoI4NbW_zEy_f1AlZ-obl83K5l07Sac0zXJt6xQYc,16419
27
28
  falyx/config.py,sha256=Cm1F9SfNSbugPALxaEz7NRqp1wrk-g2jYq35bQzN2uE,9658
28
- falyx/context.py,sha256=EJIWQxU3SeAcufq6_WrAVIAs6abpY4-ttcemH3RVFnQ,10365
29
- falyx/debug.py,sha256=IRpYtdH8yeXJEsfP5rASALmBQb2U_EwrTudF2GIDdZY,1545
29
+ falyx/context.py,sha256=1olM6MRGMeQ_elhBegOcMDUFVHYIUqJh_7wlB74CdkQ,10804
30
+ falyx/debug.py,sha256=pguI0XQcZ-7jte5YUPexAufa1oxxalYO1JgmO6GU3rI,1557
30
31
  falyx/exceptions.py,sha256=kK9k1v7LVNjJSwYztRa9Krhr3ZOI-6Htq2ZjlYICPKg,922
31
- falyx/execution_registry.py,sha256=Ke3DlvG1pYvjwEG7fgb4KPNqCTj1MyYC9m9yd1oxmWk,7341
32
- falyx/falyx.py,sha256=LL7KzQW1O9eFtU_SGVvG-3RHlMErVsQ3l4V7H678Z7s,49272
32
+ falyx/execution_registry.py,sha256=Wpk2Wm2NUdIL4CtQxslqI1jAxNUBW0sNcQ2Op8t7ojU,7597
33
+ falyx/falyx.py,sha256=bPc6Umtpbc32KKlQPmrEOAqvFNhDh7CNIvukw5M5NoU,49714
33
34
  falyx/hook_manager.py,sha256=TFuHQnAncS_rk6vuw-VSx8bnAppLuHfrZCrzLwqcO9o,2979
34
35
  falyx/hooks.py,sha256=xMfQROib0BNsaQF4AXJpmCiGePoE1f1xpcdibgnVZWM,2913
35
36
  falyx/init.py,sha256=F9jg7mLPoBWXdJnc_fyWG7zVQSnrAO8ueDiP8AJxDWE,3331
@@ -38,7 +39,7 @@ falyx/menu.py,sha256=E580qZsx08bnWcqRVjJuD2Fy8Zh_1zIexp5f0lC7L2c,3745
38
39
  falyx/options_manager.py,sha256=dFAnQw543tQ6Xupvh1PwBrhiSWlSACHw8K-sHP_lUh4,2842
39
40
  falyx/parsers/.pytyped,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
41
  falyx/parsers/__init__.py,sha256=ZfPmbtEUechDvgl99-lWhTXmFnXS_FMXJ_xb8KGEJLo,448
41
- falyx/parsers/argparse.py,sha256=P_MS5YjtHJjEgAR8pm41SLndZhvCOCYfygv6svkMFu8,37401
42
+ falyx/parsers/argparse.py,sha256=NvrePJi0qHRSsTbddwoLSDhBk7TKPtS85UAsW9pRhuU,37504
42
43
  falyx/parsers/parsers.py,sha256=MXWC8OQ3apDaeKfY0O4J8NnkxofWVOCRnKatC00lGm0,8796
43
44
  falyx/parsers/signature.py,sha256=cCa-yKUcbbET0Ho45oFZWWHFGCX5a_LaAOWRP7b87po,2465
44
45
  falyx/parsers/utils.py,sha256=w_UzvvP62EDKXWSf3jslEsJfd45usGyFqXKNziQhLRI,2893
@@ -53,9 +54,9 @@ falyx/themes/__init__.py,sha256=1CZhEUCin9cUk8IGYBUFkVvdHRNNJBEFXccHwpUKZCA,284
53
54
  falyx/themes/colors.py,sha256=4aaeAHJetmeNInI0Zytg4E3YqKfPFelpf04vtjSvsS8,19776
54
55
  falyx/utils.py,sha256=U45xnZFUdoFC4xiji_9S1jHS5V7MvxSDtufP8EgB0SM,6732
55
56
  falyx/validators.py,sha256=t5iyzVpY8tdC4rfhr4isEfWpD5gNTzjeX_Hbi_Uq6sA,1328
56
- falyx/version.py,sha256=6ak6J_3GLVYH79iSCY8wWsCV4clQHUuDdcBlOnUh9K8,23
57
- falyx-0.1.49.dist-info/LICENSE,sha256=B0yqgaHuSdhN7T3OBmgQSiDTy8HqT5Oe_dLypRe4Ra4,1073
58
- falyx-0.1.49.dist-info/METADATA,sha256=uIl8tUOOoQzWV810xzwogyxWfNCRYYTZR684_8SXFcw,5561
59
- falyx-0.1.49.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
60
- falyx-0.1.49.dist-info/entry_points.txt,sha256=j8owOSl2j1Ss8DtGMnKfgehKaolqnIPhVFHaUBLUnMs,45
61
- falyx-0.1.49.dist-info/RECORD,,
57
+ falyx/version.py,sha256=GlCAyW7WOUPNmnX_3K1ur1QDZL8XW1tkxYm46z05bts,23
58
+ falyx-0.1.50.dist-info/LICENSE,sha256=B0yqgaHuSdhN7T3OBmgQSiDTy8HqT5Oe_dLypRe4Ra4,1073
59
+ falyx-0.1.50.dist-info/METADATA,sha256=sZV1SsxH2gfYv3YHH7OXtawrvCVGYR0pkyGSJURAo6I,5561
60
+ falyx-0.1.50.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
61
+ falyx-0.1.50.dist-info/entry_points.txt,sha256=j8owOSl2j1Ss8DtGMnKfgehKaolqnIPhVFHaUBLUnMs,45
62
+ falyx-0.1.50.dist-info/RECORD,,
File without changes