A Python package to sort and format pyproject.toml
Project description
pypfmt
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd008f24ec9a8bca3f04946675f89f52b8ea6a4b9643b30188118e63d2880a01
|
|
| MD5 |
5090eda038f563e277e0c34070b1673e
|
|
| BLAKE2b-256 |
725599e633b09777a0fcfdefe2eaf17a13496e55b721e39b74f7dc1b6ad12a8e
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c69799fdf63ff8ab342e4f55684a871d302045e145bff70d4fa46f78430692d
|
|
| MD5 |
2384f34a01265a7ef5fecc8d021c8728
|
|
| BLAKE2b-256 |
79f262171d4dfde58546100d2d366844a5a81e7e3380e68a868dde44449e4320
|