Skip to main content

A Python package to sort and format pyproject.toml

Project description

pypfmt

CI PyPI version codecov Python 3.11+ uv Ruff ty License: MIT

An opinionated formatter and sorter for pyproject.toml files. Produces deterministic, consistently-ordered output so you can diff configuration across many Python projects and copy settings between them without noise.

Features

  • Sort tables and keys with opinionated defaults — [project], [build-system], and [dependency-groups] always come first; common tool sections follow a predictable order
  • Format whitespace and style via taplo for consistent indentation, trailing commas, and column alignment
  • Preserve all data — no keys, values, or comments are lost or reordered when order matters (e.g. pytest.ini_options.addopts)
  • Idempotent — running the tool twice produces identical output
  • Pre-commit hook — drop-in integration with pre-commit
  • Configurable — override defaults per-project via [tool.pypfmt]

Installation

pip install pypfmt

Or using uv (recommended):

uv add pypfmt

Usage

Format files in-place

pypfmt pyproject.toml

Multiple files (useful for monorepos):

pypfmt services/*/pyproject.toml

Check mode (CI)

Exit non-zero if any file needs formatting, without modifying files:

pypfmt --check pyproject.toml

Diff mode

Print a unified diff of proposed changes without modifying files:

pypfmt --diff pyproject.toml

Combined check + diff

Print the diff and exit non-zero if changes are needed:

pypfmt --check --diff pyproject.toml

Stdin / stdout

Pipe input through pypfmt and receive formatted output on stdout:

cat pyproject.toml | pypfmt

Pre-commit hook

Add to your .pre-commit-config.yaml:

repos:
  - repo: https://github.com/bitflight-devops/pyproject-fmt
    rev: v1.0.0  # replace with the latest tag
    hooks:
      - id: pypfmt

language: python is used so pre-commit installs taplo and all other dependencies automatically.

Configuration

Add a [tool.pypfmt] section to your pyproject.toml to override defaults.

Sort order

[tool.pypfmt]
# Replace the root-level table ordering entirely
sort-first = ["project", "build-system", "dependency-groups"]

# Or append extra tables to the default ordering
extend-sort-first = ["my-custom-tool"]

# Disable alphabetical key sorting within tables
sort-table-keys = false

Per-table overrides

[tool.pypfmt]
# Extend the built-in per-table overrides
[tool.pypfmt.extend-overrides]
"tool.mypy" = { first = ["strict", "plugins"] }
"project.optional-dependencies.*" = { inline_arrays = true }

taplo formatting options

[tool.pypfmt]
# Replace all taplo options
taplo-options = ["column_width=100", "indent_string=  "]

# Or append extra options to the defaults
extend-taplo-options = ["column_width=100"]

Comment handling

[tool.pypfmt]
comments-header = true   # preserve file-level header comments (default: true)
comments-footer = true   # preserve file-level footer comments (default: true)
comments-inline = true   # preserve inline comments (default: true)
comments-block  = true   # preserve block comments (default: true)

Default opinionated behaviour

Behaviour Default
Root table order project, build-system, dependency-groups, then alphabetical
Tool section order hatch, git-cliff, uv, pytest, coverage, ty, ruff, mypy, …
Key order within [project] name, version, description, readme, dynamic, authors, maintainers, license, classifiers, keywords, requires-python, dependencies, then alphabetical
Classifiers Sorted alphabetically
Dependencies Sorted alphabetically
pytest.ini_options.addopts Preserved as-is (positional arguments)
keywords Preserved as-is (positional)
Inline comments Aligned
Indentation 4 spaces
Trailing commas in arrays Always added

Development

Prerequisites

  • Python 3.11+
  • uv for package management

Setup

git clone https://github.com/bitflight-devops/pyproject-fmt.git
cd pyproject-fmt
uv sync --all-groups

Running Tests

uv run poe test

# With coverage
uv run poe test-cov

# Across all Python versions
uv run poe test-matrix

Code Quality

# Run all checks (lint, format, type-check)
uv run poe verify

# Auto-fix lint and format issues
uv run poe fix

Pre-commit hooks (prek)

prek install
prek run --all-files

Documentation

uv run poe docs-serve

License

This project is licensed under the MIT License - see the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pypfmt-1.1.11.tar.gz (14.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pypfmt-1.1.11-py3-none-any.whl (15.9 kB view details)

Uploaded Python 3

File details

Details for the file pypfmt-1.1.11.tar.gz.

File metadata

  • Download URL: pypfmt-1.1.11.tar.gz
  • Upload date:
  • Size: 14.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pypfmt-1.1.11.tar.gz
Algorithm Hash digest
SHA256 dd008f24ec9a8bca3f04946675f89f52b8ea6a4b9643b30188118e63d2880a01
MD5 5090eda038f563e277e0c34070b1673e
BLAKE2b-256 725599e633b09777a0fcfdefe2eaf17a13496e55b721e39b74f7dc1b6ad12a8e

See more details on using hashes here.

File details

Details for the file pypfmt-1.1.11-py3-none-any.whl.

File metadata

  • Download URL: pypfmt-1.1.11-py3-none-any.whl
  • Upload date:
  • Size: 15.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pypfmt-1.1.11-py3-none-any.whl
Algorithm Hash digest
SHA256 5c69799fdf63ff8ab342e4f55684a871d302045e145bff70d4fa46f78430692d
MD5 2384f34a01265a7ef5fecc8d021c8728
BLAKE2b-256 79f262171d4dfde58546100d2d366844a5a81e7e3380e68a868dde44449e4320

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page