Change __main__ to load falyx config from predefined locations

This commit is contained in:
Roland Thomas Jr 2025-05-01 22:32:36 -04:00
parent e91654ca27
commit 2d879561c9
Signed by: roland
GPG Key ID: 7C3C2B085A4C2872
2 changed files with 37 additions and 150 deletions

View File

@ -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())

View File

@ -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}")