pyproject-toml

pyproject.toml Configuration Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "pyproject-toml" with this command: npx skills add vamseeachanta/workspace-hub/vamseeachanta-workspace-hub-pyproject-toml

pyproject.toml Configuration Skill

Master pyproject.toml for modern Python project configuration, build systems, tool settings, and dependency management.

When to Use This Skill

Use pyproject.toml configuration when you need:

  • Project metadata - Name, version, description, authors

  • Dependency management - Core and optional dependencies

  • Build configuration - Setuptools, hatch, flit, or poetry

  • Tool configuration - pytest, ruff, mypy, black, isort

  • Entry points - CLI scripts and plugins

  • Package discovery - Source directory configuration

Avoid when:

  • Legacy projects requiring setup.py (rare, migrate instead)

  • Non-Python projects

Core Structure

Complete pyproject.toml Template

============================================================

BUILD SYSTEM

============================================================

[build-system] requires = ["setuptools>=68.0", "wheel"] build-backend = "setuptools.build_meta"

============================================================

PROJECT METADATA

============================================================

[project] name = "my-project" version = "0.1.0" description = "A comprehensive Python project template" readme = "README.md" requires-python = ">=3.10" license = {text = "MIT"} authors = [ {name = "Your Name", email = "your.email@example.com"} ] maintainers = [ {name = "Your Name", email = "your.email@example.com"} ] keywords = ["python", "template", "project"] classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Topic :: Software Development :: Libraries :: Python Modules", ]

Core dependencies

dependencies = [ "pandas>=2.0.0", "numpy>=1.24.0", "pyyaml>=6.0", "click>=8.0.0", ]

============================================================

OPTIONAL DEPENDENCIES

============================================================

[project.optional-dependencies] dev = [ "pytest>=7.0.0", "pytest-cov>=4.0.0", "ruff>=0.1.0", "mypy>=1.4.0", "black>=23.0.0", "isort>=5.12.0", ] docs = [ "mkdocs>=1.5.0", "mkdocs-material>=9.0.0", ] viz = [ "plotly>=5.15.0", "matplotlib>=3.7.0", ] all = [ "my-project[dev,docs,viz]", ]

============================================================

ENTRY POINTS (CLI & PLUGINS)

============================================================

[project.scripts] my-cli = "my_project.cli:main" my-tool = "my_project.tools:run"

[project.gui-scripts] my-gui = "my_project.gui:main"

[project.entry-points."my_project.plugins"] plugin1 = "my_project.plugins.plugin1:Plugin1" plugin2 = "my_project.plugins.plugin2:Plugin2"

============================================================

URLS

============================================================

[project.urls] Homepage = "https://github.com/username/my-project" Documentation = "https://my-project.readthedocs.io" Repository = "https://github.com/username/my-project.git" Issues = "https://github.com/username/my-project/issues" Changelog = "https://github.com/username/my-project/blob/main/CHANGELOG.md"

============================================================

PACKAGE DISCOVERY

============================================================

[tool.setuptools] package-dir = {"" = "src"} include-package-data = true

[tool.setuptools.packages.find] where = ["src"] include = ["my_project*"] exclude = ["tests*"]

[tool.setuptools.package-data] my_project = [".yaml", ".json", "data/*"]

============================================================

UV CONFIGURATION

============================================================

[tool.uv] dev-dependencies = [ "pytest>=7.0.0", "pytest-cov>=4.0.0", "ruff>=0.1.0", "mypy>=1.4.0", ]

============================================================

PYTEST CONFIGURATION

============================================================

[tool.pytest.ini_options] minversion = "7.0" testpaths = ["tests"] python_files = ["test_.py", "test.py"] python_functions = ["test"] python_classes = ["Test"] addopts = [ "-v", "--tb=short", "--strict-markers", "-ra", ] markers = [ "slow: marks tests as slow (deselect with '-m "not slow"')", "integration: marks tests as integration tests", "unit: marks tests as unit tests", ] filterwarnings = [ "ignore::DeprecationWarning", "ignore::PendingDeprecationWarning", ]

