From 18a8376469190b0015f66ac51aa8ca7ff0dde72b Mon Sep 17 00:00:00 2001 From: kolo Date: Mon, 9 Feb 2026 14:50:03 +0300 Subject: [PATCH] add new init command for generate boilerplate in flat or src layout --- src/argenta/_cli/__main__.py | 4 +- src/argenta/_cli/commands/__init__.py | 3 +- src/argenta/_cli/commands/init.py | 108 ++++++++++++++++++++++++++ src/argenta/app/protocols.py | 6 +- 4 files changed, 114 insertions(+), 7 deletions(-) create mode 100644 src/argenta/_cli/commands/init.py diff --git a/src/argenta/_cli/__main__.py b/src/argenta/_cli/__main__.py index 0414abb..6d8444a 100644 --- a/src/argenta/_cli/__main__.py +++ b/src/argenta/_cli/__main__.py @@ -1,12 +1,12 @@ from typer import Typer -from .commands import run_handler +from .commands import run_handler, init_handler def main(): app = Typer() app.command("run")(run_handler) - app.command("init")(run_handler) + app.command("init")(init_handler) app() if __name__ == '__main__': diff --git a/src/argenta/_cli/commands/__init__.py b/src/argenta/_cli/commands/__init__.py index e6c21d7..f8debf7 100644 --- a/src/argenta/_cli/commands/__init__.py +++ b/src/argenta/_cli/commands/__init__.py @@ -1 +1,2 @@ -from .run import run_handler \ No newline at end of file +from .run import run_handler as run_handler +from .init import init_handler as init_handler \ No newline at end of file diff --git a/src/argenta/_cli/commands/init.py b/src/argenta/_cli/commands/init.py new file mode 100644 index 0000000..566ba6d --- /dev/null +++ b/src/argenta/_cli/commands/init.py @@ -0,0 +1,108 @@ +__all__ = ["init_handler"] + +from pathlib import Path +from typing import Literal + +GITIGNORE_CONTENT = """ +__pycache__/ +*.py[cod] +.env +.venv/ +env/ +""" + +FLAT_MAIN_TEMPLATE = """ +from argenta import Orchestrator, App + +from handlers import router + + +def main(): + app = App() + app.include_router(router) + + orchestrator = Orchestrator() + orchestrator.start_polling(app) + +if __name__ == "__main__": + main() +""" + +FLAT_HANDLERS_TEMPLATE = """ +from argenta import Router, Response + +router = Router("Hello command") + +@router.command("hello") +def start_handler(response: Response): + print("Hello world!") +""" + +SRC_MAIN_TEMPLATE = """ +from argenta import Orchestrator, App + +from .routers import router + + +def main(): + app = App() + app.include_router(router) + + orchestrator = Orchestrator() + orchestrator.start_polling(app) + +if __name__ == "__main__": + main() +""" + +SRC_ROUTERS_TEMPLATE = """ +from argenta import Router +from .handlers.hello_world_handler import hello_handler + +router = Router() + +router.command('hello')(hello_handler) +""" + +SRC_HANDLER_TEMPLATE = """ +from argenta import Response + + +def hello_handler(response: Response) -> None: + print("Hello world!") + +""" + + +def create_file(path: Path, content: str) -> None: + if not path.exists(): + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(content.strip(), encoding="utf-8") + print(f"Created: {path}") + else: + print(f"Skipped: {path} (already exists)") + + +def init_handler(with_arch: Literal["flat", "src"] = "flat") -> None: + cwd = Path.cwd() + project_name = cwd.name.lower().replace(" ", "_") + + create_file(cwd / ".gitignore", GITIGNORE_CONTENT) + + if with_arch == "flat": + create_file(cwd / "main.py", FLAT_MAIN_TEMPLATE) + create_file(cwd / "handlers.py", FLAT_HANDLERS_TEMPLATE) + + elif with_arch == "src": + base_pkg = cwd / "src" / project_name / "application" + + create_file(base_pkg / "__main__.py", SRC_MAIN_TEMPLATE) + create_file(base_pkg / "routers.py", SRC_ROUTERS_TEMPLATE) + create_file(base_pkg / "handlers" / "hello_world_handler.py", SRC_HANDLER_TEMPLATE) + + create_file(cwd / "src" / "__init__.py", "") + create_file(cwd / "src" / project_name / "__init__.py", "") + create_file(base_pkg / "__init__.py", "") + create_file(base_pkg / "handlers" / "__init__.py", "") + + print("\nInitialization complete.") diff --git a/src/argenta/app/protocols.py b/src/argenta/app/protocols.py index 985c8e0..ab19d22 100644 --- a/src/argenta/app/protocols.py +++ b/src/argenta/app/protocols.py @@ -7,7 +7,7 @@ __all__ = [ "HandlerFunc", ] -from typing import Any, Protocol, TypeVar +from typing import Any, Protocol, TypeVar, Callable from argenta.response import Response @@ -39,6 +39,4 @@ class DescriptionMessageGenerator(Protocol): raise NotImplementedError -class HandlerFunc(Protocol): - def __call__(self, response: Response, /, *args: Any, **kwargs: Any) -> None: - raise NotImplementedError +type HandlerFunc = Callable[..., Any]