Skip to main content

compat-check

test

Check whether a GitHub repo or PyPI package would install cleanly in this environment — before you actually install it.

$ compat-check https://github.com/pallets/flask
compat-check: https://github.com/pallets/flask
backend: uv
requirements checked: blinker>=1.9.0, click>=8.1.3, itsdangerous>=2.2.0, jinja2>=3.1.2, markupsafe>=2.1.1, werkzeug>=3.1.0

OK — 6 package(s) would install cleanly:
  + blinker==1.9.0
  + click==8.5.0
  ...
$ compat-check some-package-with-a-real-conflict
PROBLEMS FOUND — 1 package(s) cannot be resolved:

  [numpy]
      × No solution found when resolving dependencies:
      ╰─▶ Because you require numpy>=2.0 and numpy<1.20, we can conclude that your
          requirements are unsatisfiable.

Why this instead of uv/pip themselves

uv and pip already resolve dependencies — that's not the gap. Two things are:

  • You still have to actually run the install (or a dry-run) yourself, reading whatever error comes back. compat-check does that in a throwaway venv and hands you a plain-language pass/fail, without touching your real environment.
  • Both resolvers are fail-fast: a single dry-run call reports only the first unsatisfiable requirement. If two unrelated packages in the same requirements.txt are both broken, one hides behind the other. compat-check drops each failure and retries until every one surfaces.

It does not try to out-resolve uv/pip — it wraps them (preferring uv when available, falling back to the standard-library venv + pip when it isn't) and reports what actually happened, not a static prediction from metadata.

What it checks

  • Whether every requirement resolves at all (missing versions, yanked releases, platform/ABI mismatches — reported with the resolver's own explanation)
  • Whether requirements in the same source conflict with each other

What it deliberately does not check (yet)

  • BLAS/LAPACK backend compatibility — this is a post-install diagnostic (numpy.show_config()), not something knowable before installing
  • GPU/CUDA driver compatibility beyond what the resolver itself reports — PyTorch-style packages that ship on a separate index aren't covered
  • setup.py-only packages with no pyproject.toml/requirements.txt/ setup.cfg (would require unsafe code execution to parse reliably)

Install

Not yet published to PyPI — install directly from the repo:

uv tool install git+https://github.com/jahyunlee00299/compat-check

(or pipx install git+https://github.com/jahyunlee00299/compat-check, or clone and pip install . into a venv)

Usage

compat-check <github-url-or-pypi-package-name> [--python 3.11] [--no-cache] [--tree]

Exit codes: 0 clean, 1 conflicts found, 2 source could not be resolved at all (bad URL, nonexistent package), 3 invalid parameter (checked before any network call, so a typo costs nothing).

--python and the pip fallback

--python is honoured only by the uv backend. The pip fallback builds its venv with the standard-library venv module, which can only clone the interpreter compat-check is itself running on — it cannot fetch another version. Rather than accept the flag and quietly ignore it, the report states the version actually probed:

$ compat-check requests --python 3.9     # on a machine without uv
compat-check: requests
backend: pip
python: 3.13 (requested 3.9 — NOT honoured)

with the reason on stderr. The cache is keyed on the version that was really used, so two requests that run the identical probe share one cache entry instead of being stored under two versions, only one of which was measured. Install uv to target other Python versions for real.

--tree shows the full dependency tree (requires uv — no pip-backend equivalent exists):

$ compat-check https://github.com/pallets/flask --tree
...
https://github.com/pallets/flask
├── blinker v1.9.0
├── click v8.5.0
├── itsdangerous v2.2.0
├── jinja2 v3.1.6
│   └── markupsafe v3.0.3
├── markupsafe v3.0.3
└── werkzeug v3.1.8
    └── markupsafe v3.0.3

Results are cached locally (~/.cache/compat_check/, 7-day TTL) since a dry-run against the same environment and requirements won't change minute-to-minute. Use --no-cache to force a fresh probe. The cache holds the 500 most recent entries (oldest evicted first) and is invalidated automatically when compat-check's own version changes, so a resolver change never serves an answer computed by an older build.

How it works

  1. Fetch the requirement list — from pyproject.toml, requirements.txt, or setup.cfg on the GitHub repo, or from PyPI's JSON API for a bare package name. A requirements.txt that uses -r other.txt has those files fetched and spliced in, so the list is the complete one: on home-assistant/core that is 51 requirements rather than the 47 visible in the root file. An include that cannot be read is an error, never a silently shorter list.

    -c constraint files are read but kept separate — a constraint pins a package if something pulls it in, so treating those entries as requirements would inflate the same repo to 181 packages it never asked to install.

  2. Create a disposable virtual environment.

  3. Run pip install --dry-run (or uv pip install --dry-run) against it — this resolves and would-download, but never actually installs anything or runs arbitrary setup code from the target package.

  4. Report the result, retrying with failing packages dropped one at a time so every conflict in a multi-package source gets surfaced, not just the first one the resolver hits.

License

MIT

Release files for compat-check 0.3.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 compat-check 0.3.0
File Size Uploaded
compat_check-0.3.0.tar.gz 34.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for compat-check 0.3.0
File Interpreter ABI Platform
compat_check-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 61.9 kB

Release files / compat_check-0.3.0.tar.gz

Download URL compat_check-0.3.0.tar.gz
Size 34.5 kB
Tags Source
SHA-256 checksum
How to use checksums
a7a30679cb584f1db98bea64d0e35d77013ca00f83a39a066e785f9c62b867a7
BLAKE2b-256 checksum
How to use checksums
abcbb76f7e4be7e931fffacdd707cb774a2635e8dbaef114bd453d346254ede8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release files / compat_check-0.3.0-py3-none-any.whl

Download URL compat_check-0.3.0-py3-none-any.whl
Size 27.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6225bd8beefc3993bc47f77c9e06d4b0134cbeab0c1de9d74a0e35b3c1ffa799
BLAKE2b-256 checksum
How to use checksums
e0d5067780b124e518342fcc4aa6d9ab0dbe71b8b682fb8135e232eefc95d0ba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release history Release notifications | RSS feed

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

This release

0.3.0 This release

2 release files

0.2.0

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