Skip to main content
Entirius
AI platform for e-commerce
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

ADR-009: pyproject.toml Standard for Python Projects

Status

Status: Accepted
Date: 2025-07-10
Authors: Piotr Brzozowski
Reviewers: Piotr Brzozowski

Decision

pyproject.toml is adopted as the unified configuration standard for all Python projects in the Entirius ecosystem. This modern Python packaging standard (PEP 518, PEP 621) centralizes project configuration, dependencies, and tool settings in a single file.

Quick Reference

Essential pyproject.toml Structure

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "entirius-service-example"
version = "1.0.0"
description = "Description of the project"
authors = [{name = "Author Name", email = "[email protected]"}]
license = {text = "MPL-2.0"}
requires-python = ">=3.11"
dependencies = ["django>=5.0", "djangorestframework>=3.14"]

[project.optional-dependencies]
dev = ["ruff>=0.1.0", "pytest>=7.0", "mypy>=1.0"]
test = ["pytest>=7.0", "pytest-django>=4.5", "coverage>=7.0"]

[tool.ruff]
line-length = 88
target-version = "py311"

Migration Commands

# Convert existing setup.py to pyproject.toml
uv init --package project-name

# Install dependencies using pyproject.toml
uv pip install -e .

# Install with development dependencies
uv pip install -e ".[dev]"

Context

The Entirius project consists of multiple Python components including Django services, Python modules, and Python libraries. Currently, these projects use different approaches for dependency management and project configuration:

  • Some projects use setup.py for package configuration
  • Others use requirements.txt for dependency management
  • Configuration is scattered across multiple files (setup.py, setup.cfg, requirements.txt, Pipfile, etc.)

Python’s ecosystem has evolved toward standardization around pyproject.toml (PEP 518, PEP 621) as the unified configuration file for Python projects. This standard provides:

  • Centralized configuration - Single file for all project metadata
  • Tool compatibility - Supported by modern Python tools (pip, UV, setuptools, etc.)
  • Standardization - Official Python packaging standard
  • Better dependency management - Clear separation of runtime, development, and optional dependencies

Considered Options

Adopt pyproject.toml Standard

  • Description: Migrate all Python projects to use pyproject.toml as the primary configuration file
  • Pros:
    • Modern Python packaging standard (PEP 518, PEP 621)
    • Single file for all project configuration
    • Better tool integration and compatibility
    • Consistent dependency management
    • Future-proof approach aligned with Python ecosystem
    • Excellent support in UV package manager (per ADR-007)
  • Cons:
    • Migration effort for existing projects
    • Learning curve for team members
    • Some legacy tools may not support it
  • Impact on system: Standardizes configuration across all Python projects

Rationale

Chosen option: Adopt pyproject.toml Standard

Key decision factors:

  • Modern standard: PEP 518 and PEP 621 establish pyproject.toml as the official Python packaging approach
  • Tool unification: Single file consolidates project metadata, dependencies, and tool configurations
  • UV integration: Excellent compatibility with UV package manager (per ADR-007) for optimal performance
  • Dependency management: Clear separation of runtime, development, test, and optional dependencies
  • Risk analysis: Low risk with widespread adoption and official Python community backing
  • Business impact: Standardized configuration reduces maintenance overhead and improves developer productivity
  • Compatibility: Native support in modern Python tools including Hatchling, Ruff, pytest, and mypy

Standard Configuration Structure:

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "entirius-service-example"
version = "1.0.0"
description = "Description of the project"
authors = [{name = "Piotr Brzozowski", email = "[email protected]"}]
license = {text = "MPL-2.0"}
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
    "django>=5.0",
    "djangorestframework>=3.14",
]

[project.optional-dependencies]
dev = [
    "black>=23.0",
    "pytest>=7.0",
    "mypy>=1.0",
    "ruff>=0.1.0",
]
test = [
    "pytest>=7.0",
    "pytest-django>=4.5",
    "coverage>=7.0",
]

[project.urls]
Homepage = "https://github.com/entirius/entirius-service-example"
Documentation = "https://docs.entirius.com"
Repository = "https://github.com/entirius/entirius-service-example"
Issues = "https://github.com/entirius/entirius-service-example/issues"

[tool.black]
line-length = 88
target-version = ['py311']

[tool.pytest.ini_options]
DJANGO_SETTINGS_MODULE = "main.settings.testing"
python_files = ["tests.py", "test_*.py", "*_tests.py"]

[tool.mypy]
python_version = "3.11"
warn_return_any = true
warn_unused_configs = true

[tool.ruff]
line-length = 88
target-version = "py311"
  • ADR-007: UV Python Package Manager - pyproject.toml has excellent UV support
  • ADR-008: GitHub Repository Naming Patterns - establishes project types that need standardized configuration

References