Python Project Scaffold
Standardized Python project initialization — the pattern used for CLI tools, data pipelines, and libraries. Produces a working pip install -e . project in under a minute.
Directory Structure
project-name/
├── README.md
├── pyproject.toml
├── src/
│ └── package_name/
│ ├── __init__.py
│ ├── cli.py # rich-based CLI
│ └── core_module.py
├── tests/
│ ├── __init__.py
│ └── test_core.py
└── data/ # optional static data
pyproject.toml Template
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "package-name"
version = "0.1.0"
description = "Short description"
readme = "README.md"
license = {text = "MIT"}
requires-python = ">=3.10"
authors = [{name = "Your Name"}]
keywords = ["keyword1", "keyword2"]
dependencies = [
"rich>=13.0.0",
"pydantic>=2.0.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"pytest-cov>=4.0.0",
"ruff>=0.1.0",
]
[project.scripts]
cli-name = "package_name.cli:main"
[tool.ruff]
line-length = 100
target-version = "py310"
[tool.pytest.ini_options]
testpaths = ["tests"]
CLI Template (rich-based)
"""Package description."""
import argparse
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
console = Console()
def create_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(prog="cli-name")
subparsers = parser.add_subparsers(dest="command")
cmd = subparsers.add_parser("action", help="Do something")
cmd.add_argument("input", help="Input value")
cmd.add_argument("--flag", action="store_true", help="Optional flag")
return parser
def main():
parser = create_parser()
args = parser.parse_args()
if not args.command:
parser.print_help()
return
if args.command == "action":
console.print(f"[green]Processing:[/green] {args.input}")
Installation
cd project-name
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
On systems with PEP 668 restrictions (Ubuntu 24.04+, Debian 12+), the venv is required — --break-system-packages works but is not recommended.
Pitfalls
- pip install timeout: Large packages (rdkit, numpy) may take 2-5 minutes. Use
terminal(background=True, notify_on_complete=True)with a 600s timeout for the install step. - src layout imports: Package is importable as
package_name(notsrc.package_name). Thepip install -e .creates the editable link. - Script entry points: Defined in
[project.scripts], become available on PATH only afterpip install.
Verification
source .venv/bin/activate
python -c "import package_name; print(package_name.__version__)"
pytest tests/ -v