pyroma
Pyroma rhymes with aroma, and is a product aimed at giving a rating of how well a Python project complies with the best practices of the Python packaging ecosystem, primarily PyPI, pip, Distribute etc, as well as a list of issues that could be improved.
The aim of this is both to help people make a project that is nice and usable, but also to improve the quality of Python third-party software, making it easier and more enjoyable to use the vast array of available modules for Python.
It's written so that there are a library with methods to call from Python, as well as a script, also called pyroma.
The complete documentation, including the upgrade guide and changelog, is published at hbmartin.github.io/pyroma.
It can be run on a project directory before making a release:
$ pyroma .
On a distribution before uploading it to the CheeseShop:
$ pyroma pyroma-1.0.tar.gz
Or you can give it a package name on CheeseShop:
$ pyroma pyroma
If you use an internal PyPI-compatible package index, specify it with
--index-url:
$ pyroma --index-url https://packages.example.com internal-package
Giving it a name on CheeseShop is the most extensive test, as it will test for several things isn't otherwise tested.
Note that pyroma extracts metadata by asking the project's build backend for it, which — like installing the package with pip — can execute code shipped with the package. Be as careful about running pyroma on an untrusted package as you would be about installing it.
The high-level pyroma.run() API cleans up extracted distributions
after rating. If you call distributiondata.get_data() or
pypidata.get_data() directly, call distributiondata.cleanup(data)
when you no longer need the returned metadata's _path.
In all cases the output is similar:
------------------------------
Checking .
Found pyroma
------------------------------
The packages long_description is quite short.
------------------------------
Final rating: 9/10
Cottage Cheese
------------------------------
For machine-readable output, pass --format json:
$ pyroma --format json .
Exit codes
0: The package rated equal to or above the--minrating (default 8).2: The package rated below the--minrating.1: Used by thezest.releaserintegration when you choose to abort the release after a low rating.3: An error prevented rating the package: it could not be found or downloaded, or the configuration (for example a--skip-testsvalue that skips every rated test) made rating impossible. With--format jsonthe error is reported as a JSON document with anerrorkey.
Tests
This is the list of checks that are currently performed:
- The package should have a name, a version and a Summary. If it does not, it will receive a rating of 0.
- The name must follow the project name format from the packaging specifications; package indices reject invalid names, so an invalid name is fatal.
- The version number should be a string that complies with the version specifiers specification (PEP 440). Non-canonical forms, version epochs and local version segments are warned about.
- The
Metadata-Versionmust be a legal value. - The Summary should be over 10 characters, and the Description should be over a 100 characters.
- If your Description is ReStructuredText (the default), pyroma will convert it to HTML using Docutils, to verify that it is possible. This guarantees pretty formatting of your description on PyPI.
- The
Description-Content-Type, if given, must be a legal type/charset/variant combination. - You should have the following meta data fields filled in: classifiers, keywords, author, author_email and project URLs.
- You should have classifiers specifying the supported Python versions and the development status.
- You should have
requires-python/python_requiresspecifying the Python versions you support. - You should specify your license with the
License-Expressionfield. It must be a valid SPDX license expression; an invalid one, or combining it with the deprecatedLicensefield, is fatal since package indices reject such uploads. - Every
Requires-Distentry must be a valid dependency specifier; legacy parenthesized version specifiers and ordered comparisons on non-version environment markers are warned about. - Your project should have a
pyproject.tomldeclaring your build backend (any PEP 517 backend works: setuptools, flit, hatchling, uv_build, etc.). The file is validated against the pyproject.toml specification, including the[project]table rules (static name, static-or-dynamic version, readme/license exclusivity, noconsole_scripts/gui_scriptsentry-point groups). - Your
Project-URLlabels should include well-known labels such as Homepage, Source, Documentation, Changelog or Issues; labels over 32 characters are fatal since package indices reject them. - Deprecated metadata fields (
Home-page,Download-URL,Requires,Provides,Obsoletes,License) are warned about when your metadata version deprecates them. - If you are checking on a PyPI package, and not a local directory or local package, pyroma will check the number of owners the package has on PyPI. It should be three or more, to minimize the "Bus factor", the risk of the index owners suddenly going off-line for whatever reason.
- If you are checking on a PyPI package, and not a local directory or local package, pyroma will check that you have uploaded a source distribution, and not just binary distributions.
Version control integration
With pre-commit, pyroma can be run whenever you
commit your work by adding the following to your .pre-commit-config.yaml:
repos:
- repo: https://github.com/regebro/pyroma
rev: "5.0b2"
hooks:
- id: pyroma
Credits
The project was created by Lennart Regebro, regebro@gmail.com
The name "Pyroma" was coined by Wichert Akkerman, wichert@wiggy.net
Contributors:
- David Andreoletti
- Godefroid Chapelle
- Dmitry Vakhrushev
- Hugo van Kemenade
- Jeff Quast
- Maurits van Rees
- Hervé Beraud
- Érico Andrei
- Jakub Wilk
- Andreas Lutro
- Scott Colby
- Andrew Murray
- Nikita Sobolev
- Charles Tapley Hoyt
- Max Tyulin
- Michael Howitz
- Florian Bruhin
- Christopher A.M. Gerlach
- RuRo
- Wesley Barroso Lopes
- Alexander Bessman
- Matt Norton
Release files for pyroma621 6.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pyroma621-6.0.0.tar.gz | 82.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyroma621-6.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 165.7 kB
Release files / pyroma621-6.0.0.tar.gz
| Download URL | pyroma621-6.0.0.tar.gz |
|---|---|
| Size | 82.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ca98875daec28ca9891b0acf5e1a9722df287e098334c2c9e0efd38021ce184a
|
|
BLAKE2b-256 checksum How to use checksums |
907333ebf90ee693e07db4b6cf9697497cff4fd3823b5f7e3dc8be10a0b98743
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 1, 2026.
Transparency logRelease files / pyroma621-6.0.0-py3-none-any.whl
| Download URL | pyroma621-6.0.0-py3-none-any.whl |
|---|---|
| Size | 83.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
74580fd5c4158f5e2fc3e542b52e0835374bcc91b3fc8c140a6a58aefe5f4f01
|
|
BLAKE2b-256 checksum How to use checksums |
18e2978fc3ea5f8c51d41d8374d2f59b2163174c7fee2651e4fcbff577886a0d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 1, 2026.
Transparency log