NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #4661 most downloaded on PyPI
Format pyproject.toml files
Last release today
04 Oct 2026
Ships on a steady schedule
a new release about every 2 weeks
Most releases are documented
notes for 52 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
5 years old
111 releases · first in 2022
One column per quarter.
Nothing published for this version
pyproject -fmt /2.30.0 Latest Latest Compare # Choose a tag to compare
pyproject -fmt /2.30.0 Latest
Latest
Compare
Keep the classifiers a bound admits.
The test suite the source distribution ships passes from the unpacked sdist. The backend read the project metadata from beside itself, and the sdist k
pyproject.toml it belongs to, so eight tests ended on the file it could not find. It reads the metadata from either place. (#454, #457)A build from the source distribution runs on what that distribution carries. 2.29.0 named toml-fmt-common as a dependency and resolved it from PyPI, w
The wheels held their vendored copy throughout, so an install that takes a wheel was never affected.
The source distribution no longer names toml-fmt-common as a dependency. The newest release of that package on PyPI dates from May, months behind this
A string measures from the start of its key. A long key can be what pushes a value past column_width ; measuring the value alone left lines running pa
column_width; measuring the value alone left lines running past the column the setting asks for. (#448)requires-python = ">= 3.12" did not parse as a version bound, so the generated classifiers fell back to the configured floor and ceiling. pypa/build carried a 3.9 classifier it does not support. (#448)requires-python = "<3.10.1" lost the whole 3.10 series, and claimed Programming Language :: Python :: 3 :: Only for a bound that admits Python 2. (#448)'zz' and 'aa' held their order while the same values in double quotes sorted. (#448)classifiers written as a string stays as written. Asking for generated classifiers replaced the string with an array, losing what the file said. (#448)include-group entries where the file wrote them. An include-group pulls its group in at the point it sits, so moving it changes what the group resolves to. (#448)license = "MIT or later" came back rewritten as though it were an SPDX expression; the formatter now rewrites the value only once it parses as one over registered identifiers. (#448)* catch-all in a setuptools data table matches the way the file spells it. * is not a name TOML reads bare, so a file writes it quoted; the catch-all led the table only because a quote happens to sort before a letter. (#448)A file keeps the line endings it was written with. A CRLF file came back LF, turning every line of a Windows checkout into a diff.
The wheel declares its dependencies in the METADATA header , where an installer looks for them.
A sub-table written under its own header reads in the same key order as the folded form.
project.version stays as written. It is the exact version published in the package metadata, and normalizing it rewrote what a release had already gon
project.version stays as written. It is the exact version published in the package metadata, and normalizing it rewrote what a release had already gone out as. (#431)✨ feat(pyproject-fmt): normalize and validate project.version by @gaborbernat in #428
✨ feat(pyproject-fmt): order tool.pyproject-fmt config keys by @gaborbernat in #421
🐛 fix(build): vendor only git-tracked common sources by @gaborbernat in #419
🐛 fix(common): space before marker after URL by @gaborbernat in #410
🐛 fix(common): honor multi-blank table spacing options by @gaborbernat in #403
📝 docs: keep comments to why only and de-slop docs by @gaborbernat in #394
base_python_file key in tox environments by @edgarrmondragon in #386🐛 fix(common): keep empty table when sub-table stays expanded by @gaborbernat in #385
Nothing published for this version
✨ feat(pyproject-fmt): drop redundant wheel from setuptools build requires by @gaborbernat in #373
📝 docs(pyproject-fmt): overhaul the formatting reference by @gaborbernat in #366
✨ feat(build): ship self-contained pyproject-fmt and tox-toml-fmt wheels by @gaborbernat in #363
✨ feat(build): support free-threaded Python wheels by @gaborbernat in #307
🐛 fix(pyproject-fmt): produce valid TOML when sorting arrays with value on bracket line by @gaborbernat in #293
Nothing published for this version
✨ feat(pyproject-fmt): add bandit to recognized linters by @gaborbernat in #276
♻️ refactor(pyproject-fmt): sort type checkers after linters by @gaborbernat in #274
🐛 fix(common): panic on non-array nodes in array ops by @gaborbernat in #266
✨ feat(tox-toml-fmt): add inline table key reordering by @gaborbernat in #264
✨ feat(common): add shared config file support by @gaborbernat in #258
⬆️ build(deps): update Rust and Python dependencies by @gaborbernat in #243
🐛 fix(project): stop sorting authors and maintainers (#228) by @gaborbernat in #229
🐛 fix(key): normalize literal key quotes to basic (#217) by @gaborbernat in #219
✨ feat(string): add skip_wrap_for_keys config to preserve specific strings by @gaborbernat in #216
🐛 fix(array): preserve trailing comments during sort by @gaborbernat in #208
🐛 fix(array): preserve single-line arrays with trailing comments by @gaborbernat in #204
🐛 fix(table): preserve comments when collapsing array of tables by @gaborbernat in #198
Release pyproject-fmt 2.14.2 [skip ci] by @gaborbernat
<a id="2.14.1"></a>
🐛 fix(table): preserve table headers and reduce duplication by @gaborbernat in #192
<a id="2.14.0"></a>
✨ feat(changelog): add --regenerate flag for full changelog rebuild by @gaborbernat in #166
<a id="2.12.1"></a>
Nothing published for this version
Fix expand_tables setting for specific sub-tables by @gaborbernat in #148
<a id="2.12.0"></a>
Generate README.rst dynamically from docs at build time by @gaborbernat in #145
<a id="2.11.1"></a>
Fix parsing of versions in parentheses by @jamesbursa in #122
<a id="2.11.0"></a>
Allow to opt out of the Python version classifier generation by @gaborbernat in #102
<a id="2.10.0"></a>
Add a few more type checkers to top level tables by @browniebroke in #98
<a id="2.9.0"></a>
Sort [tool.uv] higher in the pyproject.toml by @browniebroke in #97
<a id="2.8.0"></a>
Fix parsing of version pre labels by @adamchainz in #89
<a id="2.7.0"></a>
Replace upstream pep508 that's deprecated with our own by @gaborbernat in #84
<a id="2.6.0"></a>
Use abi3-py39 by @gaborbernat in #58
<a id="2.5.1"></a>
Include all ident parts in keys by @adamchainz in #31
<a id="2.5.0"></a>
Add support for PEP 735 dependency-groups by @browniebroke in #16
<a id="2.4.3"></a>
Fix tomli not present for Python\<3.11 by @gaborbernat in #9
<a id="2.4.2"></a>
- Initial release
<a id="2.4.1"></a>
- Initial release
<a id="2.4.0"></a>
Fix GitHub action warning by @gaborbernat
For versions before 2.4.0, see releases in the old repositories: pyproject-fmt (Python) and pyproject-fmt-rust (Rust).
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →