Python packaging quality assessment tool that evaluates how well Python projects comply with best practices of the Python packaging ecosystem.
—
Comprehensive quality assessment system with pluggable tests that evaluate various aspects of Python packaging best practices. The rating system provides detailed feedback, actionable recommendations, and numerical scores from 0-10 with humorous cheese-themed descriptions.
rate(data, skip_tests=None)
def rate(data, skip_tests=None):
"""Rate package metadata quality using comprehensive test suite.
Args:
data: Package metadata dictionary from data extraction modules
skip_tests: List of test class names to skip during evaluation
Returns:
tuple: (rating: int, failures: list[str])
- rating: Numerical score from 0-10
- failures: List of failure messages for failed tests
Example:
>>> data = projectdata.get_data('/path/to/project')
>>> rating, failures = rate(data)
>>> print(f"Rating: {rating}/10")
>>> for failure in failures:
... print(f"- {failure}")
"""The main rating function that:
get_all_tests()
def get_all_tests():
"""Get list of all available test class names.
Returns:
list: List of test class names for use with skip_tests parameter
Example:
['Name', 'Version', 'VersionIsString', 'PEPVersion', 'Description',
'LongDescription', 'Classifiers', 'ClassifierVerification', ...]
"""get_code_licenses()
def get_code_licenses():
"""Build mapping of license short codes to classifier strings.
Returns:
dict: Mapping from license codes (e.g., 'MIT', 'GPL') to
sets of corresponding trove classifiers
Example:
{'MIT': {'License :: OSI Approved :: MIT License'},
'GPL': {'License :: OSI Approved :: GNU General Public License v2 (GPLv2)', ...}}
"""ALL_TESTS
ALL_TESTS: list
"""List of all available test instances.
Contains instantiated test objects for all quality checks.
Used internally by the rating system to run evaluations.
"""LEVELS
LEVELS: list
"""Rating descriptions with cheese-themed messages.
Index corresponds to rating (0-10):
- 0: "This cheese seems to contain no dairy products"
- 1: "Vieux Bologne"
- 2: "Limburger"
- ...
- 10: "Your cheese is so fresh most people think it's a cream: Mascarpone"
"""CODE_LICENSES
CODE_LICENSES: dict
"""Mapping of license codes to trove classifier sets.
Built from trove-classifiers package, provides lookup from
common license abbreviations to their full classifier names.
"""PEP386_RE
PEP386_RE: re.Pattern
"""Compiled regex pattern for validating PEP-386 version format.
Used internally by PEPVersion test to validate legacy version formats.
Matches versions like '1.0', '1.0.1', '1.0a1', '1.0.post1', '1.0.dev1'.
"""PEP440_RE
PEP440_RE: re.Pattern
"""Compiled regex pattern for validating PEP-440 version format.
Used internally by PEPVersion test to validate modern version formats.
Supports epochs, pre-releases, post-releases, dev releases, and local versions.
"""SHORT_NAME_RE
SHORT_NAME_RE: re.Pattern
"""Compiled regex pattern for extracting license short names from classifiers.
Used by get_code_licenses() to parse license abbreviations from
trove classifier strings like 'License :: OSI Approved :: MIT License'.
"""The rating system includes comprehensive tests organized by category:
Tests that must pass for any meaningful rating:
Name
Version
VersionIsString
PEPVersion
Description
LongDescription
ValidREST
Classifiers
ClassifierVerification
PythonClassifierVersion
PythonRequiresVersion
Keywords
Author
AuthorEmail
Url
Licensing
DevStatusClassifier
SDist
BusFactor
MissingBuildSystem
MissingPyProjectToml
StoneAgeSetupPy
CheckManifest
from pyroma.ratings import rate, get_all_tests, LEVELS
from pyroma.projectdata import get_data
# Basic rating
data = get_data('/path/to/project')
rating, failures = rate(data)
print(f"Rating: {rating}/10 - {LEVELS[rating]}")
# Skip specific tests
rating, failures = rate(data, skip_tests=['BusFactor', 'SDist'])
# List available tests
tests = get_all_tests()
print("Available tests:", ', '.join(tests))
# Detailed analysis
if failures:
print("Issues found:")
for failure in failures:
print(f" - {failure}")
else:
print("No issues found!")BaseTest
class BaseTest:
"""Base class for all quality assessment tests.
Attributes:
fatal: bool - If True, failure results in rating 0
weight: int - Relative importance for scoring (default varies)
"""
fatal: bool = False
weight: int
def test(self, data): ...
def message(self): ...FieldTest
class FieldTest(BaseTest):
"""Base class for tests checking field presence and non-emptiness.
Attributes:
field: str - Metadata field name to check
"""
field: str
def test(self, data): ...
def message(self): ...Install with Tessl CLI
npx tessl i tessl/pypi-pyroma