Skip to main content
Yanked

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.

CI PyPI version Python versions Coverage type checked: pyright License: MIT

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/cp314t wheel 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-deps scans transitive deps via lock files with pinned-version accuracy
  • Progress tracking — ftready diff compares 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-ftchecker and --no-pypi flags 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
  1. Parse — reads your dependency file and extracts package names (+ pinned versions from lock files)
  2. Query PyPI — hits /pypi/{pkg}/json (or /pypi/{pkg}/{version}/json for pinned versions) in parallel
  3. Detect pure-Python — flags packages with only py3-none-any wheels and no C extensions
  4. Enrich — optionally fetches ft-checker.com test results (cached 24h)
  5. 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-any tag — meaning no compiled C extensions. These packages typically work on free-threaded Python without changes. However, packages using ctypes, 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

⚠️ 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-deps with a lock file for exact version checks.
  • Wheel tags ≠ runtime compatibility: A package shipping cp313t wheels 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

MIT

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)

Source distribution for ftready 1.0.0
File Size Uploaded
ftready-1.0.0.tar.gz 95.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ftready 1.0.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

1.0.0 This release

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