| name | python-project-setup |
| description | Sets up Python projects with modern tooling including pyproject.toml, linting with ruff, formatting, type checking with mypy or pyright, testing with pytest, and pre-commit hooks. Triggers on: "setup Python project", "create Python package", "python project structure", "pyproject.toml".
|
| license | MIT |
| metadata | {"author":"Community","version":"1.0.0","category":"project-setup"} |
Python Project Setup
Instructions
Step 1: Gather Requirements
Ask:
- What type of project? (library/package, web app, CLI tool, data pipeline)
- Minimum Python version? (default: 3.11+)
- Package manager preference? (pip, uv, poetry, pdm)
- Layout preference? (src-layout or flat-layout)
- What frameworks? (FastAPI, Django, Flask, Click, Typer)
- CI platform? (GitHub Actions, GitLab CI)
Step 2: Project Structure
src-layout (recommended for libraries):
my-project/
src/
my_package/
__init__.py
main.py
models.py
tests/
__init__.py
conftest.py
test_main.py
pyproject.toml
README.md
.pre-commit-config.yaml
.github/
workflows/
ci.yml
flat-layout (simpler, for apps):
my-project/
my_package/
__init__.py
main.py
tests/
conftest.py
test_main.py
pyproject.toml
README.md
Use src-layout by default. It prevents accidental imports of the source during testing.
Step 3: Generate pyproject.toml
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "my-package"
version = "0.1.0"
description = "A brief description of the project"
readme = "README.md"
license = "MIT"
requires-python = ">=3.11"
authors = [
{ name = "Your Name", email = "you@example.com" },
]
dependencies = []
[project.optional-dependencies]
dev = [
"pytest>=8.0",
"pytest-cov>=5.0",
"ruff>=0.4",
"mypy>=1.10",
"pre-commit>=3.7",
]
[project.scripts]
my-cli = "my_package.main:cli"
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = [
"--strict-markers",
"--strict-config",
"-ra",
]
[tool.ruff]
target-version = "py311"
line-length = 88
[tool.ruff.lint]
select = [
"E",
"W",
"F",
"I",
"B",
"C4",
"UP",
"SIM",
]
[tool.ruff.lint.isort]
known-first-party = ["my_package"]
[tool.mypy]
python_version = "3.11"
strict = true
warn_return_any = true
warn_unused_configs = true
[tool.coverage.run]
source = ["src/my_package"]
branch = true
[tool.coverage.report]
fail_under = 80
show_missing = true
exclude_lines = [
"pragma: no cover",
"if TYPE_CHECKING:",
]
Step 4: Configure Linting and Formatting
Ruff (recommended - replaces flake8, isort, black):
Add to pyproject.toml (shown above). Ruff handles both linting and formatting:
ruff check .
ruff format .
ruff check --fix .
Type checking with mypy:
mypy src/
For strict mode, address these common issues:
- Add return type annotations to all functions
- Use
from __future__ import annotations for modern syntax
- Add
py.typed marker file for library packages
Step 5: Testing Setup
conftest.py with common fixtures:
import pytest
@pytest.fixture
def sample_data():
"""Provide sample test data."""
return {"name": "test", "value": 42}
@pytest.fixture
def tmp_config(tmp_path):
"""Create a temporary config file."""
config_file = tmp_path / "config.toml"
config_file.write_text('[app]\ndebug = true\n')
return config_file
Run tests with coverage:
pytest --cov --cov-report=term-missing --cov-report=html
Step 6: Pre-commit Hooks
.pre-commit-config.yaml:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.4
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.10.0
hooks:
- id: mypy
additional_dependencies: []
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-toml
- id: check-added-large-files
Install: pre-commit install
Step 7: Development Workflow Commands
Provide a Makefile or document these commands:
.PHONY: install lint format test typecheck all
install:
pip install -e ".[dev]"
pre-commit install
lint:
ruff check .
format:
ruff format .
test:
pytest --cov --cov-report=term-missing
typecheck:
mypy src/
all: lint typecheck test
Example
User says: "Set up a new Python CLI tool project"
Response:
- src-layout with Click/Typer for CLI framework
- pyproject.toml with CLI entry point in [project.scripts]
- Ruff for linting and formatting
- pytest with fixtures for CLI testing (CliRunner)
- Pre-commit config
- GitHub Actions CI workflow
Guidelines
- Default to src-layout for libraries, flat-layout for single-purpose apps
- Always use pyproject.toml over setup.py or setup.cfg (PEP 621)
- Recommend ruff over separate flake8+isort+black installations
- Pin minimum versions in dependencies, not exact versions
- Use optional dependency groups: dev, test, docs
- Include py.typed marker for typed libraries
- Set coverage threshold at 80% minimum
- Configure strict mypy mode from the start (easier than adding later)
- Use uv for faster dependency resolution when available