============================================================

COVERAGE CONFIGURATION

============================================================

[tool.coverage.run] source = ["src"] branch = true parallel = true omit = [ "/tests/", "/pycache/", "*/conftest.py", ]

[tool.coverage.paths] source = ["src"]

[tool.coverage.report] exclude_lines = [ "pragma: no cover", "def repr", "raise NotImplementedError", "if TYPE_CHECKING:", "if name == .main.:", "@abstractmethod", ] show_missing = true precision = 2 fail_under = 80

[tool.coverage.html] directory = "htmlcov"

============================================================

RUFF CONFIGURATION (Linting & Formatting)

============================================================

[tool.ruff] target-version = "py310" line-length = 88 indent-width = 4 exclude = [ ".git", ".venv", "pycache", "build", "dist", "*.egg-info", ]

[tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # Pyflakes "I", # isort "B", # flake8-bugbear "C4", # flake8-comprehensions "UP", # pyupgrade "ARG", # flake8-unused-arguments "SIM", # flake8-simplify ] ignore = [ "E501", # line too long (handled by formatter) "B008", # function call in default argument "B905", # zip strict ] fixable = ["ALL"] unfixable = []

[tool.ruff.lint.per-file-ignores] "tests/*" = ["ARG001", "S101"] "init.py" = ["F401"]

[tool.ruff.lint.isort] known-first-party = ["my_project"] force-single-line = false lines-after-imports = 2

[tool.ruff.format] quote-style = "double" indent-style = "space" skip-magic-trailing-comma = false line-ending = "auto"

============================================================

MYPY CONFIGURATION

============================================================

[tool.mypy] python_version = "3.10" strict = true warn_return_any = true warn_unused_configs = true disallow_untyped_defs = true disallow_incomplete_defs = true check_untyped_defs = true no_implicit_optional = true warn_redundant_casts = true warn_unused_ignores = true show_error_codes = true show_column_numbers = true pretty = true exclude = [ "tests/", "build/", "dist/", ]

[[tool.mypy.overrides]] module = [ "pandas.", "numpy.", "plotly.", "yaml.", ] ignore_missing_imports = true

============================================================

BLACK CONFIGURATION (if not using ruff format)

============================================================

[tool.black] line-length = 88 target-version = ["py310", "py311", "py312"] include = '.pyi?$' exclude = ''' /( .git | .venv | pycache | build | dist )/ '''

============================================================

ISORT CONFIGURATION (if not using ruff)

============================================================

[tool.isort] profile = "black" line_length = 88 known_first_party = ["my_project"] skip = [".venv", "build", "dist"] multi_line_output = 3 include_trailing_comma = true force_grid_wrap = 0 use_parentheses = true ensure_newline_before_comments = true

============================================================

BUMPVER (Version Management)

============================================================

[tool.bumpver] current_version = "0.1.0" version_pattern = "MAJOR.MINOR.PATCH" commit_message = "bump version {old_version} -> {new_version}" commit = true tag = true push = false

[tool.bumpver.file_patterns] "pyproject.toml" = [ 'version = "{version}"', 'current_version = "{version}"', ] "src/my_project/init.py" = [ 'version = "{version}"', ]

Section-by-Section Guide

  1. Build System

[build-system] requires = ["setuptools>=68.0", "wheel"] build-backend = "setuptools.build_meta"

Alternative build backends:

Hatch

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

Flit

[build-system] requires = ["flit_core>=3.4"] build-backend = "flit_core.buildapi"

Poetry

[build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api"

PDM

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

  1. Project Metadata

[project] name = "my-project" # Package name (PyPI) version = "0.1.0" # Semantic version description = "Short description" # One-line summary readme = "README.md" # Long description file requires-python = ">=3.10" # Python version constraint license = {text = "MIT"} # License identifier

Alternative license formats

license = {file = "LICENSE"}

license = "MIT"

authors = [ {name = "Name", email = "email@example.com"} ]

keywords = ["keyword1", "keyword2"]

PyPI classifiers

classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", ]

  1. Dependencies

[project]

Core dependencies (always installed)

dependencies = [ "pandas>=2.0.0", # Minimum version "numpy>=1.24,<2.0", # Version range "requests~=2.28", # Compatible release "click==8.1.3", # Exact version "pyyaml", # Any version ]

[project.optional-dependencies]

Install with: pip install my-project[dev]

dev = [ "pytest>=7.0", "ruff>=0.1.0", ]

Install with: pip install my-project[viz]

viz = [ "plotly>=5.0", "matplotlib>=3.7", ]

Install all optional deps

all = [ "my-project[dev,viz]", ]

  1. Package Discovery

Src layout (recommended):

[tool.setuptools] package-dir = {"" = "src"}

[tool.setuptools.packages.find] where = ["src"] include = ["my_project*"] exclude = ["tests*"]

Flat layout:

[tool.setuptools.packages.find] include = ["my_project*"] exclude = ["tests*"]

Include data files:

[tool.setuptools.package-data] my_project = [ ".yaml", ".json", "data/.csv", "templates/.html", ]

  1. Entry Points

CLI scripts:

[project.scripts]

Creates: my-cli command

my-cli = "my_project.cli:main"

Module with arguments

my-tool = "my_project.tools:run"

Python code:

src/my_project/cli.py

import click

@click.command() @click.option("--name", default="World") def main(name: str) -> None: """CLI entry point.""" click.echo(f"Hello, {name}!")

if name == "main": main()

Plugin system:

[project.entry-points."my_project.plugins"] csv = "my_project.plugins.csv:CSVPlugin" json = "my_project.plugins.json:JSONPlugin"

Tool-Specific Configurations

pytest

[tool.pytest.ini_options] minversion = "7.0" testpaths = ["tests"] addopts = [ "-v", # Verbose "--tb=short", # Short traceback "-ra", # Show extra summary "--strict-markers", # Error on unknown markers "--cov=src", # Coverage "--cov-report=html", # HTML report ] markers = [ "slow: slow tests", "integration: integration tests", ]

ruff (Modern Linter)

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

[tool.ruff.lint] select = ["E", "W", "F", "I", "B", "C4", "UP"] ignore = ["E501"]

[tool.ruff.format] quote-style = "double"

mypy (Type Checker)

[tool.mypy] python_version = "3.10" strict = true warn_return_any = true

[[tool.mypy.overrides]] module = ["pandas.", "numpy."] ignore_missing_imports = true

Complete Examples

Example 1: Data Processing Library

[build-system] requires = ["setuptools>=68.0", "wheel"] build-backend = "setuptools.build_meta"

[project] name = "data-processor" version = "1.0.0" description = "Data processing utilities for engineering workflows" readme = "README.md" requires-python = ">=3.10" license = {text = "MIT"}

dependencies = [ "pandas>=2.0.0", "numpy>=1.24.0", "openpyxl>=3.1.0", "pyyaml>=6.0", ]

[project.optional-dependencies] viz = ["plotly>=5.15.0"] dev = ["pytest>=7.0", "ruff>=0.1.0", "mypy>=1.4"]

[project.scripts] data-process = "data_processor.cli:main"

[tool.setuptools.packages.find] where = ["src"]

[tool.pytest.ini_options] testpaths = ["tests"] addopts = ["-v", "--cov=src"]

[tool.ruff] line-length = 88 select = ["E", "W", "F", "I"]

Example 2: Web Scraping Package

[build-system] requires = ["setuptools>=68.0", "wheel"] build-backend = "setuptools.build_meta"

[project] name = "energy-scraper" version = "0.1.0" description = "BSEE and SODIR data extraction utilities" requires-python = ">=3.10"

dependencies = [ "scrapy>=2.12.0", "selenium>=4.15.0", "beautifulsoup4>=4.12.0", "pandas>=2.0.0", "pyyaml>=6.0", "aiohttp>=3.9.0", ]

[project.optional-dependencies] dev = [ "pytest>=7.0", "pytest-asyncio>=0.21", "ruff>=0.1.0", ]

[project.scripts] bsee-fetch = "energy_scraper.bsee:main" sodir-fetch = "energy_scraper.sodir:main"

[tool.setuptools.packages.find] where = ["src"]

[tool.pytest.ini_options] asyncio_mode = "auto" testpaths = ["tests"]

Example 3: Workspace-Hub Standard Template

Standard pyproject.toml for workspace-hub repositories

[build-system] requires = ["setuptools>=68.0", "wheel"] build-backend = "setuptools.build_meta"

[project] name = "workspace-project" version = "0.1.0" description = "Standardized project configuration" readme = "README.md" requires-python = ">=3.10" license = {text = "MIT"} authors = [{name = "Development Team"}]

dependencies = [ "pandas>=2.0.0", "numpy>=1.24.0", "pyyaml>=6.0", "plotly>=5.15.0", "click>=8.0.0", ]

[project.optional-dependencies] dev = [ "pytest>=7.0.0", "pytest-cov>=4.0.0", "ruff>=0.1.0", "mypy>=1.4.0", "deepdiff>=6.0.0", ]

[tool.setuptools] package-dir = {"" = "src"}

[tool.setuptools.packages.find] where = ["src"]

[tool.uv] dev-dependencies = [ "pytest>=7.0.0", "pytest-cov>=4.0.0", "ruff>=0.1.0", ]

[tool.pytest.ini_options] testpaths = ["tests"] addopts = ["-v", "--tb=short", "--cov=src", "--cov-report=html"]

[tool.coverage.run] source = ["src"] branch = true

[tool.coverage.report] fail_under = 80

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

[tool.ruff.lint] select = ["E", "W", "F", "I", "B", "C4", "UP"]

[tool.mypy] python_version = "3.10" strict = true

[[tool.mypy.overrides]] module = ["pandas.", "numpy.", "plotly.*"] ignore_missing_imports = true

[tool.bumpver] current_version = "0.1.0" version_pattern = "MAJOR.MINOR.PATCH" commit_message = "bump version {old_version} -> {new_version}" commit = true tag = true

Best Practices

  1. Version Constraints

Recommended patterns

dependencies = [ "pandas>=2.0.0", # Minimum version (most common) "numpy>=1.24,<2.0", # Range for major version compatibility "requests~=2.28", # Compatible release (~=2.28 means >=2.28,<3.0) ]

Avoid

dependencies = [ "pandas==2.1.3", # Too strict, causes conflicts "numpy", # Too loose, may break with updates ]

  1. Organize Optional Dependencies

[project.optional-dependencies]

Group by purpose

dev = ["pytest", "ruff", "mypy"] docs = ["mkdocs", "mkdocs-material"] viz = ["plotly", "matplotlib"]

Convenience groups

test = ["pytest", "pytest-cov"] lint = ["ruff", "mypy"] all = ["my-project[dev,docs,viz]"]

  1. Use src Layout

my-project/ ├── pyproject.toml ├── src/ │ └── my_project/ │ ├── init.py │ └── core.py └── tests/ └── test_core.py

  1. Keep Tools Consistent

Use same line-length everywhere

[tool.ruff] line-length = 88

[tool.black] line-length = 88

[tool.isort] line_length = 88

Resources

Use this template for all Python projects in workspace-hub!

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

echarts

No summary provided by upstream source.

Repository SourceNeeds Review
General

pandoc

No summary provided by upstream source.

Repository SourceNeeds Review
General

mkdocs

No summary provided by upstream source.

Repository SourceNeeds Review
General

gis

No summary provided by upstream source.

Repository SourceNeeds Review