falyx 0.1.23__py3-none-any.whl → 0.1.25__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.
Files changed (44) hide show
  1. falyx/__init__.py +1 -1
  2. falyx/action/__init__.py +41 -0
  3. falyx/{action.py → action/action.py} +41 -23
  4. falyx/{action_factory.py → action/action_factory.py} +17 -5
  5. falyx/{http_action.py → action/http_action.py} +10 -9
  6. falyx/{io_action.py → action/io_action.py} +19 -14
  7. falyx/{menu_action.py → action/menu_action.py} +9 -79
  8. falyx/{select_file_action.py → action/select_file_action.py} +5 -36
  9. falyx/{selection_action.py → action/selection_action.py} +22 -8
  10. falyx/action/signal_action.py +43 -0
  11. falyx/action/types.py +37 -0
  12. falyx/bottom_bar.py +3 -3
  13. falyx/command.py +13 -10
  14. falyx/config.py +17 -9
  15. falyx/context.py +16 -8
  16. falyx/debug.py +2 -1
  17. falyx/exceptions.py +3 -0
  18. falyx/execution_registry.py +59 -13
  19. falyx/falyx.py +67 -77
  20. falyx/hook_manager.py +20 -3
  21. falyx/hooks.py +13 -6
  22. falyx/init.py +1 -0
  23. falyx/logger.py +5 -0
  24. falyx/menu.py +85 -0
  25. falyx/options_manager.py +7 -3
  26. falyx/parsers.py +2 -2
  27. falyx/prompt_utils.py +30 -1
  28. falyx/protocols.py +2 -1
  29. falyx/retry.py +23 -12
  30. falyx/retry_utils.py +2 -1
  31. falyx/selection.py +7 -3
  32. falyx/signals.py +3 -0
  33. falyx/tagged_table.py +2 -1
  34. falyx/themes/__init__.py +15 -0
  35. falyx/utils.py +11 -39
  36. falyx/validators.py +8 -7
  37. falyx/version.py +1 -1
  38. {falyx-0.1.23.dist-info → falyx-0.1.25.dist-info}/METADATA +2 -1
  39. falyx-0.1.25.dist-info/RECORD +46 -0
  40. falyx/signal_action.py +0 -30
  41. falyx-0.1.23.dist-info/RECORD +0 -41
  42. {falyx-0.1.23.dist-info → falyx-0.1.25.dist-info}/LICENSE +0 -0
  43. {falyx-0.1.23.dist-info → falyx-0.1.25.dist-info}/WHEEL +0 -0
  44. {falyx-0.1.23.dist-info → falyx-0.1.25.dist-info}/entry_points.txt +0 -0
falyx/retry.py CHANGED
@@ -8,10 +8,12 @@ import random
8
8
  from pydantic import BaseModel, Field
9
9
 
10
10
  from falyx.context import ExecutionContext
11
- from falyx.utils import logger
11
+ from falyx.logger import logger
12
12
 
13
13
 
14
14
  class RetryPolicy(BaseModel):
15
+ """RetryPolicy"""
16
+
15
17
  max_retries: int = Field(default=3, ge=0)
16
18
  delay: float = Field(default=1.0, ge=0.0)
17
19
  backoff: float = Field(default=2.0, ge=1.0)
@@ -34,6 +36,8 @@ class RetryPolicy(BaseModel):
34
36
 
35
37
 
36
38
  class RetryHandler:
39
+ """RetryHandler class to manage retry policies for actions."""
40
+
37
41
  def __init__(self, policy: RetryPolicy = RetryPolicy()):
38
42
  self.policy = policy
39
43
 
@@ -49,7 +53,7 @@ class RetryHandler:
49
53
  self.policy.delay = delay
50
54
  self.policy.backoff = backoff
51
55
  self.policy.jitter = jitter
52
- logger.info(f"🔄 Retry policy enabled: {self.policy}")
56
+ logger.info("🔄 Retry policy enabled: %s", self.policy)
53
57
 
