Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions packages/create-awesome-python-app/README.md
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
# create-awesome-python-app

CLI package (stub). Entry point: `create-awesome-python-app`.
CLI package. Framework: **Typer** (chosen over Click for richer typing/help).

Depends on workspace member `create-python-app-core`.
```bash
uv run create-awesome-python-app --help
uvx create-awesome-python-app@latest my-app # after PyPI publish
```
2 changes: 2 additions & 0 deletions packages/create-awesome-python-app/pyproject.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,6 +6,8 @@ readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"create-python-app-core",
"rich>=15.0.0",
"typer>=0.27.0",
]

[project.scripts]
Expand Down
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,76 @@
"""CLI entrypoint placeholder (full Typer app lands in Epic 4)."""
"""Typer CLI entrypoint for create-awesome-python-app."""

from __future__ import annotations

import asyncio

import typer
from create_python_app_core import (
check_python_version,
create_python_app,
print_env_info,
)
from rich.console import Console

from create_awesome_python_app import __version__

app = typer.Typer(
name="create-awesome-python-app",
help="Composable scaffolding CLI for production-ready Python apps.",
no_args_is_help=False,
add_completion=False,
)
console = Console(stderr=True)


def main() -> None:
print("create-awesome-python-app stub — see roadmap issue #1")
"""Console script entrypoint."""
check_python_version(">=3.12", "create-awesome-python-app")
app()


@app.callback(invoke_without_command=True)
def scaffold(
ctx: typer.Context,
project_directory: str | None = typer.Argument("my-project"),
version: bool = typer.Option(False, "--version", help="Show version"),
info: bool = typer.Option(False, "--info", "-i", help="Print env info"),
verbose: bool = typer.Option(False, "--verbose", "-v"),
template: str | None = typer.Option(None, "--template", "-t"),
no_install: bool = typer.Option(False, "--no-install"),
force: bool = typer.Option(False, "--force", "-f"),
) -> None:
"""Scaffold a new Python project (flags expand in later issues)."""
if version:
console.print(__version__)
raise typer.Exit(0)
if info:
print_env_info()
if ctx.invoked_subcommand is not None:
return
if not template:
console.print(
"[yellow]Stub CLI[/yellow]: pass --template "
"(full interactive mode lands in #34)."
)
console.print(f"Would scaffold [cyan]{project_directory}[/cyan]")
raise typer.Exit(0)

asyncio.run(
create_python_app(
project_directory or "my-project",
{
"template": template,
"install": not no_install,
"force": force,
"verbose": verbose,
},
)
)
console.print(f"[green]Created[/green] {project_directory}")


@app.command("cache")
def cache_placeholder() -> None:
"""Cache management (subcommands land in #37)."""
console.print("cache subcommands: see #37")
20 changes: 15 additions & 5 deletions packages/create-awesome-python-app/tests/test_cli.py
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
from create_awesome_python_app.cli import main
from create_awesome_python_app.cli import app
from typer.testing import CliRunner

runner = CliRunner()

def test_main_prints_stub(capsys) -> None:
main()
captured = capsys.readouterr()
assert "stub" in captured.out.lower()

def test_version() -> None:
result = runner.invoke(app, ["--version"])
assert result.exit_code == 0
combined = result.stdout + result.stderr
assert "0.0.0" in combined


def test_help() -> None:
result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
assert "Scaffold" in result.stdout or "create" in result.stdout.lower()
75 changes: 74 additions & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.