This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Reason given by maintainers: Unmaintained
🧵 ftready
Is your project ready for free-threaded Python? Find out in one command.
Quickstart · Features · Usage · Tracking Progress · CI Integration · Python API · PyPI
PEP 703 introduced a free-threaded build of CPython (3.13t) that disables the GIL — unlocking true multi-core parallelism. PEP 779 made free-threading a supported (no longer experimental) feature in CPython 3.14. But your project is only as ready as its least-compatible dependency. See the free-threading guide for background.
ftready scans your dependency tree, queries PyPI for cp313t/cp314t wheels, cross-references ft-checker.com test results, and tells you exactly where you stand:
Package Compatibility Details
─────────────────────────────────────────────────────
numpy ✅ Success free-threaded wheel found
pandas ✅ Success free-threaded wheel found
scipy ✅ Success free-threaded wheel found
scikit-learn ✅ Success free-threaded wheel found
matplotlib ✅ Success free-threaded wheel found
pillow ✅ Success free-threaded wheel found
opencv-python ⬜ Not tested
tqdm 🐍 Pure Python likely compatible (no C extensions)
loguru 🐍 Pure Python likely compatible (no C extensions)
─────────────────────────────────────────────────────
✅ 6 passed · ❌ 0 failed · ⬜ 1 unknown · 🐍 2 pure
⚡ Quickstart
pip install ftready # or: uv tool install ftready
ftready
That's it. Reads your pyproject.toml and prints a compatibility report.
🎯 Features
- PyPI-first detection — queries
cp313t/cp314twheel tags in parallel for every dependency - Real test results — enriches with ft-checker.com data covering ~1000 top packages
- Pure-Python detection — flags packages with no C extensions as likely compatible
- Every input format —
pyproject.toml(PEP 621 + Poetry),requirements.txt,uv.lock,poetry.lock,pdm.lock - Full dependency tree —
--all-depsscans transitive deps via lock files with pinned-version accuracy - Progress tracking —
ftready diffcompares two JSON reports to show what changed over time - Multiple outputs — rich tables, plain text, JSON, or CSV
- CI-ready — configurable exit codes (
--fail-on) to gate or report without blocking - Offline-safe —
--no-ftcheckerand--no-pypiflags for controlled environments
📖 Usage
Input sources
ftready # pyproject.toml in current dir
ftready --pyproject path/to/pyproject.toml # specific pyproject.toml
ftready --requirements requirements.txt # requirements file
ftready --include-dev # include dev dependencies
ftready --all-deps # full tree (auto-detects lock file)
ftready --all-deps --lock path/to/uv.lock # specific lock file
Output formats
ftready # rich table (default)
ftready --plain # plain-text table
ftready --format json # JSON (for scripting)
ftready --format csv # CSV
ftready --output report.txt # write to file
ftready -v # verbose progress to stderr
Data source control
ftready --no-ftchecker # PyPI only (skip ft-checker.com)
ftready --no-pypi # ft-checker only (skip PyPI)
ftready --no-cache # force fresh ft-checker scrape
ftready --cache-ttl 48 # cache ft-checker data for 48 hours
ftready --cache-file /tmp/ft_cache.json # custom cache location
Exit codes
| Code | Meaning |
|---|---|
0 |
No blocking issues (configurable via --fail-on) |
1 |
At least one dependency has a Failed status |
2 |
Configuration error (missing input file, etc.) |
ftready --fail-on=never # always exit 0 (report only)
ftready --fail-on=unknown # exit 1 on Failed OR Unknown
ftready --fail-on=failed # exit 1 on Failed only (default)
📈 Tracking Progress
Save JSON reports over time and use ftready diff to see what changed:
# Save a baseline
ftready --format json --output baseline.json
# ... weeks later, check again
ftready --format json --output current.json
# Compare the two
ftready diff baseline.json current.json
ftready diff: 2025-01-15T12:00:00+00:00 → 2025-03-01T12:00:00+00:00
3.13t ready: 5 → 8 (+3)
3.14t ready: 2 → 5 (+3)
✅ Improved (3):
scipy: 3.13t: Not tested → Success
pillow: 3.13t: Not tested → Success, 3.14t: Not tested → Success
matplotlib: 3.14t: Not tested → Success
The diff also supports --format json for machine-readable output.
🔄 How It Works
pyproject.toml ─┐
requirements.txt ┼──▶ Parse ──▶ PyPI API ──▶ ft-checker.com ──▶ Report
uv.lock ────────┘ │ (parallel) (optional) │
│ │
└── pinned versions ──▶ exact endpoint ▼
table/json/csv
- Parse — reads your dependency file and extracts package names (+ pinned versions from lock files)
- Query PyPI — hits
/pypi/{pkg}/json(or/pypi/{pkg}/{version}/jsonfor pinned versions) in parallel - Detect pure-Python — flags packages with only
py3-none-anywheels and no C extensions - Enrich — optionally fetches ft-checker.com test results (cached 24h)
- Report — renders results as a styled table, JSON, or CSV with configurable exit codes
About "Pure Python": A package is flagged as 🐍 when all its published wheels use the
py3-none-anytag — meaning no compiled C extensions. These packages typically work on free-threaded Python without changes. However, packages usingctypes,cffi, or calling native code at runtime may still have issues despite being "pure." Treat this as a strong signal, not a guarantee.
🏗 CI Integration
Report without blocking:
- name: Check free-threaded compatibility
run: |
pip install ftready
ftready --plain --fail-on=never -v
Gate on failures:
- name: Check free-threaded compatibility
run: |
pip install ftready
ftready --plain -v
JSON artifact for downstream processing:
- name: Check free-threaded compatibility
run: |
pip install ftready
ftready --format json --output ft-report.json --fail-on=never
- uses: actions/upload-artifact@v4
with:
name: ft-compat-report
path: ft-report.json
Track progress across CI runs by downloading a previous artifact and diffing:
- name: Compare with baseline
run: |
pip install ftready
ftready --format json --output current.json --fail-on=never
ftready diff baseline.json current.json || true
🐍 Python API
ftready exports a public API for programmatic use:
from ftready import (
load_dependencies,
fetch_ftchecker_db,
build_results,
generate_report,
diff_reports,
format_diff,
)
from pathlib import Path
# Load deps from pyproject.toml
deps = load_dependencies(Path("pyproject.toml"))
# Query data sources
ft_db = fetch_ftchecker_db(Path(".ft_cache.json"))
results = build_results(deps, ft_db)
# Render as JSON
report = generate_report(results, include_dev=False, output_format="json")
# Compare two JSON reports
summary = diff_reports("old_report.json", "new_report.json")
print(format_diff(summary))
📊 Data Sources
| Source | Role | Coverage |
|---|---|---|
| PyPI JSON API | Primary — cp313t/cp314t wheel tag detection |
Every package on PyPI |
| PyPI version endpoint | Primary — pinned-version checking from lock files | Every package on PyPI |
| ft-checker.com | Enrichment — actual test results | ~1000 top packages |
When both sources report on a package, ft-checker.com takes priority — a package may ship free-threaded wheels but still fail tests.
Related resources
- py-free-threading.github.io — official porting guide, C-API status, and ecosystem tracker
- hugovk.dev/free-threaded-wheels — auto-updated dashboard of the top 360 packages with free-threaded wheels
⚠️ Limitations
- Latest release only (without lock files): When no lock file is used, ftready checks the latest PyPI release. If you're pinned to an older version, use
--all-depswith a lock file for exact version checks. - Wheel tags ≠ runtime compatibility: A package shipping
cp313twheels doesn't guarantee it works correctly under free-threaded Python — it only means the maintainer built wheels for that target. ft-checker.com test results provide stronger evidence. - ft-checker.com coverage: The enrichment source covers ~1000 popular packages. Niche packages may only have PyPI wheel tag data.
- No transitive blocker tracing: The tool reports status per-package but doesn't show dependency chains (e.g., "X depends on Y which depends on Z, and Z is the blocker").
📄 License
Metadata
Release files for ftready 1.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 | |
|---|---|---|---|
| ftready-1.0.0.tar.gz | 95.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ftready-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 119.4 kB
Release files / ftready-1.0.0.tar.gz
| Download URL | ftready-1.0.0.tar.gz |
|---|---|
| Size | 95.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bee4ea37e949a93ad075676521b02aaf478821c5c2a907c002f7c4d406c4dc04
|
|
BLAKE2b-256 checksum How to use checksums |
ea9940b70cc2d2cac8adcbce732a8171e05b15cd8a63000c0bed7b4c900220f2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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 Apr 6, 2026.
Transparency logRelease files / ftready-1.0.0-py3-none-any.whl
| Download URL | ftready-1.0.0-py3-none-any.whl |
|---|---|
| Size | 24.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e62f027c375ea039982dccaf5fa680fb66411569bba6502e4d47de967f672d74
|
|
BLAKE2b-256 checksum How to use checksums |
f8cd920e4318378a07316990b278e672f854b432e4bc792f08c66073d51e9381
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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 Apr 6, 2026.
Transparency log