Thank you for your interest in contributing! This document provides guidelines for working with this project.
-
Clone the repository:
git clone https://github.com/LavLabInfrastructure/python-template.git cd python-template
-
Install Hatch (build & environment manager):
pip install hatch -
Install pre-commit hooks:
pip install pre-commit pre-commit install
All project tasks are managed through Hatch environments:
| Task | Command |
|---|---|
| Run tests | hatch run test:test |
| Run tests with coverage | hatch run test:cov |
| Lint code | hatch run lint:check |
| Format code | hatch run lint:format |
| Auto-fix lint issues | hatch run lint:fix |
| Run all lint checks | hatch run lint:all |
| Type check | hatch run types:check |
| Build docs | hatch run docs:build-docs |
| Serve docs locally | hatch run docs:serve-docs |
| Build wheel | hatch build |
- Formatter & Linter: Ruff handles both formatting and linting. Configuration lives in
pyproject.tomlunder[tool.ruff]. - Line length: 88 characters (consistent with Black's default).
- Docstrings: Use Sphinx-style docstrings (
:param:,:type:,:return:,:rtype:). - Type hints: Encouraged. The project includes a
py.typedmarker for PEP 561 compliance.
This project follows a library-first design:
- Library modules (
src/python_template/) contain all business logic as importable functions and classes. - CLI (
src/python_template/cli.py) is a thin wrapper that parses arguments and delegates to library functions. - Tests (
tests/) import directly from the library — never from the CLI.
When adding new functionality:
- Write the logic as a function or class in a library module.
- Add tests that call the function directly.
- If CLI access is needed, add a subcommand in
cli.pythat wraps the library function.
- Tests live in
tests/and use pytest. - Shared fixtures belong in
tests/conftest.py. - Name test files
test_<module>.pyand test functionstest_<behavior>. - Aim for descriptive test names that explain what is being verified.
def test_example_returns_input_unchanged():
"""Verify the example function passes through its argument."""
assert example("hello") == "hello"-
Create a branch from
main:git checkout -b feature/my-change -
Make your changes and ensure all checks pass:
hatch run lint:all hatch run test:cov hatch run types:check
-
Commit with a clear, descriptive message. Pre-commit hooks will run Ruff automatically.
-
Open a Pull Request against
main. The CI pipeline will run linting, tests, and build checks.
The project includes multi-stage Docker builds:
| Target | Purpose |
|---|---|
base |
Base image with source and non-root user |
hatch |
Runs Hatch commands (used in CI) |
dev |
Full development environment |
prod |
Minimal production image with only the wheel installed |
# Build and run tests via Docker
docker build --target hatch -t myapp:hatch .
docker run --rm -e HATCH_ENV=test myapp:hatch cov
# Build production image
docker build --target prod -t myapp:prod .Open an issue on GitHub if you have questions or run into problems.