Rename falyx.action.types.FileReturnType -> falyx.action.action_types.FileType, falyx.action.base -> falyx.action.base_action, argparse tweaks for custom cli programs
This commit is contained in:
@ -2,19 +2,24 @@ import asyncio
|
|||||||
|
|
||||||
from falyx import Falyx
|
from falyx import Falyx
|
||||||
from falyx.action import SelectFileAction
|
from falyx.action import SelectFileAction
|
||||||
from falyx.action.types import FileReturnType
|
from falyx.action.action_types import FileType
|
||||||
|
|
||||||
sf = SelectFileAction(
|
sf = SelectFileAction(
|
||||||
name="select_file",
|
name="select_file",
|
||||||
suffix_filter=".yaml",
|
suffix_filter=".yaml",
|
||||||
title="Select a YAML file",
|
title="Select a YAML file",
|
||||||
prompt_message="Choose 2 > ",
|
prompt_message="Choose 2 > ",
|
||||||
return_type=FileReturnType.TEXT,
|
return_type=FileType.TEXT,
|
||||||
columns=3,
|
columns=3,
|
||||||
number_selections=2,
|
number_selections=2,
|
||||||
)
|
)
|
||||||
|
|
||||||
flx = Falyx()
|
flx = Falyx(
|
||||||
|
title="File Selection Example",
|
||||||
|
description="This example demonstrates how to select files using Falyx.",
|
||||||
|
version="1.0.0",
|
||||||
|
program="file_select.py",
|
||||||
|
)
|
||||||
|
|
||||||
flx.add_command(
|
flx.add_command(
|
||||||
key="S",
|
key="S",
|
||||||
|
@ -8,7 +8,7 @@ Licensed under the MIT License. See LICENSE file for details.
|
|||||||
from .action import Action
|
from .action import Action
|
||||||
from .action_factory import ActionFactoryAction
|
from .action_factory import ActionFactoryAction
|
||||||
from .action_group import ActionGroup
|
from .action_group import ActionGroup
|
||||||
from .base import BaseAction
|
from .base_action import BaseAction
|
||||||
from .chained_action import ChainedAction
|
from .chained_action import ChainedAction
|
||||||
from .fallback_action import FallbackAction
|
from .fallback_action import FallbackAction
|
||||||
from .http_action import HTTPAction
|
from .http_action import HTTPAction
|
||||||
|
@ -6,7 +6,7 @@ from typing import Any, Callable
|
|||||||
|
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.context import ExecutionContext
|
from falyx.context import ExecutionContext
|
||||||
from falyx.execution_registry import ExecutionRegistry as er
|
from falyx.execution_registry import ExecutionRegistry as er
|
||||||
from falyx.hook_manager import HookManager, HookType
|
from falyx.hook_manager import HookManager, HookType
|
||||||
|
@ -4,7 +4,7 @@ from typing import Any, Callable
|
|||||||
|
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.context import ExecutionContext
|
from falyx.context import ExecutionContext
|
||||||
from falyx.execution_registry import ExecutionRegistry as er
|
from falyx.execution_registry import ExecutionRegistry as er
|
||||||
from falyx.hook_manager import HookType
|
from falyx.hook_manager import HookType
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
"""action_group.py"""
|
"""action_group.py"""
|
||||||
import asyncio
|
import asyncio
|
||||||
import random
|
import random
|
||||||
from typing import Any, Callable
|
from typing import Any, Callable, Sequence
|
||||||
|
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
from falyx.action.action import Action
|
from falyx.action.action import Action
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.action.mixins import ActionListMixin
|
from falyx.action.mixins import ActionListMixin
|
||||||
from falyx.context import ExecutionContext, SharedContext
|
from falyx.context import ExecutionContext, SharedContext
|
||||||
from falyx.execution_registry import ExecutionRegistry as er
|
from falyx.execution_registry import ExecutionRegistry as er
|
||||||
@ -54,7 +54,7 @@ class ActionGroup(BaseAction, ActionListMixin):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
name: str,
|
name: str,
|
||||||
actions: list[BaseAction] | None = None,
|
actions: Sequence[BaseAction | Callable[..., Any]] | None = None,
|
||||||
*,
|
*,
|
||||||
hooks: HookManager | None = None,
|
hooks: HookManager | None = None,
|
||||||
inject_last_result: bool = False,
|
inject_last_result: bool = False,
|
||||||
@ -70,7 +70,7 @@ class ActionGroup(BaseAction, ActionListMixin):
|
|||||||
if actions:
|
if actions:
|
||||||
self.set_actions(actions)
|
self.set_actions(actions)
|
||||||
|
|
||||||
def _wrap_if_needed(self, action: BaseAction | Any) -> BaseAction:
|
def _wrap_if_needed(self, action: BaseAction | Callable[..., Any]) -> BaseAction:
|
||||||
if isinstance(action, BaseAction):
|
if isinstance(action, BaseAction):
|
||||||
return action
|
return action
|
||||||
elif callable(action):
|
elif callable(action):
|
||||||
@ -81,12 +81,18 @@ class ActionGroup(BaseAction, ActionListMixin):
|
|||||||
f"{type(action).__name__}"
|
f"{type(action).__name__}"
|
||||||
)
|
)
|
||||||
|
|
||||||
def add_action(self, action: BaseAction | Any) -> None:
|
def add_action(self, action: BaseAction | Callable[..., Any]) -> None:
|
||||||
action = self._wrap_if_needed(action)
|
action = self._wrap_if_needed(action)
|
||||||
super().add_action(action)
|
super().add_action(action)
|
||||||
if hasattr(action, "register_teardown") and callable(action.register_teardown):
|
if hasattr(action, "register_teardown") and callable(action.register_teardown):
|
||||||
action.register_teardown(self.hooks)
|
action.register_teardown(self.hooks)
|
||||||
|
|
||||||
|
def set_actions(self, actions: Sequence[BaseAction | Callable[..., Any]]) -> None:
|
||||||
|
"""Replaces the current action list with a new one."""
|
||||||
|
self.actions.clear()
|
||||||
|
for action in actions:
|
||||||
|
self.add_action(action)
|
||||||
|
|
||||||
def get_infer_target(self) -> tuple[Callable[..., Any] | None, dict[str, Any] | None]:
|
def get_infer_target(self) -> tuple[Callable[..., Any] | None, dict[str, Any] | None]:
|
||||||
arg_defs = same_argument_definitions(self.actions)
|
arg_defs = same_argument_definitions(self.actions)
|
||||||
if arg_defs:
|
if arg_defs:
|
||||||
|
@ -5,7 +5,7 @@ from __future__ import annotations
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
class FileReturnType(Enum):
|
class FileType(Enum):
|
||||||
"""Enum for file return types."""
|
"""Enum for file return types."""
|
||||||
|
|
||||||
TEXT = "text"
|
TEXT = "text"
|
||||||
@ -28,7 +28,7 @@ class FileReturnType(Enum):
|
|||||||
return aliases.get(value, value)
|
return aliases.get(value, value)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _missing_(cls, value: object) -> FileReturnType:
|
def _missing_(cls, value: object) -> FileType:
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
normalized = value.lower()
|
normalized = value.lower()
|
||||||
alias = cls._get_alias(normalized)
|
alias = cls._get_alias(normalized)
|
||||||
@ -36,7 +36,7 @@ class FileReturnType(Enum):
|
|||||||
if member.value == alias:
|
if member.value == alias:
|
||||||
return member
|
return member
|
||||||
valid = ", ".join(member.value for member in cls)
|
valid = ", ".join(member.value for member in cls)
|
||||||
raise ValueError(f"Invalid FileReturnType: '{value}'. Must be one of: {valid}")
|
raise ValueError(f"Invalid FileType: '{value}'. Must be one of: {valid}")
|
||||||
|
|
||||||
|
|
||||||
class SelectionReturnType(Enum):
|
class SelectionReturnType(Enum):
|
@ -1,5 +1,5 @@
|
|||||||
# Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
|
# Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
|
||||||
"""base.py
|
"""base_action.py
|
||||||
|
|
||||||
Core action system for Falyx.
|
Core action system for Falyx.
|
||||||
|
|
@ -2,12 +2,12 @@
|
|||||||
"""chained_action.py"""
|
"""chained_action.py"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any, Callable
|
from typing import Any, Callable, Sequence
|
||||||
|
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
from falyx.action.action import Action
|
from falyx.action.action import Action
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.action.fallback_action import FallbackAction
|
from falyx.action.fallback_action import FallbackAction
|
||||||
from falyx.action.literal_input_action import LiteralInputAction
|
from falyx.action.literal_input_action import LiteralInputAction
|
||||||
from falyx.action.mixins import ActionListMixin
|
from falyx.action.mixins import ActionListMixin
|
||||||
@ -47,7 +47,7 @@ class ChainedAction(BaseAction, ActionListMixin):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
name: str,
|
name: str,
|
||||||
actions: list[BaseAction | Any] | None = None,
|
actions: Sequence[BaseAction | Callable[..., Any]] | None = None,
|
||||||
*,
|
*,
|
||||||
hooks: HookManager | None = None,
|
hooks: HookManager | None = None,
|
||||||
inject_last_result: bool = False,
|
inject_last_result: bool = False,
|
||||||
@ -67,7 +67,7 @@ class ChainedAction(BaseAction, ActionListMixin):
|
|||||||
if actions:
|
if actions:
|
||||||
self.set_actions(actions)
|
self.set_actions(actions)
|
||||||
|
|
||||||
def _wrap_if_needed(self, action: BaseAction | Any) -> BaseAction:
|
def _wrap_if_needed(self, action: BaseAction | Callable[..., Any]) -> BaseAction:
|
||||||
if isinstance(action, BaseAction):
|
if isinstance(action, BaseAction):
|
||||||
return action
|
return action
|
||||||
elif callable(action):
|
elif callable(action):
|
||||||
@ -75,7 +75,7 @@ class ChainedAction(BaseAction, ActionListMixin):
|
|||||||
else:
|
else:
|
||||||
return LiteralInputAction(action)
|
return LiteralInputAction(action)
|
||||||
|
|
||||||
def add_action(self, action: BaseAction | Any) -> None:
|
def add_action(self, action: BaseAction | Callable[..., Any]) -> None:
|
||||||
action = self._wrap_if_needed(action)
|
action = self._wrap_if_needed(action)
|
||||||
if self.actions and self.auto_inject and not action.inject_last_result:
|
if self.actions and self.auto_inject and not action.inject_last_result:
|
||||||
action.inject_last_result = True
|
action.inject_last_result = True
|
||||||
@ -83,6 +83,12 @@ class ChainedAction(BaseAction, ActionListMixin):
|
|||||||
if hasattr(action, "register_teardown") and callable(action.register_teardown):
|
if hasattr(action, "register_teardown") and callable(action.register_teardown):
|
||||||
action.register_teardown(self.hooks)
|
action.register_teardown(self.hooks)
|
||||||
|
|
||||||
|
def set_actions(self, actions: Sequence[BaseAction | Callable[..., Any]]) -> None:
|
||||||
|
"""Replaces the current action list with a new one."""
|
||||||
|
self.actions.clear()
|
||||||
|
for action in actions:
|
||||||
|
self.add_action(action)
|
||||||
|
|
||||||
def get_infer_target(self) -> tuple[Callable[..., Any] | None, dict[str, Any] | None]:
|
def get_infer_target(self) -> tuple[Callable[..., Any] | None, dict[str, Any] | None]:
|
||||||
if self.actions:
|
if self.actions:
|
||||||
return self.actions[0].get_infer_target()
|
return self.actions[0].get_infer_target()
|
||||||
|
@ -21,7 +21,7 @@ from typing import Any, Callable
|
|||||||
|
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.context import ExecutionContext
|
from falyx.context import ExecutionContext
|
||||||
from falyx.execution_registry import ExecutionRegistry as er
|
from falyx.execution_registry import ExecutionRegistry as er
|
||||||
from falyx.hook_manager import HookManager, HookType
|
from falyx.hook_manager import HookManager, HookType
|
||||||
|
@ -7,7 +7,7 @@ from rich.console import Console
|
|||||||
from rich.table import Table
|
from rich.table import Table
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.context import ExecutionContext
|
from falyx.context import ExecutionContext
|
||||||
from falyx.execution_registry import ExecutionRegistry as er
|
from falyx.execution_registry import ExecutionRegistry as er
|
||||||
from falyx.hook_manager import HookType
|
from falyx.hook_manager import HookType
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
# Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
|
# Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
|
||||||
"""mixins.py"""
|
"""mixins.py"""
|
||||||
from falyx.action.base import BaseAction
|
from typing import Sequence
|
||||||
|
|
||||||
|
from falyx.action.base_action import BaseAction
|
||||||
|
|
||||||
|
|
||||||
class ActionListMixin:
|
class ActionListMixin:
|
||||||
@ -9,7 +11,7 @@ class ActionListMixin:
|
|||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.actions: list[BaseAction] = []
|
self.actions: list[BaseAction] = []
|
||||||
|
|
||||||
def set_actions(self, actions: list[BaseAction]) -> None:
|
def set_actions(self, actions: Sequence[BaseAction]) -> None:
|
||||||
"""Replaces the current action list with a new one."""
|
"""Replaces the current action list with a new one."""
|
||||||
self.actions.clear()
|
self.actions.clear()
|
||||||
for action in actions:
|
for action in actions:
|
||||||
|
@ -9,7 +9,7 @@ from typing import Any, Callable
|
|||||||
|
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.context import ExecutionContext
|
from falyx.context import ExecutionContext
|
||||||
from falyx.execution_registry import ExecutionRegistry as er
|
from falyx.execution_registry import ExecutionRegistry as er
|
||||||
from falyx.hook_manager import HookManager, HookType
|
from falyx.hook_manager import HookManager, HookType
|
||||||
|
@ -11,7 +11,7 @@ from typing import Any, Callable
|
|||||||
|
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.context import ExecutionContext, SharedContext
|
from falyx.context import ExecutionContext, SharedContext
|
||||||
from falyx.execution_registry import ExecutionRegistry as er
|
from falyx.execution_registry import ExecutionRegistry as er
|
||||||
from falyx.hook_manager import HookManager, HookType
|
from falyx.hook_manager import HookManager, HookType
|
||||||
|
@ -7,7 +7,7 @@ from prompt_toolkit.formatted_text import FormattedText, merge_formatted_text
|
|||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.context import ExecutionContext
|
from falyx.context import ExecutionContext
|
||||||
from falyx.execution_registry import ExecutionRegistry as er
|
from falyx.execution_registry import ExecutionRegistry as er
|
||||||
from falyx.hook_manager import HookType
|
from falyx.hook_manager import HookType
|
||||||
|
@ -14,8 +14,8 @@ from prompt_toolkit import PromptSession
|
|||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.action_types import FileType
|
||||||
from falyx.action.types import FileReturnType
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.context import ExecutionContext
|
from falyx.context import ExecutionContext
|
||||||
from falyx.execution_registry import ExecutionRegistry as er
|
from falyx.execution_registry import ExecutionRegistry as er
|
||||||
from falyx.hook_manager import HookType
|
from falyx.hook_manager import HookType
|
||||||
@ -50,7 +50,7 @@ class SelectFileAction(BaseAction):
|
|||||||
prompt_message (str): Message to display when prompting for selection.
|
prompt_message (str): Message to display when prompting for selection.
|
||||||
style (str): Style for the selection options.
|
style (str): Style for the selection options.
|
||||||
suffix_filter (str | None): Restrict to certain file types.
|
suffix_filter (str | None): Restrict to certain file types.
|
||||||
return_type (FileReturnType): What to return (path, content, parsed).
|
return_type (FileType): What to return (path, content, parsed).
|
||||||
console (Console | None): Console instance for output.
|
console (Console | None): Console instance for output.
|
||||||
prompt_session (PromptSession | None): Prompt session for user input.
|
prompt_session (PromptSession | None): Prompt session for user input.
|
||||||
"""
|
"""
|
||||||
@ -65,7 +65,7 @@ class SelectFileAction(BaseAction):
|
|||||||
prompt_message: str = "Choose > ",
|
prompt_message: str = "Choose > ",
|
||||||
style: str = OneColors.WHITE,
|
style: str = OneColors.WHITE,
|
||||||
suffix_filter: str | None = None,
|
suffix_filter: str | None = None,
|
||||||
return_type: FileReturnType | str = FileReturnType.PATH,
|
return_type: FileType | str = FileType.PATH,
|
||||||
number_selections: int | str = 1,
|
number_selections: int | str = 1,
|
||||||
separator: str = ",",
|
separator: str = ",",
|
||||||
allow_duplicates: bool = False,
|
allow_duplicates: bool = False,
|
||||||
@ -104,35 +104,35 @@ class SelectFileAction(BaseAction):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("number_selections must be a positive integer or one of '*'")
|
raise ValueError("number_selections must be a positive integer or one of '*'")
|
||||||
|
|
||||||
def _coerce_return_type(self, return_type: FileReturnType | str) -> FileReturnType:
|
def _coerce_return_type(self, return_type: FileType | str) -> FileType:
|
||||||
if isinstance(return_type, FileReturnType):
|
if isinstance(return_type, FileType):
|
||||||
return return_type
|
return return_type
|
||||||
return FileReturnType(return_type)
|
return FileType(return_type)
|
||||||
|
|
||||||
def get_options(self, files: list[Path]) -> dict[str, SelectionOption]:
|
def get_options(self, files: list[Path]) -> dict[str, SelectionOption]:
|
||||||
value: Any
|
value: Any
|
||||||
options = {}
|
options = {}
|
||||||
for index, file in enumerate(files):
|
for index, file in enumerate(files):
|
||||||
try:
|
try:
|
||||||
if self.return_type == FileReturnType.TEXT:
|
if self.return_type == FileType.TEXT:
|
||||||
value = file.read_text(encoding="UTF-8")
|
value = file.read_text(encoding="UTF-8")
|
||||||
elif self.return_type == FileReturnType.PATH:
|
elif self.return_type == FileType.PATH:
|
||||||
value = file
|
value = file
|
||||||
elif self.return_type == FileReturnType.JSON:
|
elif self.return_type == FileType.JSON:
|
||||||
value = json.loads(file.read_text(encoding="UTF-8"))
|
value = json.loads(file.read_text(encoding="UTF-8"))
|
||||||
elif self.return_type == FileReturnType.TOML:
|
elif self.return_type == FileType.TOML:
|
||||||
value = toml.loads(file.read_text(encoding="UTF-8"))
|
value = toml.loads(file.read_text(encoding="UTF-8"))
|
||||||
elif self.return_type == FileReturnType.YAML:
|
elif self.return_type == FileType.YAML:
|
||||||
value = yaml.safe_load(file.read_text(encoding="UTF-8"))
|
value = yaml.safe_load(file.read_text(encoding="UTF-8"))
|
||||||
elif self.return_type == FileReturnType.CSV:
|
elif self.return_type == FileType.CSV:
|
||||||
with open(file, newline="", encoding="UTF-8") as csvfile:
|
with open(file, newline="", encoding="UTF-8") as csvfile:
|
||||||
reader = csv.reader(csvfile)
|
reader = csv.reader(csvfile)
|
||||||
value = list(reader)
|
value = list(reader)
|
||||||
elif self.return_type == FileReturnType.TSV:
|
elif self.return_type == FileType.TSV:
|
||||||
with open(file, newline="", encoding="UTF-8") as tsvfile:
|
with open(file, newline="", encoding="UTF-8") as tsvfile:
|
||||||
reader = csv.reader(tsvfile, delimiter="\t")
|
reader = csv.reader(tsvfile, delimiter="\t")
|
||||||
value = list(reader)
|
value = list(reader)
|
||||||
elif self.return_type == FileReturnType.XML:
|
elif self.return_type == FileType.XML:
|
||||||
tree = ET.parse(file, parser=ET.XMLParser(encoding="UTF-8"))
|
tree = ET.parse(file, parser=ET.XMLParser(encoding="UTF-8"))
|
||||||
root = tree.getroot()
|
root = tree.getroot()
|
||||||
value = ET.tostring(root, encoding="unicode")
|
value = ET.tostring(root, encoding="unicode")
|
||||||
|
@ -6,8 +6,8 @@ from prompt_toolkit import PromptSession
|
|||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.action_types import SelectionReturnType
|
||||||
from falyx.action.types import SelectionReturnType
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.context import ExecutionContext
|
from falyx.context import ExecutionContext
|
||||||
from falyx.execution_registry import ExecutionRegistry as er
|
from falyx.execution_registry import ExecutionRegistry as er
|
||||||
from falyx.hook_manager import HookType
|
from falyx.hook_manager import HookType
|
||||||
|
@ -5,7 +5,7 @@ from prompt_toolkit.validation import Validator
|
|||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.context import ExecutionContext
|
from falyx.context import ExecutionContext
|
||||||
from falyx.execution_registry import ExecutionRegistry as er
|
from falyx.execution_registry import ExecutionRegistry as er
|
||||||
from falyx.hook_manager import HookType
|
from falyx.hook_manager import HookType
|
||||||
|
@ -27,7 +27,7 @@ from rich.console import Console
|
|||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
from falyx.action.action import Action
|
from falyx.action.action import Action
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.context import ExecutionContext
|
from falyx.context import ExecutionContext
|
||||||
from falyx.debug import register_debug_hooks
|
from falyx.debug import register_debug_hooks
|
||||||
from falyx.execution_registry import ExecutionRegistry as er
|
from falyx.execution_registry import ExecutionRegistry as er
|
||||||
|
@ -14,7 +14,7 @@ from pydantic import BaseModel, Field, field_validator, model_validator
|
|||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
|
|
||||||
from falyx.action.action import Action
|
from falyx.action.action import Action
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.command import Command
|
from falyx.command import Command
|
||||||
from falyx.falyx import Falyx
|
from falyx.falyx import Falyx
|
||||||
from falyx.logger import logger
|
from falyx.logger import logger
|
||||||
|
@ -43,7 +43,7 @@ from rich.markdown import Markdown
|
|||||||
from rich.table import Table
|
from rich.table import Table
|
||||||
|
|
||||||
from falyx.action.action import Action
|
from falyx.action.action import Action
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.bottom_bar import BottomBar
|
from falyx.bottom_bar import BottomBar
|
||||||
from falyx.command import Command
|
from falyx.command import Command
|
||||||
from falyx.context import ExecutionContext
|
from falyx.context import ExecutionContext
|
||||||
@ -346,7 +346,6 @@ class Falyx:
|
|||||||
aliases=["HISTORY"],
|
aliases=["HISTORY"],
|
||||||
action=Action(name="View Execution History", action=er.summary),
|
action=Action(name="View Execution History", action=er.summary),
|
||||||
style=OneColors.DARK_YELLOW,
|
style=OneColors.DARK_YELLOW,
|
||||||
simple_help_signature=True,
|
|
||||||
arg_parser=parser,
|
arg_parser=parser,
|
||||||
help_text="View the execution history of commands.",
|
help_text="View the execution history of commands.",
|
||||||
)
|
)
|
||||||
@ -1152,7 +1151,7 @@ class Falyx:
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
if self.cli_args.command == "version" or self.cli_args.version:
|
if self.cli_args.command == "version" or self.cli_args.version:
|
||||||
self.console.print(f"[{self.version_style}]{self.program} v{__version__}[/]")
|
self.console.print(f"[{self.version_style}]{self.program} v{self.version}[/]")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
if self.cli_args.command == "preview":
|
if self.cli_args.command == "preview":
|
||||||
|
@ -4,7 +4,7 @@ from dataclasses import dataclass
|
|||||||
|
|
||||||
from prompt_toolkit.formatted_text import FormattedText
|
from prompt_toolkit.formatted_text import FormattedText
|
||||||
|
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.signals import BackSignal, QuitSignal
|
from falyx.signals import BackSignal, QuitSignal
|
||||||
from falyx.themes import OneColors
|
from falyx.themes import OneColors
|
||||||
from falyx.utils import CaseInsensitiveDict
|
from falyx.utils import CaseInsensitiveDict
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.parser.argument_action import ArgumentAction
|
from falyx.parser.argument_action import ArgumentAction
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ from rich.console import Console
|
|||||||
from rich.markup import escape
|
from rich.markup import escape
|
||||||
from rich.text import Text
|
from rich.text import Text
|
||||||
|
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.exceptions import CommandArgumentError
|
from falyx.exceptions import CommandArgumentError
|
||||||
from falyx.parser.argument import Argument
|
from falyx.parser.argument import Argument
|
||||||
from falyx.parser.argument_action import ArgumentAction
|
from falyx.parser.argument_action import ArgumentAction
|
||||||
|
@ -76,14 +76,14 @@ def get_root_parser(
|
|||||||
help="Run in non-interactive mode with all prompts bypassed.",
|
help="Run in non-interactive mode with all prompts bypassed.",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-v", "--verbose", action="store_true", help="Enable debug logging for Falyx."
|
"-v", "--verbose", action="store_true", help=f"Enable debug logging for {prog}."
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--debug-hooks",
|
"--debug-hooks",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Enable default lifecycle debug logging",
|
help="Enable default lifecycle debug logging",
|
||||||
)
|
)
|
||||||
parser.add_argument("--version", action="store_true", help="Show Falyx version")
|
parser.add_argument("--version", action="store_true", help=f"Show {prog} version")
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@ -98,7 +98,6 @@ def get_subparsers(
|
|||||||
subparsers = parser.add_subparsers(
|
subparsers = parser.add_subparsers(
|
||||||
title=title,
|
title=title,
|
||||||
description=description,
|
description=description,
|
||||||
metavar="COMMAND",
|
|
||||||
dest="command",
|
dest="command",
|
||||||
)
|
)
|
||||||
return subparsers
|
return subparsers
|
||||||
@ -124,6 +123,8 @@ def get_arg_parsers(
|
|||||||
subparsers: _SubParsersAction | None = None,
|
subparsers: _SubParsersAction | None = None,
|
||||||
) -> FalyxParsers:
|
) -> FalyxParsers:
|
||||||
"""Returns the argument parser for the CLI."""
|
"""Returns the argument parser for the CLI."""
|
||||||
|
if epilog is None:
|
||||||
|
epilog = f"Tip: Use '{prog} run ?[COMMAND]' to preview any command from the CLI."
|
||||||
if root_parser is None:
|
if root_parser is None:
|
||||||
parser = get_root_parser(
|
parser = get_root_parser(
|
||||||
prog=prog,
|
prog=prog,
|
||||||
@ -145,7 +146,14 @@ def get_arg_parsers(
|
|||||||
parser = root_parser
|
parser = root_parser
|
||||||
|
|
||||||
if subparsers is None:
|
if subparsers is None:
|
||||||
subparsers = get_subparsers(parser)
|
if prog == "falyx":
|
||||||
|
subparsers = get_subparsers(
|
||||||
|
parser,
|
||||||
|
title="Falyx Commands",
|
||||||
|
description="Available commands for the Falyx CLI.",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
subparsers = get_subparsers(parser, title="subcommands", description=None)
|
||||||
if not isinstance(subparsers, _SubParsersAction):
|
if not isinstance(subparsers, _SubParsersAction):
|
||||||
raise TypeError("subparsers must be an instance of _SubParsersAction")
|
raise TypeError("subparsers must be an instance of _SubParsersAction")
|
||||||
|
|
||||||
@ -154,10 +162,10 @@ def get_arg_parsers(
|
|||||||
if isinstance(commands, dict):
|
if isinstance(commands, dict):
|
||||||
for command in commands.values():
|
for command in commands.values():
|
||||||
run_description.append(command.usage)
|
run_description.append(command.usage)
|
||||||
command_description = command.description or command.help_text
|
command_description = command.help_text or command.description
|
||||||
run_description.append(f"{' '*24}{command_description}")
|
run_description.append(f"{' '*24}{command_description}")
|
||||||
run_epilog = (
|
run_epilog = (
|
||||||
"Tip: Use 'falyx run ?[COMMAND]' to preview commands by their key or alias."
|
f"Tip: Use '{prog} run ?[COMMAND]' to preview commands by their key or alias."
|
||||||
)
|
)
|
||||||
run_parser = subparsers.add_parser(
|
run_parser = subparsers.add_parser(
|
||||||
"run",
|
"run",
|
||||||
@ -259,7 +267,7 @@ def get_arg_parsers(
|
|||||||
"-t", "--tag", help="Filter commands by tag (case-insensitive)", default=None
|
"-t", "--tag", help="Filter commands by tag (case-insensitive)", default=None
|
||||||
)
|
)
|
||||||
|
|
||||||
version_parser = subparsers.add_parser("version", help="Show the Falyx version")
|
version_parser = subparsers.add_parser("version", help=f"Show {prog} version")
|
||||||
|
|
||||||
return FalyxParsers(
|
return FalyxParsers(
|
||||||
root=parser,
|
root=parser,
|
||||||
|
@ -6,7 +6,7 @@ from typing import Any, Literal, Union, get_args, get_origin
|
|||||||
|
|
||||||
from dateutil import parser as date_parser
|
from dateutil import parser as date_parser
|
||||||
|
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.logger import logger
|
from falyx.logger import logger
|
||||||
from falyx.parser.signature import infer_args_from_func
|
from falyx.parser.signature import infer_args_from_func
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import Any, Awaitable, Protocol, runtime_checkable
|
from typing import Any, Awaitable, Protocol, runtime_checkable
|
||||||
|
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
|
|
||||||
|
|
||||||
@runtime_checkable
|
@runtime_checkable
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
|
# Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
|
||||||
"""retry_utils.py"""
|
"""retry_utils.py"""
|
||||||
from falyx.action.action import Action
|
from falyx.action.action import Action
|
||||||
from falyx.action.base import BaseAction
|
from falyx.action.base_action import BaseAction
|
||||||
from falyx.hook_manager import HookType
|
from falyx.hook_manager import HookType
|
||||||
from falyx.retry import RetryHandler, RetryPolicy
|
from falyx.retry import RetryHandler, RetryPolicy
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
__version__ = "0.1.52"
|
__version__ = "0.1.53"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "falyx"
|
name = "falyx"
|
||||||
version = "0.1.52"
|
version = "0.1.53"
|
||||||
description = "Reliable and introspectable async CLI action framework."
|
description = "Reliable and introspectable async CLI action framework."
|
||||||
authors = ["Roland Thomas Jr <roland@rtj.dev>"]
|
authors = ["Roland Thomas Jr <roland@rtj.dev>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
Reference in New Issue
Block a user