Skip to main content

Check if your Python project dependencies are ready for free-threaded Python (3.13t/3.14t)

Project description

🧵 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 formatpyproject.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 trackingftready 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 Primarycp313t/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

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

ftready-1.0.0.tar.gz (95.0 kB view details)

Uploaded Source

Built Distribution

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

ftready-1.0.0-py3-none-any.whl (24.4 kB view details)

Uploaded Python 3

File details

Details for the file ftready-1.0.0.tar.gz.

File metadata

  • Download URL: ftready-1.0.0.tar.gz
  • Upload date:
  • Size: 95.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ftready-1.0.0.tar.gz
Algorithm Hash digest
SHA256 bee4ea37e949a93ad075676521b02aaf478821c5c2a907c002f7c4d406c4dc04
MD5 7f0bde542d1c660cc14eecfb98767a70
BLAKE2b-256 ea9940b70cc2d2cac8adcbce732a8171e05b15cd8a63000c0bed7b4c900220f2

See more details on using hashes here.

Provenance

The following attestation bundles were made for ftready-1.0.0.tar.gz:

Publisher: publish.yml on dxvidparham/ftready

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ftready-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: ftready-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 24.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ftready-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e62f027c375ea039982dccaf5fa680fb66411569bba6502e4d47de967f672d74
MD5 1a2af3989a3119253c26f5a8b72dec43
BLAKE2b-256 f8cd920e4318378a07316990b278e672f854b432e4bc792f08c66073d51e9381

See more details on using hashes here.

Provenance

The following attestation bundles were made for ftready-1.0.0-py3-none-any.whl:

Publisher: publish.yml on dxvidparham/ftready

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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