Skip to main content

pyrift

Detect silent Python behaviour differences across CPython versions and CPython vs PyPy.

PyPI version Python 3.10+ Tests License: MIT PyPI Downloads


What is pyrift?

Python upgrades and cross-runtime compatibility (CPython vs PyPy) introduce silent behaviour differences — code that runs without errors but produces wrong results, leaks resources, or crashes only in certain environments.

These are not syntax errors. Linters won't catch them. They are not CVEs. Security scanners won't catch them. They only appear at runtime, often in production.

pyrift statically detects these patterns before they become bugs.


Install

pip install pyrift

Zero external dependencies. Pure Python. Works on Python 3.10+.


Quick start — CLI

# Scan current directory
pyrift scan .

# Scan a specific path
pyrift scan ./src

# JSON output (for CI integration)
pyrift scan . --format json

# Markdown report saved to file
pyrift scan . --format markdown --output report.md

# Check version
pyrift --version

Example output

[ERROR] src/server.py:42 CPY002: Exception.add_note() requires Python 3.11+
→ Guard with: if sys.version_info >= (3, 11): e.add_note(...)

[ERROR] src/compat.py:17 CPY007: Module removed in Python 3.13
→ Find a third-party replacement for 'cgi' on PyPI

[WARNING] src/resource.py:88 PPY001: Relying on del for resource cleanup breaks on PyPy
→ Use context managers (with statement) or try/finally blocks

Scanned 23 file(s). Found 2 error(s), 1 warning(s). Score: 77/100

Quick start — Python API

import pyrift

# Scan a directory
result = pyrift.scan("./src")

print(result)
# ScanResult(files=23, errors=2, warnings=1, score=77)

# Iterate findings
for finding in result.findings:
    print(finding)

# Filter by severity
for error in result.errors:
    print(f"{error.file}:{error.line}{error.title}")

# Export formats
json_output     = pyrift.to_json(result)
markdown_output = pyrift.to_markdown(result)
text_output     = pyrift.to_text(result)

# Scan a single file
findings = pyrift.scan_file("./src/utils.py")

Rules

CPython rules — version compatibility

ID Title Severity Affects
CPY001 Dict ordering assumption Warning CPython < 3.7
CPY002 Exception.add_note() requires Python 3.11+ Error CPython ≤ 3.10
CPY003 X | Y union type syntax requires Python 3.10+ Error CPython ≤ 3.9
CPY004 tomllib requires Python 3.11+ Error CPython ≤ 3.10
CPY005 match/case requires Python 3.10+ Error CPython ≤ 3.9
CPY006 asyncio.timeout() / TaskGroup requires Python 3.11+ Error CPython ≤ 3.10
CPY007 Module removed in Python 3.13 (21 modules) Error CPython ≥ 3.13

PyPy rules — runtime differences

ID Title Severity Affects
PPY001 Relying on __del__ for resource cleanup Error PyPy all versions
PPY002 ctypes usage may silently fail Warning PyPy all versions
PPY003 sys.getrefcount() is meaningless on PyPy Error PyPy all versions
PPY004 weakref.proxy() raises ReferenceError unpredictably Warning PyPy all versions

Full rule documentation: docs/rules.md


Use in CI

Add pyrift to your GitHub Actions workflow:

- name: Run pyrift
  run: |
    pip install pyrift
    pyrift scan . --format json --output pyrift-report.json
    pyrift scan .

Exit code is 1 when errors are found — fails the CI build automatically. Use --exit-zero to report without failing.


Use with pre-commit

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/BHUVANSH855/pyrift
    rev: v0.2.0
    hooks:
      - id: pyrift

Why pyrift?

Tool What it catches What it misses
pylint / ruff Style, common bugs Runtime behaviour differences
mypy / pyright Type errors Runtime behaviour differences
pip-audit Known CVEs Behaviour differences
bandit Security patterns Behaviour differences
pyrift Silent runtime behaviour differences (that's the whole point)

pyrift does not replace any of these tools. It catches what they all miss.


Contributing

Contributions are very welcome — especially new rules for behaviour differences you have personally encountered.

See CONTRIBUTING.md for the full guide.


Project status

  • Version: 0.2.0
  • Rules: 11 (7 CPython + 4 PyPy)
  • Tests: 45 passing
  • Dependencies: zero
  • Python: 3.10+

Author

Built by Bhuvansh Kataria — CPython contributor and PyPy toolkit author.


License

MIT — see LICENSE

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyrift-0.3.0.tar.gz (23.8 kB view details)

Uploaded Source

Built Distribution

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

pyrift-0.3.0-py3-none-any.whl (29.4 kB view details)

Uploaded Python 3

File details

Details for the file pyrift-0.3.0.tar.gz.

File metadata

  • Download URL: pyrift-0.3.0.tar.gz
  • Upload date:
  • Size: 23.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.6

File hashes

Hashes for pyrift-0.3.0.tar.gz
Algorithm Hash digest
SHA256 c31ba34af9195db7fdbf0ba928de7f2534edadcf951c77ec88d0530156393f6e
MD5 3bcca30bc52f82366778df4b44e0bbbe
BLAKE2b-256 a453aa42e156e7370001531a6f730c2d8bb9db478311a013b2c09959322917f3

See more details on using hashes here.

File details

Details for the file pyrift-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: pyrift-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 29.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.6

File hashes

Hashes for pyrift-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b6eb5573d02d4d9f550d3fcae82184cc42256097fd2654003b8eca66fe28ecd8
MD5 fac6d1a077b5527249d024d7a259898f
BLAKE2b-256 9dbce0786775d4052c775672493e42a46db38178e242b00b896dbbb025642300

See more details on using hashes here.

Release history Release notifications | RSS feed

0.5.0

2 files

0.4.0

2 files

0.3.1

2 files

This release

0.3.0 This release

2 files

0.2.0

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page