Skip to main content

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.

Metadata

Release files for pypfmt 1.1.13

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pypfmt 1.1.13
File Size Uploaded
pypfmt-1.1.13.tar.gz 14.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pypfmt 1.1.13
File Interpreter ABI Platform
pypfmt-1.1.13-py3-none-any.whl Python 3 none any Details

Total release size: 30.2 kB

Release files / pypfmt-1.1.13.tar.gz

Download URL pypfmt-1.1.13.tar.gz
Size 14.2 kB
Tags Source
SHA-256 checksum
How to use checksums
17250a6c08123d69f133feb6a3a9ff9739b214ceeb96cc4fe309ea82a0d8fa86
BLAKE2b-256 checksum
How to use checksums
f5149249813166797c29eec652de020aee5b97a2f9bdb35514cf0e660ccf8b83
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","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}

Release files / pypfmt-1.1.13-py3-none-any.whl

Download URL pypfmt-1.1.13-py3-none-any.whl
Size 15.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
36b3fca5e98c612b3c9d0a0baa174293f32b4af084c80b3af7d39892234dc666
BLAKE2b-256 checksum
How to use checksums
ccd7b7b49d053e918457fcb5bedfe33115f4134afd336e5cec18c08e00369dac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","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}

Release history Release notifications | RSS feed

1.1.15

2 release files

1.1.14

2 release files

This release

1.1.13 This release

2 release files

1.1.12

2 release files

1.1.11

2 release files

1.1.10

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page