From 2d879561c9b79a2ce44371436c3535bc8fe64310 Mon Sep 17 00:00:00 2001 From: Roland Thomas Date: Thu, 1 May 2025 22:32:36 -0400 Subject: [PATCH] Change __main__ to load falyx config from predefined locations --- falyx/__main__.py | 177 ++++++++-------------------------------------- falyx/config.py | 10 ++- 2 files changed, 37 insertions(+), 150 deletions(-) diff --git a/falyx/__main__.py b/falyx/__main__.py index fc33a35..3cff04f 100644 --- a/falyx/__main__.py +++ b/falyx/__main__.py @@ -6,166 +6,47 @@ Licensed under the MIT License. See LICENSE file for details. """ import asyncio -import random -from argparse import Namespace +import sys +from pathlib import Path -from falyx.action import Action, ActionGroup, ChainedAction +from falyx.config import loader from falyx.falyx import Falyx -from falyx.parsers import FalyxParsers, get_arg_parsers -from falyx.version import __version__ +from falyx.parsers import get_arg_parsers -class Foo: - def __init__(self, flx: Falyx) -> None: - self.flx = flx - - async def build(self): - await asyncio.sleep(1) - print("โœ… Build complete!") - return "Build complete!" - - async def test(self): - await asyncio.sleep(1) - print("โœ… Tests passed!") - return "Tests passed!" - - async def deploy(self): - await asyncio.sleep(1) - print("โœ… Deployment complete!") - return "Deployment complete!" - - async def clean(self): - print("๐Ÿงน Cleaning...") - await asyncio.sleep(1) - print("โœ… Clean complete!") - return "Clean complete!" - - async def build_package(self): - print("๐Ÿ”จ Building...") - await asyncio.sleep(1) - print("โœ… Build finished!") - return "Build finished!" - - async def package(self): - print("๐Ÿ“ฆ Packaging...") - await asyncio.sleep(1) - print("โœ… Package complete!") - return "Package complete!" - - async def run_tests(self): - print("๐Ÿงช Running tests...") - await asyncio.sleep(random.randint(1, 3)) - print("โœ… Tests passed!") - return "Tests passed!" - - async def run_integration_tests(self): - print("๐Ÿ”— Running integration tests...") - await asyncio.sleep(random.randint(1, 3)) - print("โœ… Integration tests passed!") - return "Integration tests passed!" - - async def run_linter(self): - print("๐Ÿงน Running linter...") - await asyncio.sleep(random.randint(1, 3)) - print("โœ… Linter passed!") - return "Linter passed!" - - async def run(self): - await self.flx.run() +def find_falyx_config() -> Path | None: + candidates = [ + Path.cwd() / "falyx.yaml", + Path.cwd() / "falyx.toml", + Path.cwd() / ".falyx.yaml", + Path.home() / ".config" / "falyx" / "falyx.yaml", + Path.home() / ".falyx.yaml", + ] + return next((p for p in candidates if p.exists()), None) -def parse_args() -> Namespace: - parsers: FalyxParsers = get_arg_parsers() - return parsers.parse_args() +def bootstrap() -> Path | None: + config_path = find_falyx_config() + if config_path and str(config_path.parent) not in sys.path: + sys.path.insert(0, str(config_path.parent)) + return config_path + return None async def main() -> None: - """Build and return a Falyx instance with all your commands.""" - args = parse_args() + bootstrap_path = bootstrap() + if not bootstrap_path: + print("No Falyx config file found. Exiting.") + return None + args = get_arg_parsers().parse_args() flx = Falyx( - title="๐Ÿš€ Falyx CLI", + title="๐Ÿ› ๏ธ Config-Driven CLI", cli_args=args, - columns=5, - welcome_message="Welcome to Falyx CLI!", - exit_message="Goodbye!", + columns=4, ) - foo = Foo(flx) - - # --- Bottom bar info --- - flx.bottom_bar.columns = 3 - flx.bottom_bar.add_toggle_from_option("V", "Verbose", flx.options, "verbose") - flx.bottom_bar.add_toggle_from_option("U", "Debug Hooks", flx.options, "debug_hooks") - flx.bottom_bar.add_static("Version", f"Falyx v{__version__}") - - # --- Command actions --- - - # --- Single Actions --- - flx.add_command( - key="B", - description="Build project", - action=Action("Build", foo.build), - tags=["build"], - spinner=True, - spinner_message="๐Ÿ“ฆ Building...", - ) - flx.add_command( - key="T", - description="Run tests", - action=Action("Test", foo.test), - tags=["test"], - spinner=True, - spinner_message="๐Ÿงช Running tests...", - ) - flx.add_command( - key="D", - description="Deploy project", - action=Action("Deploy", foo.deploy), - tags=["deploy"], - spinner=True, - spinner_message="๐Ÿš€ Deploying...", - ) - - # --- Build pipeline (ChainedAction) --- - pipeline = ChainedAction( - name="Full Build Pipeline", - actions=[ - Action("Clean", foo.clean), - Action("Build", foo.build_package), - Action("Package", foo.package), - ], - ) - flx.add_command( - key="P", - description="Run Build Pipeline", - action=pipeline, - tags=["build", "pipeline"], - spinner=True, - spinner_message="๐Ÿ”จ Running build pipeline...", - spinner_type="line", - ) - - # --- Test suite (ActionGroup) --- - test_suite = ActionGroup( - name="Test Suite", - actions=[ - Action("Unit Tests", foo.run_tests), - Action("Integration Tests", foo.run_integration_tests), - Action("Lint", foo.run_linter), - ], - ) - flx.add_command( - key="G", - description="Run All Tests", - action=test_suite, - tags=["test", "parallel"], - spinner=True, - spinner_type="line", - ) - await foo.run() + flx.add_commands(loader(bootstrap_path)) + await flx.run() if __name__ == "__main__": - try: - asyncio.run(main()) - except (KeyboardInterrupt, EOFError): - pass + asyncio.run(main()) diff --git a/falyx/config.py b/falyx/config.py index 5884319..3bca858 100644 --- a/falyx/config.py +++ b/falyx/config.py @@ -35,7 +35,7 @@ def import_action(dotted_path: str) -> Any: return getattr(module, attr) -def loader(file_path: str) -> list[dict[str, Any]]: +def loader(file_path: Path | str) -> list[dict[str, Any]]: """ Load command definitions from a YAML or TOML file. @@ -53,7 +53,13 @@ def loader(file_path: str) -> list[dict[str, Any]]: Raises: ValueError: If the file format is unsupported or file cannot be parsed. """ - path = Path(file_path) + if isinstance(file_path, str): + path = Path(file_path) + elif isinstance(file_path, Path): + path = file_path + else: + raise TypeError("file_path must be a string or Path object.") + if not path.is_file(): raise FileNotFoundError(f"No such config file: {file_path}")