Add dependencies
This commit is contained in:
		| @@ -18,6 +18,6 @@ repos: | ||||
|     hooks: | ||||
|     - id: sync-version | ||||
|       name: Sync version from pyproject.toml | ||||
|       entry: poetry run sync-version | ||||
|       entry: python scripts/sync_version.py | ||||
|       language: system | ||||
|       files: ^pyproject\.toml$ | ||||
|   | ||||
| @@ -46,7 +46,6 @@ def get_falyx_parsers() -> FalyxParsers: | ||||
|     falyx_parsers.subparsers.add_parser( | ||||
|         "init-global", help="Set up ~/.config/falyx with example tasks" | ||||
|     ) | ||||
|  | ||||
|     return falyx_parsers | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -27,10 +27,20 @@ TEMPLATE_CONFIG = """\ | ||||
|   spinner: true | ||||
| """ | ||||
|  | ||||
| GLOBAL_TEMPLATE_TASKS = """\ | ||||
| async def cleanup(): | ||||
|     print("🧹 Cleaning temp files...") | ||||
| """ | ||||
|  | ||||
| GLOBAL_CONFIG = """\ | ||||
| async def cleanup(): | ||||
|     print("🧹 Cleaning temp files...") | ||||
| """ | ||||
|  | ||||
| console = Console(color_system="auto") | ||||
|  | ||||
|  | ||||
| def init_project(name: str = "."): | ||||
| def init_project(name: str = ".") -> None: | ||||
|     target = Path(name).resolve() | ||||
|     target.mkdir(parents=True, exist_ok=True) | ||||
|  | ||||
| @@ -39,7 +49,7 @@ def init_project(name: str = "."): | ||||
|  | ||||
|     if tasks_path.exists() or config_path.exists(): | ||||
|         console.print(f"⚠️  Project already initialized at {target}") | ||||
|         return | ||||
|         return None | ||||
|  | ||||
|     tasks_path.write_text(TEMPLATE_TASKS) | ||||
|     config_path.write_text(TEMPLATE_CONFIG) | ||||
| @@ -47,7 +57,7 @@ def init_project(name: str = "."): | ||||
|     print(f"✅ Initialized Falyx project in {target}") | ||||
|  | ||||
|  | ||||
| def init_global(): | ||||
| def init_global() -> None: | ||||
|     config_dir = Path.home() / ".config" / "falyx" | ||||
|     config_dir.mkdir(parents=True, exist_ok=True) | ||||
|  | ||||
| @@ -56,22 +66,9 @@ def init_global(): | ||||
|  | ||||
|     if tasks_path.exists() or config_path.exists(): | ||||
|         console.print("⚠️  Global Falyx config already exists at ~/.config/falyx") | ||||
|         return | ||||
|         return None | ||||
|  | ||||
|     tasks_path.write_text( | ||||
|         """\ | ||||
| async def cleanup(): | ||||
|     print("🧹 Cleaning temp files...") | ||||
| """ | ||||
|     ) | ||||
|  | ||||
|     config_path.write_text( | ||||
|         """\ | ||||
| - key: C | ||||
|   description: Cleanup temp files | ||||
|   action: tasks.cleanup | ||||
|   aliases: [clean, cleanup] | ||||
| """ | ||||
|     ) | ||||
|     tasks_path.write_text(GLOBAL_TEMPLATE_TASKS) | ||||
|     config_path.write_text(GLOBAL_CONFIG) | ||||
|  | ||||
|     console.print("✅ Initialized global Falyx config at ~/.config/falyx") | ||||
|   | ||||
| @@ -19,6 +19,7 @@ from prompt_toolkit.formatted_text import ( | ||||
| from rich.logging import RichHandler | ||||
|  | ||||
| from falyx.themes.colors import OneColors | ||||
| from falyx.validators import yes_no_validator | ||||
|  | ||||
| logger = logging.getLogger("falyx") | ||||
|  | ||||
| @@ -69,18 +70,20 @@ def chunks(iterator, size): | ||||
|         yield chunk | ||||
|  | ||||
|  | ||||
| async def confirm_async(message: AnyFormattedText = "Are you sure?") -> bool: | ||||
|     session: PromptSession = PromptSession() | ||||
|     while True: | ||||
|         merged_message: AnyFormattedText = merge_formatted_text( | ||||
|             [message, FormattedText([(OneColors.LIGHT_YELLOW_b, " [Y/n] ")])] | ||||
|         ) | ||||
|         answer: str = (await session.prompt_async(merged_message)).strip().lower() | ||||
|         if answer in ("y", "yes"): | ||||
|             return True | ||||
|         if answer in ("n", "no", ""): | ||||
|             return False | ||||
|         print("Please enter y or n.") | ||||
| async def confirm_async( | ||||
|     message: AnyFormattedText = "Are you sure?", | ||||
|     prefix: AnyFormattedText = FormattedText([(OneColors.CYAN, "❓ ")]), | ||||
|     suffix: AnyFormattedText = FormattedText([(OneColors.LIGHT_YELLOW_b, " [Y/n] > ")]), | ||||
|     session: PromptSession | None = None, | ||||
| ) -> bool: | ||||
|     """Prompt the user with a yes/no async confirmation and return True for 'Y'.""" | ||||
|     session = session or PromptSession() | ||||
|     merged_message: AnyFormattedText = merge_formatted_text([prefix, message, suffix]) | ||||
|     answer = await session.prompt_async( | ||||
|         merged_message, | ||||
|         validator=yes_no_validator(), | ||||
|     ) | ||||
|     return True if answer.upper() == "Y" else False | ||||
|  | ||||
|  | ||||
| class CaseInsensitiveDict(dict): | ||||
|   | ||||
| @@ -16,7 +16,10 @@ def int_range_validator(minimum: int, maximum: int) -> Validator: | ||||
|         except ValueError: | ||||
|             return False | ||||
|  | ||||
|     return Validator.from_callable(validate, error_message="Invalid input.") | ||||
|     return Validator.from_callable( | ||||
|         validate, | ||||
|         error_message=f"Invalid input. Enter a number between {minimum} and {maximum}.", | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def key_validator(keys: Sequence[str] | KeysView[str]) -> Validator: | ||||
| @@ -27,4 +30,17 @@ def key_validator(keys: Sequence[str] | KeysView[str]) -> Validator: | ||||
|             return False | ||||
|         return True | ||||
|  | ||||
|     return Validator.from_callable(validate, error_message="Invalid input.") | ||||
|     return Validator.from_callable( | ||||
|         validate, error_message=f"Invalid input. Available keys: {', '.join(keys)}." | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def yes_no_validator() -> Validator: | ||||
|     """Validator for yes/no inputs.""" | ||||
|  | ||||
|     def validate(input: str) -> bool: | ||||
|         if input.upper() not in ["Y", "N"]: | ||||
|             return False | ||||
|         return True | ||||
|  | ||||
|     return Validator.from_callable(validate, error_message="Enter 'Y' or 'n'.") | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| __version__ = "0.1.14" | ||||
| __version__ = "0.1.15" | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| [tool.poetry] | ||||
| name = "falyx" | ||||
| version = "0.1.14" | ||||
| version = "0.1.15" | ||||
| description = "Reliable and introspectable async CLI action framework." | ||||
| authors = ["Roland Thomas Jr <roland@rtj.dev>"] | ||||
| license = "MIT" | ||||
| @@ -13,6 +13,8 @@ prompt_toolkit = "^3.0" | ||||
| rich = "^13.0" | ||||
| pydantic = "^2.0" | ||||
| python-json-logger = "^3.3.0" | ||||
| toml = "^0.10" | ||||
| pyyaml = "^6.0" | ||||
|  | ||||
| [tool.poetry.group.dev.dependencies] | ||||
| pytest = "^7.0" | ||||
| @@ -26,7 +28,6 @@ pytest-cov = "^4.0" | ||||
|  | ||||
| [tool.poetry.scripts] | ||||
| falyx = "falyx.__main__:main" | ||||
| sync-version = "scripts.sync_version:main" | ||||
|  | ||||
| [build-system] | ||||
| requires = ["poetry-core>=1.0.0"] | ||||
|   | ||||
| @@ -35,8 +35,8 @@ def test_bootstrap_no_config(): | ||||
|     sys_path_before = list(sys.path) | ||||
|     bootstrap_path = bootstrap() | ||||
|     assert bootstrap_path is None | ||||
|     assert str(Path.cwd()) in sys.path | ||||
|     sys.path = sys_path_before | ||||
|     assert str(Path.cwd()) not in sys.path | ||||
|  | ||||
|  | ||||
| def test_bootstrap_with_global_config(): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user