54
58
  async def retry_on_error(self, context: ExecutionContext) -> None:
55
59
  from falyx.action import Action
@@ -63,21 +67,21 @@ class RetryHandler:
63
67
  last_error = error
64
68
 
65
69
  if not target:
66
- logger.warning(f"[{name}] ⚠️ No action target. Cannot retry.")
70
+ logger.warning("[%s] ⚠️ No action target. Cannot retry.", name)
67
71
  return None
68
72
 
69
73
  if not isinstance(target, Action):
70
74
  logger.warning(
71
- f"[{name}] ❌ RetryHandler only supports only supports Action objects."
75
+ "[%s] ❌ RetryHandler only supports only supports Action objects.", name
72
76
  )
73
77
  return None
74
78
 
75
79
  if not getattr(target, "is_retryable", False):
76
- logger.warning(f"[{name}] ❌ Not retryable.")
80
+ logger.warning("[%s] ❌ Not retryable.", name)
77
81
  return None
78
82
 
79
83
  if not self.policy.enabled:
80
- logger.warning(f"[{name}] ❌ Retry policy is disabled.")
84
+ logger.warning("[%s] ❌ Retry policy is disabled.", name)
81
85
  return None
82
86
 
83
87
  while retries_done < self.policy.max_retries:
@@ -88,23 +92,30 @@ class RetryHandler:
88
92
  sleep_delay += random.uniform(-self.policy.jitter, self.policy.jitter)
89
93
 
90
94
  logger.info(
91
- f"[{name}] 🔄 Retrying ({retries_done}/{self.policy.max_retries}) "
92
- f"in {current_delay}s due to '{last_error}'..."
95
+ "[%s] 🔄 Retrying (%s/%s) in %ss due to '%s'...",
96
+ name,
97
+ retries_done,
98
+ self.policy.max_retries,
99
+ current_delay,
100
+ last_error,
93
101
  )
94
102
  await asyncio.sleep(current_delay)
95
103
  try:
96
104
  result = await target.action(*context.args, **context.kwargs)
97
105
  context.result = result
98
106
  context.exception = None
99
- logger.info(f"[{name}] ✅ Retry succeeded on attempt {retries_done}.")
107
+ logger.info("[%s] ✅ Retry succeeded on attempt %s.", name, retries_done)
100
108
  return None
101
109
  except Exception as retry_error:
102
110
  last_error = retry_error
103
111
  current_delay *= self.policy.backoff
104
112
  logger.warning(
105
- f"[{name}] ⚠️ Retry attempt {retries_done}/{self.policy.max_retries} "
106
- f"failed due to '{retry_error}'."
113
+ "[%s] ⚠️ Retry attempt %s/%s failed due to '%s'.",
114
+ name,
115
+ retries_done,
116
+ self.policy.max_retries,
117
+ retry_error,
107
118
  )
108
119
 
109
120
  context.exception = last_error
110
- logger.error(f"[{name}] ❌ All {self.policy.max_retries} retries failed.")
121
+ logger.error("[%s] ❌ All %s retries failed.", name, self.policy.max_retries)
falyx/retry_utils.py CHANGED
@@ -1,5 +1,6 @@
1
1
  # Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
2
- from falyx.action import Action, BaseAction
2
+ """retry_utils.py"""
3
+ from falyx.action.action import Action, BaseAction
3
4
  from falyx.hook_manager import HookType
4
5
  from falyx.retry import RetryHandler, RetryPolicy
5
6
 
falyx/selection.py CHANGED
@@ -9,13 +9,15 @@ from rich.console import Console
9
9
  from rich.markup import escape
10
10
  from rich.table import Table
11
11
 
12
- from falyx.themes.colors import OneColors
12
+ from falyx.themes import OneColors
13
13
  from falyx.utils import chunks
14
14
  from falyx.validators import int_range_validator, key_validator
15
15
 
16
16
 
17
17
  @dataclass
18
18
  class SelectionOption:
