MT016: PythonVersionConsistency
Overview
| Property | Value |
|---|---|
| ID | MT016 |
| Name | PythonVersionConsistency |
| Group | metadata |
| Severity | WARNING |
Description
Verifies that the requires-python specifier and Python version classifiers in pyproject.toml are consistent.
Consistency matters because:
- Inconsistent metadata confuses users about supported Python versions
- Package installers may behave unexpectedly
- PyPI displays conflicting information
- CI/CD pipelines may test wrong versions
What it checks
The check parses requires-python and compares it to Programming Language :: Python :: X.Y classifiers:
- PASSED: All classifier versions fall within the
requires-pythonrange - FAILED: Classifiers list versions outside the
requires-pythonrange - NOT_APPLICABLE: Missing
requires-pythonor no Python version classifiers
Example of inconsistency
# Inconsistent: requires-python says >=3.9 but classifiers include 3.8
[project]
requires-python = ">=3.9"
classifiers = [
"Programming Language :: Python :: 3.8", # INVALID: below 3.9
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
]How to fix
Align classifiers with requires-python
# Consistent: classifiers match requires-python range
[project]
requires-python = ">=3.9"
classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]Update requires-python to match tested versions
If you actually support Python 3.8:
[project]
requires-python = ">=3.8"
classifiers = [
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
]Handle upper bounds
If you have an upper bound on Python version:
# Only supports Python 3.9 through 3.11
[project]
requires-python = ">=3.9,<3.12"
classifiers = [
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
# Don't include 3.12 - outside requires-python range
]Common mistakes
Including untested versions:
# Bad: claims 3.13 support without testing
[project]
requires-python = ">=3.9"
classifiers = [
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.13", # Have you tested this?
]Including deprecated versions:
# Bad: includes EOL Python versions
[project]
requires-python = ">=3.9"
classifiers = [
"Programming Language :: Python :: 3.6", # EOL, not in requires-python
"Programming Language :: Python :: 3.9",
]Why WARNING severity?
This check is a WARNING because:
- Inconsistency doesn’t break the package
- It causes confusion rather than failures
- Users may attempt installation on unsupported versions
- Some tools only check
requires-python, others check classifiers
Configuration
Skip this check
[tool.pycmdcheck]
skip = ["MT016"]CLI
pycmdcheck --skip MT016Best practices
- Test all claimed versions: Run CI on every Python version in classifiers
- Use version matrices: Define versions in one place and generate both
- Update together: When dropping/adding versions, update both fields
- Include generic classifier: Add
Programming Language :: Python :: 3 - Document version policy: Explain which Python versions you support
Matrix example for CI
# .github/workflows/test.yml
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]Keep classifiers in sync with CI
# pyproject.toml
[project]
requires-python = ">=3.9"
classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]