Skip to main content

pyupcheck

Check if upgrading a Python dependency will break your code.

$ pyupcheck check-all

Found 12 dependencies to check

flask 2.3.3 -> 3.1.3  OK (15 usages safe)
requests 2.28.0 -> 2.34.2  2 BREAKING
  x src/api.py:23  resp = requests.get(url, verify=False)
    Removed: `verify` parameter no longer accepted
django 4.2.0 -> 5.0.6  1 deprecated
  ! core/models.py:8  from django.utils import timezone
    Deprecated: use datetime.timezone instead

2 breaking | 1 deprecated across 12 packages

Install

pip install pyupcheck

Commands

check - check one package

pyupcheck check flask 3.0.0        # against specific version
pyupcheck check flask              # against latest

check-all - check every dependency

Reads requirements.txt and pyproject.toml (PEP 621 and Poetry), checks every dependency against its latest version.

pyupcheck check-all
pyupcheck check-all --format html -o report.html

outdated - list stale dependencies

pyupcheck outdated

Flags major version bumps separately since they carry the most risk.

diff - changelog diff between versions

See breaking/deprecated changes between any two versions without scanning code:

pyupcheck diff django 4.2.0 5.0.0

scan - list your usages of a package

pyupcheck scan requests

versions and cache-clear

pyupcheck versions flask
pyupcheck cache-clear

Output formats

pyupcheck check flask -f json          # machine-readable
pyupcheck check flask -f md -o r.md   # markdown report
pyupcheck check flask -f html -o r.html # styled HTML report

CI integration

Exit code is 1 when the --fail-on condition is met:

pyupcheck check-all --fail-on breaking     # default
pyupcheck check-all --fail-on deprecated   # stricter
pyupcheck check-all --fail-on any          # strictest
pyupcheck check-all --fail-on never        # report only

GitHub Actions example:

- name: Check dependency upgrades
  run: |
    pip install pyupcheck
    pyupcheck check-all --fail-on breaking --quiet

Pre-commit hook (.pre-commit-config.yaml):

- repo: local
  hooks:
    - id: pyupcheck
      name: pyupcheck
      entry: pyupcheck check-all --quiet
      language: system
      pass_filenames: false

Configuration

pyproject.toml:

[tool.pyupcheck]
exclude = ["migrations", "legacy"]
ignore = ["internal-package"]
fail_on = "breaking"
min_severity = "deprecated"
cache = true

Or .pyupcheckignore:

migrations/          # trailing slash = directory
legacy/
internal-package     # no slash = package to skip

Deep mode

By default, pyupcheck detects breaking changes by parsing changelogs. That's fast but depends on maintainers writing good changelogs. Deep mode goes further:

pyupcheck check requests 3.0.0 --deep

In deep mode, pyupcheck downloads both versions of the package, extracts their actual public API surface (every module, class, function, and signature), and computes a precise diff. It then matches that against your code at the argument level, so it can tell you:

  • A function you call was removed
  • A class you import no longer exists
  • A keyword argument you pass (like verify=False) was removed from a function signature

These findings are marked [FACT] in the output because they come from the real code, not changelog prose. Deep mode is slower (it downloads and parses packages) but far more accurate.

Features

  • AST-based scanning: imports, from-imports, aliases, attribute chains, calls
  • Argument-level analysis: knows which keyword arguments you pass
  • Real API surface diffing in --deep mode
  • Jupyter notebook (.ipynb) and type stub (.pyi) scanning
  • Dynamic import detection (importlib.import_module, __import__)
  • Changelog sources: GitHub releases, raw changelog files, PyPI descriptions
  • Parses requirements.txt, pyproject.toml, setup.cfg, setup.py, environment.yml
  • 24h response cache (--no-cache to bypass, cache-clear to wipe)
  • Severity filtering with --min-severity
  • Quiet mode (-q) for hooks and scripts

Limitations

  • Changelog parsing relies on maintainers writing structured changelogs
  • Dynamic attribute access (getattr(pkg, name)) is not detected
  • GitHub API is rate limited to 60 req/hr unauthenticated; pass --github-token or set GITHUB_TOKEN for higher limits

Contributing

Contributions are welcome. Here is how to get started:

git clone https://github.com/Astronomox/pyupcheck-Astronomox.git
cd pyupcheck
pip install -e "."

Releasing (for maintainers and forks)

An upload.bat script is included to build and publish in one step. Get a PyPI API token from https://pypi.org/manage/account/token/ and run:

upload.bat YOUR_PYPI_TOKEN

It cleans old builds, builds the package, uploads to PyPI, installs the new version locally, and shows the banner to confirm. Never commit your token.

Things that would genuinely improve the tool:

  • Better changelog parsing for packages that use unconventional formats (Sphinx-based changelogs, HISTORY files)
  • pip-tools and conda lockfile support
  • A --watch mode that monitors your lockfile for changes and alerts on risky upgrades
  • Test coverage

To contribute, open an issue describing what you want to work on, then submit a pull request. Include a short test or example showing the bug or feature.

If you find a package whose changelog pyupcheck fails to parse correctly, open an issue with the package name and version range. That is the most common and most impactful thing to fix.

License

MIT

Metadata

Release files for pyupcheck 0.4.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 pyupcheck 0.4.0
File Size Uploaded
pyupcheck-0.4.0.tar.gz 29.5 kB Details

Built distribution (wheel)

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

Total release size: 60.2 kB

Release files / pyupcheck-0.4.0.tar.gz

Download URL pyupcheck-0.4.0.tar.gz
Size 29.5 kB
Tags Source
SHA-256 checksum
How to use checksums
a906118bc3e18dd10aff6b3caabbe9042c96daccfcaed44971c120cc962f14ee
BLAKE2b-256 checksum
How to use checksums
9ccf04147277c716fe439d7fa4ae64fc766834a9658a9fcaf15eb4c571e9f9cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / pyupcheck-0.4.0-py3-none-any.whl

Download URL pyupcheck-0.4.0-py3-none-any.whl
Size 30.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0cff91ce2d1444b1592e4334ccdaa7b74d7e0893ddeb666d9e9bb6faf14befec
BLAKE2b-256 checksum
How to use checksums
e1d7d6a0484ee3d005eee131a6ff2743b05b05b61ea3b7ecf0537b6b34bda51a
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

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

This release

0.4.0 This release

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.0

2 release files

0.2.1

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