19
+ """Represents a single selection option with a description and a value."""
20
+
19
21
  description: str
20
22
  value: Any
21
23
  style: str = OneColors.WHITE
@@ -26,7 +28,8 @@ class SelectionOption:
26
28
 
27
29
  def render(self, key: str) -> str:
28
30
  """Render the selection option for display."""
29
- return f"[{OneColors.WHITE}][{key}][/] [{self.style}]{self.description}[/]"
31
+ key = escape(f"[{key}]")
32
+ return f"[{OneColors.WHITE}]{key}[/] [{self.style}]{self.description}[/]"
30
33
 
31
34
 
32
35
  def render_table_base(
@@ -194,7 +197,8 @@ def render_selection_dict_table(
194
197
  row = []
195
198
  for key, option in chunk:
196
199
  row.append(
197
- f"[{OneColors.WHITE}][{key.upper()}] [{option.style}]{option.description}[/]"
200
+ f"[{OneColors.WHITE}][{key.upper()}] "
201
+ f"[{option.style}]{option.description}[/]"
198
202
  )
199
203
  table.add_row(*row)
200
204
 
falyx/signals.py CHANGED
@@ -1,4 +1,7 @@
1
1
  # Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
2
+ """signals.py"""
3
+
4
+
2
5
  class FlowSignal(BaseException):
3
6
  """Base class for all flow control signals in Falyx.
4
7
 
falyx/tagged_table.py CHANGED
@@ -1,4 +1,5 @@
1
1
  # Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
2
+ """tagged_table.py"""
2
3
  from collections import defaultdict
3
4
 
4
5
  from rich import box
@@ -10,7 +11,7 @@ from falyx.falyx import Falyx
10
11
 
11
12
  def build_tagged_table(flx: Falyx) -> Table:
12
13
  """Custom table builder that groups commands by tags."""
13
- table = Table(title=flx.title, show_header=False, box=box.SIMPLE)
14
+ table = Table(title=flx.title, show_header=False, box=box.SIMPLE) # type: ignore[arg-type]
14
15
 
15
16
  # Group commands by first tag
16
17
  grouped: dict[str, list[Command]] = defaultdict(list)
@@ -0,0 +1,15 @@
1
+ """
2
+ Falyx CLI Framework
3
+
4
+ Copyright (c) 2025 rtj.dev LLC.
5
+ Licensed under the MIT License. See LICENSE file for details.
6
+ """
7
+
8
+ from .colors import ColorsMeta, NordColors, OneColors, get_nord_theme
9
+
10
+ __all__ = [
11
+ "OneColors",
12
+ "NordColors",
13
+ "get_nord_theme",
14
+ "ColorsMeta",
15
+ ]
falyx/utils.py CHANGED
@@ -1,5 +1,7 @@
1
1
  # Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
2
2
  """utils.py"""
3
+ from __future__ import annotations
4
+
3
5
  import functools
4
6
  import inspect
5
7
  import logging
@@ -10,23 +12,12 @@ from itertools import islice
10
12
  from typing import Any, Awaitable, Callable, TypeVar
11
13
 
12
14
  import pythonjsonlogger.json
13
- from prompt_toolkit import PromptSession
14
- from prompt_toolkit.formatted_text import (
15
- AnyFormattedText,
16
- FormattedText,
17
- merge_formatted_text,
18
- )
19
15
  from rich.logging import RichHandler
20
16
 
21
- from falyx.themes.colors import OneColors
22
- from falyx.validators import yes_no_validator
23
-
24
- logger = logging.getLogger("falyx")
25
-
26
17
  T = TypeVar("T")
27
18
 
28
19
 
29
- async def _noop(*args, **kwargs):
20
+ async def _noop(*_, **__):
30
21
  pass
31
22
 
32
23
 
@@ -70,22 +61,6 @@ def chunks(iterator, size):
70
61
  yield chunk
71
62
 
72
63
 
73
- async def confirm_async(
74
- message: AnyFormattedText = "Are you sure?",
75
- prefix: AnyFormattedText = FormattedText([(OneColors.CYAN, "❓ ")]),
76
- suffix: AnyFormattedText = FormattedText([(OneColors.LIGHT_YELLOW_b, " [Y/n] > ")]),
77
- session: PromptSession | None = None,
78
- ) -> bool:
79
- """Prompt the user with a yes/no async confirmation and return True for 'Y'."""
80
- session = session or PromptSession()
81
- merged_message: AnyFormattedText = merge_formatted_text([prefix, message, suffix])
82
- answer = await session.prompt_async(
83
- merged_message,
84
- validator=yes_no_validator(),
85
- )
86
- return True if answer.upper() == "Y" else False
87
-
88
-
89
64
  class CaseInsensitiveDict(dict):
90
65
  """A case-insensitive dictionary that treats all keys as uppercase."""
91
66
 
@@ -114,12 +89,6 @@ class CaseInsensitiveDict(dict):
114
89
  items.update({self._normalize_key(k): v for k, v in kwargs.items()})
115
90
  super().update(items)
116
91
 
117
- def __iter__(self):
118
- return super().__iter__()
119
-
120
- def keys(self):
121
- return super().keys()
122
-
123
92
 
124
93
  def running_in_container() -> bool:
125
94
  try:
@@ -143,11 +112,13 @@ def setup_logging(
143
112
  console_log_level: int = logging.WARNING,
144
113
  ):
145
114
  """
146
- Configure logging for Falyx with support for both CLI-friendly and structured JSON output.
115
+ Configure logging for Falyx with support for both CLI-friendly and structured
116
+ JSON output.
147
117
 
148
- This function sets up separate logging handlers for console and file output, with optional
149
- support for JSON formatting. It also auto-detects whether the application is running inside
150
- a container to default to machine-readable logs when appropriate.
118
+ This function sets up separate logging handlers for console and file output,
119
+ with optional support for JSON formatting. It also auto-detects whether the
120
+ application is running inside a container to default to machine-readable logs
121
+ when appropriate.
151
122
 
152
123
  Args:
153
124
  mode (str | None):
@@ -170,7 +141,8 @@ def setup_logging(
170
141
  - Clears existing root handlers before setup.
171
142
  - Configures console logging using either Rich (for CLI) or JSON formatting.
172
143
  - Configures file logging in plain text or JSON based on `json_log_to_file`.
173
- - Automatically sets logging levels for noisy third-party modules (`urllib3`, `asyncio`).
144
+ - Automatically sets logging levels for noisy third-party modules
145
+ (`urllib3`, `asyncio`, `markdown_it`).
174
146
  - Propagates logs from the "falyx" logger to ensure centralized output.
175
147
 
176
148
  Raises:
falyx/validators.py CHANGED
@@ -1,4 +1,5 @@
1
1
  # Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
2
+ """validators.py"""
2
3
  from typing import KeysView, Sequence
3
4
 
4
5
  from prompt_toolkit.validation import Validator
@@ -7,10 +8,10 @@ from prompt_toolkit.validation import Validator
7
8
  def int_range_validator(minimum: int, maximum: int) -> Validator:
8
9
  """Validator for integer ranges."""
9
10
 
10
- def validate(input: str) -> bool:
11
+ def validate(text: str) -> bool:
11
12
  try:
12
- value = int(input)
13
- if not (minimum <= value <= maximum):
13
+ value = int(text)
14
+ if not minimum <= value <= maximum:
14
15
  return False
15
16
  return True
16
17
  except ValueError:
@@ -25,8 +26,8 @@ def int_range_validator(minimum: int, maximum: int) -> Validator:
25
26
  def key_validator(keys: Sequence[str] | KeysView[str]) -> Validator:
26
27
  """Validator for key inputs."""
27
28
 
28
- def validate(input: str) -> bool:
29
- if input.upper() not in [key.upper() for key in keys]:
29
+ def validate(text: str) -> bool:
30
+ if text.upper() not in [key.upper() for key in keys]:
30
31
  return False
31
32
  return True
32
33
 
@@ -38,8 +39,8 @@ def key_validator(keys: Sequence[str] | KeysView[str]) -> Validator:
38
39
  def yes_no_validator() -> Validator:
39
40
  """Validator for yes/no inputs."""
40
41
 
41
- def validate(input: str) -> bool:
42
- if input.upper() not in ["Y", "N"]:
42
+ def validate(text: str) -> bool:
43
+ if text.upper() not in ["Y", "N"]:
43
44
  return False
44
45
  return True
45
46
 
falyx/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.23"
1
+ __version__ = "0.1.25"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: falyx
3
- Version: 0.1.23
3
+ Version: 0.1.25
4
4
  Summary: Reliable and introspectable async CLI action framework.
5
5
  License: MIT
6
6
  Author: Roland Thomas Jr
@@ -12,6 +12,7 @@ Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Classifier: Programming Language :: Python :: 3.13
15
+ Requires-Dist: aiohttp (>=3.11,<4.0)
15
16
  Requires-Dist: prompt_toolkit (>=3.0,<4.0)
16
17
  Requires-Dist: pydantic (>=2.0,<3.0)
17
18
  Requires-Dist: python-json-logger (>=3.3.0,<4.0.0)
@@ -0,0 +1,46 @@
1
+ falyx/.pytyped,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ falyx/__init__.py,sha256=L40665QyjAqHQxHdxxY2_yPeDa4p0LE7Nu_2dkm08Ls,650
3
+ falyx/__main__.py,sha256=g_LwJieofK3DJzCYtpkAMEeOXhzSLQenb7pRVUqcf-Y,2152
4
+ falyx/action/__init__.py,sha256=P3Eh0lE2VunzxqwfLbZKxE6FEcdR_u5OROkDTBYgeP0,904
5
+ falyx/action/action.py,sha256=CJB9eeeEqBGkZHjMpG24eXHRjouKSfESCI1zWzoE7JQ,32488
6
+ falyx/action/action_factory.py,sha256=qhlx8-BAEiNDJrbzF0HZzipY09Ple6J7FxxNvoBda9Y,4228
7
+ falyx/action/http_action.py,sha256=aIieGHyZSkz1ZGay-fwgDYZ0QF17XypAWtKeVAYp5f4,5806
8
+ falyx/action/io_action.py,sha256=zdDq07zSLlaShBQ3ztXTRC6aZL0JoERNZSmvHy1V22w,9718
9
+ falyx/action/menu_action.py,sha256=8qttPuq0AUh_oFaa3A82e19dSl4ZhQ9Y_j5CU7zHAlc,5532
10
+ falyx/action/select_file_action.py,sha256=hHLhmTSacWaUXhRTeIIiXt8gR7zbjkXJ2MAkKQYCpp4,7799
11
+ falyx/action/selection_action.py,sha256=22rF7UqRrQAMjGIheDqAbUizVMBg9aCl9e4VOLLZZJo,8811
12
+ falyx/action/signal_action.py,sha256=5UMqvzy7fBnLANGwYUWoe1VRhrr7e-yOVeLdOnCBiJo,1350
13
+ falyx/action/types.py,sha256=iVD-bHm1GRXOTIlHOeT_KcDBRZm4Hz5Xzl_BOalvEf4,961
14
+ falyx/bottom_bar.py,sha256=iWxgOKWgn5YmREeZBuGA50FzqzEfz1-Vnqm0V_fhldc,7383
15
+ falyx/command.py,sha256=s7r9aeUYEk9iUNE69JQtlFoPx9AehTxkHMPxpLKVIOA,12238
16
+ falyx/config.py,sha256=yg5KHkiZh4sNOPrkqL-ym0YrMUomBqUSyuOcXFOp6Ew,7204
17
+ falyx/config_schema.py,sha256=j5GQuHVlaU-VLxLF9t8idZRjqOP9MIKp1hyd9NhpAGU,3124
18
+ falyx/context.py,sha256=FNF-IS7RMDxel2l3kskEqQImZ0mLO6zvGw_xC9cIzgI,10338
19
+ falyx/debug.py,sha256=oWWTLOF8elrx_RGZ1G4pbzfFr46FjB0woFXpVU2wmjU,1567
20
+ falyx/exceptions.py,sha256=Qxp6UScZWEyno-6Lgksrv3s9iwjbr2U-d6hun-_xpc0,798
21
+ falyx/execution_registry.py,sha256=re56TImfL67p30ZlVBjqxz9Nn34SD4gvTlwFVPSzVCM,4712
22
+ falyx/falyx.py,sha256=cSCVtLsW8n5ZfRvjxVTJF5Rf3Qg1pNWWVqRdqSHTEGo,40545
23
+ falyx/hook_manager.py,sha256=GuGxVVz9FXrU39Tk220QcsLsMXeut7ZDkGW3hU9GcwQ,2952
24
+ falyx/hooks.py,sha256=IV2nbj5FjY2m3_L7x4mYBnaRDG45E8tWQU90i4butlw,2940
25
+ falyx/init.py,sha256=abcSlPmxVeByLIHdUkNjqtO_tEkO3ApC6f9WbxsSEWg,3393
26
+ falyx/logger.py,sha256=1Mfb_vJFJ1tQwziuyU2p-cSMi2Js8N2byniFEnI6vOQ,132
27
+ falyx/menu.py,sha256=faxGgocqQYY6HtzVbenHaFj8YqsmycBEyziC8Ahzqjo,2870
28
+ falyx/options_manager.py,sha256=dFAnQw543tQ6Xupvh1PwBrhiSWlSACHw8K-sHP_lUh4,2842
29
+ falyx/parsers.py,sha256=hxrBouQEqdgk6aWzNa7UwTg7u55vJffSEUUTiiQoI0U,5602
30
+ falyx/prompt_utils.py,sha256=qgk0bXs7mwzflqzWyFhEOTpKQ_ZtMIqGhKeg-ocwNnE,1542
31
+ falyx/protocols.py,sha256=dXNS-kh-5XB92PE5POy4uJ4KLT0O3ZAoiqw55jgR2IM,306
32
+ falyx/retry.py,sha256=UUzY6FlKobr84Afw7yJO9rj3AIQepDk2fcWs6_1gi6Q,3788
33
+ falyx/retry_utils.py,sha256=EAzc-ECTu8AxKkmlw28ioOW9y-Y9tLQ0KasvSkBRYgs,694
34
+ falyx/selection.py,sha256=l2LLISqgP8xfHdcTAEbTTqs_Bae4-LVUKMN7VQH7tM0,10731
35
+ falyx/signals.py,sha256=4PTuVRB_P_aWfnU8pANqhMxGTLq7TJDEyk9jCp0Bx2c,713
36
+ falyx/tagged_table.py,sha256=4SV-SdXFrAhy1JNToeBCvyxT-iWVf6cWY7XETTys4n8,1067
37
+ falyx/themes/__init__.py,sha256=1CZhEUCin9cUk8IGYBUFkVvdHRNNJBEFXccHwpUKZCA,284
38
+ falyx/themes/colors.py,sha256=4aaeAHJetmeNInI0Zytg4E3YqKfPFelpf04vtjSvsS8,19776
39
+ falyx/utils.py,sha256=uss-FV8p164pmhoqYtQt8gNp5z8fGbuMAk4dRJ6RopI,6717
40
+ falyx/validators.py,sha256=t5iyzVpY8tdC4rfhr4isEfWpD5gNTzjeX_Hbi_Uq6sA,1328
41
+ falyx/version.py,sha256=Ej7LsXg-6CASlaEHsZkUoLDpYEfHeFKdIeXMIM0esgA,23
42
+ falyx-0.1.25.dist-info/LICENSE,sha256=B0yqgaHuSdhN7T3OBmgQSiDTy8HqT5Oe_dLypRe4Ra4,1073
43
+ falyx-0.1.25.dist-info/METADATA,sha256=ZFvg_e4wFYKOB5f85YQswxEk1bQ9H3Eg6di63jcLrkU,5521
44
+ falyx-0.1.25.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
45
+ falyx-0.1.25.dist-info/entry_points.txt,sha256=j8owOSl2j1Ss8DtGMnKfgehKaolqnIPhVFHaUBLUnMs,45
46
+ falyx-0.1.25.dist-info/RECORD,,
falyx/signal_action.py DELETED
@@ -1,30 +0,0 @@
1
- # Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
2
- from falyx.action import Action
3
- from falyx.signals import FlowSignal
4
-
5
-
6
- class SignalAction(Action):
7
- """
8
- An action that raises a control flow signal when executed.
9
-
10
- Useful for exiting a menu, going back, or halting execution gracefully.
11
- """
12
-
13
- def __init__(self, name: str, signal: Exception):
14
- if not isinstance(signal, FlowSignal):
15
- raise TypeError(
16
- f"Signal must be an FlowSignal instance, got {type(signal).__name__}"
17
- )
18
-
19
- async def raise_signal(*args, **kwargs):
20
- raise signal
21
-
22
- super().__init__(name=name, action=raise_signal)
23
- self._signal = signal
24
-
25
- @property
26
- def signal(self):
27
- return self._signal
28
-
29
- def __str__(self):
30
- return f"SignalAction(name={self.name}, signal={self._signal.__class__.__name__})"
@@ -1,41 +0,0 @@
1
- falyx/.pytyped,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- falyx/__init__.py,sha256=dYRamQJlT1Zoy5Uu1uG4NCV05Xk98nN1LAQrSR1CT2A,643
3
- falyx/__main__.py,sha256=g_LwJieofK3DJzCYtpkAMEeOXhzSLQenb7pRVUqcf-Y,2152
4
- falyx/action.py,sha256=J-SG5zltYbqtdvTwBBUeEj4jp44DOKBR6G5rvmdkkTs,32147
5
- falyx/action_factory.py,sha256=VDy-EcdAs8-Xu-HVMeQi7NGZWmT2MP7AWYKhmcSsNDE,3693
6
- falyx/bottom_bar.py,sha256=NTen52Nfz32eWSBmJtEUuJO33u5sGQj-33IeudPVsqQ,7403
7
- falyx/command.py,sha256=8J3xeHw3fYiqf05EUbXd--aEIJso5bzxb5JECGuISQk,12199
8
- falyx/config.py,sha256=FyM9euPgEDS9kmL8foO-qAOeV8IqCEj2L4vc5SlzNA4,6959
9
- falyx/config_schema.py,sha256=j5GQuHVlaU-VLxLF9t8idZRjqOP9MIKp1hyd9NhpAGU,3124
10
- falyx/context.py,sha256=Dm7HV-eigU-aTv5ERah6Ow9fIRdrOsB1G6ETPIu42Gw,10070
11
- falyx/debug.py,sha256=-jbTti29UC5zP9qQlWs3TbkOQR2f3zKSuNluh-r56wY,1551
12
- falyx/exceptions.py,sha256=YVbhPp2BNvZoO_xqeGSRKHVQ2rdLOLf1HCjH4JTj9w8,776
13
- falyx/execution_registry.py,sha256=lZVQBuuyijuOcFcYFmKmLe-wofKjYz2NiY3dhdRLuTI,2932
14
- falyx/falyx.py,sha256=M6M8s4Rq-aYelDGH4NJYgdXKBNMnzfwux57GJLnDthY,41322
15
- falyx/hook_manager.py,sha256=E9Vk4bdoUTeXPQ_BQEvY2Jt-jUAusc40LI8JDy3NLUw,2381
16
- falyx/hooks.py,sha256=9zXk62DsJLJrmwTdyeNy5s-rVRvl8feuYRrfMmz6cVQ,2802
17
- falyx/http_action.py,sha256=JfopEleXJ0goVHi0VCn983c22GrmJhobnPIP7sTRqzU,5796
18
- falyx/init.py,sha256=RPD2CBIqjOGGjW545IaCKUbjGsE_XnScuuDSrP058uM,3379
19
- falyx/io_action.py,sha256=hrMT2JKWvFDOPgwTJSHCz8OiGkxl-bULhm6NoIBLA1g,9602
20
- falyx/menu_action.py,sha256=kagtnn3djDxUm_Cyynp0lj-sZ9D_FZn4IEBYnFYqB74,7986
21
- falyx/options_manager.py,sha256=yYpn-moYN-bRYgMLccmi_de4mUzhTT7cv_bR2FFWZ8c,2798
22
- falyx/parsers.py,sha256=r2FZTN26PqrnEQG4hVPorzzTPQZihsb4ca23fQY4Lgo,5574
23
- falyx/prompt_utils.py,sha256=l2uyem7f_lrvsh7L62BcJ9cAwoRSjo4NFsN43UgrBhs,624
24
- falyx/protocols.py,sha256=c32UniP5SKeoxHINZyuXrpSAOjlOKjYJ-SvsVcrgFjg,280
25
- falyx/retry.py,sha256=GncBUiDDfDHUvLsWsWQw2Nq2XYL0TR0Fne3iXPzvQ48,3551
26
- falyx/retry_utils.py,sha256=SN5apcsg71IG2-KylysqdJd-PkPBLoCVwsgrSTF9wrQ,666
27
- falyx/select_file_action.py,sha256=EWM_qpHtzj5Ol7TSzKxDpevgym6QIwAzJFqLkg8x6IU,8610
28
- falyx/selection.py,sha256=bgMYVHicE8aQXdvccxOK2i5ijtftUMlRyT-wsGSogHQ,10607
29
- falyx/selection_action.py,sha256=oBAJ2r9-O27BYk4Lkx_vBUDNrHuC4JyIROfL0MGZOd8,8339
30
- falyx/signal_action.py,sha256=wsG-Rmgif2Q1AACY-Ie7oyGdbk9AyYvAHSg7mFxNprI,893
31
- falyx/signals.py,sha256=tlUbz3x6z3rYlUggan_Ntoy4bU5RbOd8UfR4cNcV6kQ,694
32
- falyx/tagged_table.py,sha256=sn2kosRRpcpeMB8vKk47c9yjpffSz_9FXH_e6kw15mA,1019
33
- falyx/themes/colors.py,sha256=4aaeAHJetmeNInI0Zytg4E3YqKfPFelpf04vtjSvsS8,19776
34
- falyx/utils.py,sha256=b1GQ3ooz4Io3zPE7MsoDm7j42AioTG-ZcWH-N2TRpbI,7710
35
- falyx/validators.py,sha256=NMxqCk8Fr8HQGVDYpg8B_JRk5SKR41E_G9gj1YfQnxg,1316
36
- falyx/version.py,sha256=0byemO6n6WCv41u9vBG2AIsOkVbxLvok7puvwy8EhfU,23
37
- falyx-0.1.23.dist-info/LICENSE,sha256=B0yqgaHuSdhN7T3OBmgQSiDTy8HqT5Oe_dLypRe4Ra4,1073
38
- falyx-0.1.23.dist-info/METADATA,sha256=j9Eamk8lsuPAByILQpiGVB3hyVoDnqRzf7gOAxJB62E,5484
39
- falyx-0.1.23.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
40
- falyx-0.1.23.dist-info/entry_points.txt,sha256=j8owOSl2j1Ss8DtGMnKfgehKaolqnIPhVFHaUBLUnMs,45
41
- falyx-0.1.23.dist-info/RECORD,,
File without changes