Skip to main content

Offline deep validator for pyproject.toml: file existence, URL and email format, PEP 440 version and PEP 508 specifier validity, version-constraint satisfiability, and entry-point format.

Project description

pyproject-doctor

pyproject-doctor logo

Offline deep validator for pyproject.toml that catches the semantic mistakes other tools miss.

Most validators only check TOML syntax. pyproject-doctor goes further: it validates that your versions are PEP 440 compliant, your requires-python is a valid specifier set, your dependencies are PEP 508 compliant, your version constraints are actually satisfiable, your referenced files exist, your URLs are real URLs, your email addresses look right, and your entry-point references are correctly formatted.

What it checks

Code Description
version-invalid project.version is not a valid PEP 440 version
requires-python-invalid project.requires-python is empty, malformed, not a valid PEP 440 specifier set, or unsatisfiable (e.g. >=3.12,<3.8)
dep-invalid A dependency in project.dependencies, project.optional-dependencies, or build-system.requires is not a valid PEP 508 requirement
constraint-unsatisfiable A dependency's version specifiers form an impossible range (e.g. >=2.0,<1.0)
file-missing A file referenced by project.readme, project.license, or an entry-point module does not exist
url-invalid A value in project.urls is not a valid absolute URL
email-invalid An author or maintainer email address is malformed
entry-point-invalid A script or entry-point value is not in valid module:attr format
classifier-unknown A classifier in project.classifiers is not a known trove classifier (requires pip install 'pyproject-doctor[classifiers]')
dynamic-malformed project.dynamic is not a list of strings
dynamic-name-forbidden name appears in project.dynamic (PEP 621 requires it to always be static)
dynamic-field-unknown An entry in project.dynamic is not a recognized [project] field name
dynamic-static-conflict A field listed in project.dynamic is also set statically in [project]
license-expression-invalid project.license in its modern PEP 639 string form is not a valid SPDX license expression: empty, an unknown license or exception identifier, a deprecated identifier, the disallowed + suffix (use the -or-later form), a misplaced operator, or unbalanced parentheses. The legacy table form ({ file = ... } / { text = ... }) is not treated as an expression

Install

pip install pyproject-doctor

Or with classifier validation:

pip install "pyproject-doctor[classifiers]"

Usage

# Validate pyproject.toml in the current directory
pyproject-doctor

# Validate a specific file
pyproject-doctor /path/to/pyproject.toml

# JSON output
pyproject-doctor --format json

# SARIF 2.1.0 output (for GitHub code scanning and other SARIF consumers)
pyproject-doctor --format sarif

Exit code is 1 if any error-level diagnostic is found, 0 otherwise.

The sarif format emits a SARIF 2.1.0 log: each diagnostic becomes one result, the diagnostic code is the ruleId, every result points at the analyzed pyproject.toml, and the SARIF level (error, warning, note) is derived from the diagnostic's level.

Pre-commit

Add to .pre-commit-config.yaml:

repos:
  - repo: https://github.com/amaar-mc/pyproject-doctor
    rev: v0.4.0
    hooks:
      - id: pyproject-doctor

Example output

error project.version: version-invalid: 'not.a.version' is not a valid PEP 440 version
error project.dependencies[0]: constraint-unsatisfiable: Dependency 'requests': constraint '>=3.0,<2.0' is unsatisfiable (lower bound 3.0 exceeds upper bound 2.0)
error project.urls.Homepage: url-invalid: URL 'not-a-url' is not a valid absolute URL (must have scheme and host)

License

MIT. Copyright (c) 2026 Amaar Chughtai.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyproject_doctor-0.4.0.tar.gz (956.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyproject_doctor-0.4.0-py3-none-any.whl (22.2 kB view details)

Uploaded Python 3

File details

Details for the file pyproject_doctor-0.4.0.tar.gz.

File metadata

  • Download URL: pyproject_doctor-0.4.0.tar.gz
  • Upload date:
  • Size: 956.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for pyproject_doctor-0.4.0.tar.gz
Algorithm Hash digest
SHA256 79c449ad925632b46f690822d071223e2a85c62a71b6d85516059fd5658e3aea
MD5 f0517fe99ac382e7477771185a147ddc
BLAKE2b-256 a984c71402cc47ae70962c024dd55ca3bb608798e66431344155d90c87144c5c

See more details on using hashes here.

File details

Details for the file pyproject_doctor-0.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pyproject_doctor-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5c8c45f27e9cf4fe888cfdc3d10efe85b6ffe6359a194278a3ed7c355305d335
MD5 902ac61448415ca062fb29140cc6f57c
BLAKE2b-256 7d036ccad3ff773b1752ac01be33a1f3c636c3d27a0caed9fa4b27ec0059c2cd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page