Skip to main content

wheeltruth

Your tests passed. Your published wheel is missing files.

wheeltruth checks that your built wheel/sdist actually contains everything the package needs — before your users find out the hard way.

The problem

twine check verifies your README renders. Nothing in the standard toolchain verifies that the files made it into the artifact. Two real cases from 2026:

  • MLX v0.32.0 (2026-07-25): the macOS ARM64 wheel shipped py.typed but silently dropped every .pyi stub the previous release had. Downstream type checking broke, and the test suite never noticed — because tests run against the source tree, not the wheel.
  • OpenSpace (2026-06-14): a tracked host_skills/ directory vanished from the built distribution, breaking integrations for everyone who installed it.

Build backends, MANIFEST.in glitches, and package-data misconfigurations drop files quietly. wheeltruth inspects the artifact itself — the thing PyPI actually serves — not your repo.

Install

pip install wheeltruth

Usage

# Check one or more built artifacts
wheeltruth check dist/*

# Compare a wheel against its sdist (catches files dropped between the two)
wheeltruth check dist/mypkg-1.0-py3-none-any.whl dist/mypkg-1.0.tar.gz

# Also verify expected packages from the project config
wheeltruth check dist/* --project .

# Install into a throwaway venv and import every top-level module
wheeltruth check dist/*.whl --smoke

# Machine-readable report for CI logs / PR comments
wheeltruth check dist/* --report md

Exit code is 0 when clean, 1 when issues are found — drop it straight into CI:

- name: Build
  run: python -m build
- name: Verify artifacts
  run: |
    pip install wheeltruth
    wheeltruth check dist/*

What it checks

Wheel only

  • RECORD completeness: every file in the zip is listed, every listed file exists, and sha256 hashes/sizes match (tampered or hand-edited wheels fail).
  • entry_points.txt: every console_scripts/gui_scripts target resolves to a module actually inside the wheel (no more ModuleNotFoundError on first run).
  • Typing stub coverage: in a typed package (ships py.typed or .pyi stubs), a compiled extension module (.so/.pyd/.dylib) with neither a .py source nor a .pyi stub is flagged — that's the case where downstream type checkers truly get nothing (the MLX case: the dropped stubs described compiled modules). Pure-Python packages with py.typed and inline annotations are not flagged.
  • METADATA name/version consistency with the wheel filename.

Wheel vs sdist

  • Files tracked in the sdist's packages that never made it into the wheel (the OpenSpace case), and vice versa. Handles src/ layouts and ignores tests/, docs/, etc.

With --project .

  • Packages declared in pyproject.toml / setup.cfg / setup.py (or auto-discovered) actually exist in the wheel.

With --smoke

  • Installs the wheel into a throwaway venv (--no-deps --no-index) and imports every top-level module.

Limitations (v0.2)

  • v0.2 is check-only: it reports problems, it doesn't fix your build config.
  • Heuristics, not proof: "expected files" are inferred from the sdist or project config. Exotic layouts may produce false positives — file an issue.
  • --smoke needs a working venv + pip and takes a few seconds per wheel.
  • Stub checks are consistency checks; they can't know what the previous release shipped.

License

MIT

Metadata

Release files for wheeltruth 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for wheeltruth 0.2.0
File Size Uploaded
wheeltruth-0.2.0.tar.gz 18.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for wheeltruth 0.2.0
File Interpreter ABI Platform
wheeltruth-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 31.8 kB

Release files / wheeltruth-0.2.0.tar.gz

Download URL wheeltruth-0.2.0.tar.gz
Size 18.0 kB
Tags Source
SHA-256 checksum
How to use checksums
5512d10e037fd54b7b23be3b34c26909ca3defc7bf401343a711ead355bfcea8
BLAKE2b-256 checksum
How to use checksums
371e3b85d6b43e6405d31a93cd3166d9ffe3dcf3544f800c5738f433c32be49b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / wheeltruth-0.2.0-py3-none-any.whl

Download URL wheeltruth-0.2.0-py3-none-any.whl
Size 13.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
57431151fd3365c3a6172ba8fbd120ff8b1394e3fb6e68fc89f6f1067eef49f1
BLAKE2b-256 checksum
How to use checksums
42777ad898bb6b2b2675fd97622b50581274ab81c63c25a5c12d604be8c9668e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page