# pyproject.toml Patterns Comprehensive patterns for Python project configuration. ## Minimal Project ```toml [project] name = "my-project" version = "0.1.0" requires-python = ">=3.10" dependencies = [ "httpx>=0.25", "pydantic>=2.0", ] ``` ## Standard Library Project ```toml [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "my-package" version = "0.1.0" description = "A short description of the project" readme = "README.md" license = "MIT" requires-python = ">=3.10" authors = [ { name = "Your Name", email = "you@example.com" } ] keywords = ["keyword1", "keyword2"] classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", ] dependencies = [ "httpx>=0.25", "pydantic>=2.0", "rich>=13.0", ] [project.optional-dependencies] dev = [ "pytest>=7.0", "pytest-asyncio>=0.21", "pytest-cov>=4.0", "ruff>=0.1", "mypy>=1.0", ] docs = [ "mkdocs>=1.5", "mkdocs-material>=9.0", ] [project.scripts] my-cli = "my_package.cli:main" [project.urls] Homepage = "https://github.com/username/my-package" Documentation = "https://my-package.readthedocs.io" Repository = "https://github.com/username/my-package" Issues = "https://github.com/username/my-package/issues" ``` ## CLI Application ```toml [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "my-cli" version = "0.1.0" requires-python = ">=3.10" dependencies = [ "typer>=0.9", "rich>=13.0", ] [project.scripts] mycli = "my_cli.main:app" [project.optional-dependencies] dev = ["pytest", "ruff"] ``` ## FastAPI Application ```toml [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "my-api" version = "0.1.0" requires-python = ">=3.10" dependencies = [ "fastapi>=0.100", "uvicorn[standard]>=0.23", "pydantic>=2.0", "sqlalchemy>=2.0", "alembic>=1.12", "python-dotenv>=1.0", ] [project.optional-dependencies] dev = [ "pytest>=7.0", "pytest-asyncio>=0.21", "httpx>=0.25", # for testing "ruff>=0.1", "mypy>=1.0", ] ``` ## Tool Configurations ### Ruff (Linting + Formatting) ```toml [tool.ruff] line-length = 100 target-version = "py310" exclude = [ ".git", ".venv", "__pycache__", "dist", "build", ] [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "UP", # pyupgrade "B", # flake8-bugbear "C4", # flake8-comprehensions "DTZ", # flake8-datetimez "T10", # flake8-debugger "FA", # flake8-future-annotations "ISC", # flake8-implicit-str-concat "PIE", # flake8-pie "PT", # flake8-pytest-style "Q", # flake8-quotes "RSE", # flake8-raise "RET", # flake8-return "SIM", # flake8-simplify "TID", # flake8-tidy-imports "TCH", # flake8-type-checking "ARG", # flake8-unused-arguments "PTH", # flake8-use-pathlib "RUF", # Ruff-specific rules ] ignore = [ "E501", # line too long (handled by formatter) "B008", # do not perform function calls in argument defaults ] [tool.ruff.lint.per-file-ignores] "tests/**" = ["S101"] # Allow assert in tests [tool.ruff.lint.isort] known-first-party = ["my_package"] ``` ### pytest ```toml [tool.pytest.ini_options] testpaths = ["tests"] python_files = ["test_*.py"] python_functions = ["test_*"] addopts = [ "-ra", "-q", "--strict-markers", "--strict-config", ] markers = [ "slow: marks tests as slow", "integration: marks tests as integration tests", ] asyncio_mode = "auto" filterwarnings = [ "error", "ignore::DeprecationWarning", ] ``` ### mypy ```toml [tool.mypy] python_version = "3.10" strict = true warn_return_any = true warn_unused_ignores = true disallow_untyped_defs = true disallow_incomplete_defs = true check_untyped_defs = true disallow_untyped_decorators = true no_implicit_optional = true warn_redundant_casts = true warn_unreachable = true [[tool.mypy.overrides]] module = "tests.*" disallow_untyped_defs = false [[tool.mypy.overrides]] module = ["httpx.*", "pydantic.*"] ignore_missing_imports = true ``` ### Coverage ```toml [tool.coverage.run] source = ["my_package"] branch = true omit = [ "*/__pycache__/*", "*/tests/*", ] [tool.coverage.report] exclude_lines = [ "pragma: no cover", "def __repr__", "raise NotImplementedError", "if TYPE_CHECKING:", "if __name__ == .__main__.:", ] fail_under = 80 show_missing = true ``` ## Build Systems ### Hatchling (Recommended) ```toml [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["src/my_package"] [tool.hatch.version] path = "src/my_package/__init__.py" ``` ### Setuptools ```toml [build-system] requires = ["setuptools>=61.0", "wheel"] build-backend = "setuptools.build_meta" [tool.setuptools.packages.find] where = ["src"] ``` ### Poetry (pyproject.toml native) ```toml [tool.poetry] name = "my-package" version = "0.1.0" description = "" authors = ["Your Name "] readme = "README.md" [tool.poetry.dependencies] python = "^3.10" httpx = "^0.25" [tool.poetry.group.dev.dependencies] pytest = "^7.0" ruff = "^0.1" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" ``` ## Version Management ### Static Version ```toml [project] version = "0.1.0" ``` ### Dynamic Version (from file) ```toml [project] dynamic = ["version"] [tool.hatch.version] path = "src/my_package/__init__.py" # Reads: __version__ = "0.1.0" ``` ### Dynamic Version (from VCS) ```toml [project] dynamic = ["version"] [tool.hatch.version] source = "vcs" [tool.hatch.build.hooks.vcs] version-file = "src/my_package/_version.py" ```