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
CPY008 __slots__ may not prevent __dict__ with base classes Info All versions
CPY009 ExceptionGroup requires Python 3.11+ Error CPython ≤ 3.10
CPY010 @dataclass(slots=True) requires Python 3.10+ Error CPython ≤ 3.9

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
PPY005 File write without explicit flush may lose data Warning PyPy all versions
PPY006 Monkey-patching built-in types behaves differently Warning PyPy all versions
PPY007 sys.intern() identity guarantees differ on PyPy 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.4.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.


Roadmap

Planned for upcoming versions — contributions welcome:

  • CPY014typing.TypeAlias requires Python 3.10+
  • CPY015typing.Never requires Python 3.11+
  • PPY008array.array behaviour differences on PyPy
  • PPY009decimal module precision differences on PyPy
  • Pre-commit hook native support
  • VS Code extension
  • GitHub Action marketplace listing

See CONTRIBUTING.md to add a rule yourself — rule IDs CPY011+ and PPY008+ are open for community contributions.


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.4.0
  • Rules: 20 (13 CPython + 7 PyPy)
  • Tests: 79 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.4.0.tar.gz (26.5 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.4.0-py3-none-any.whl (32.7 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for pyrift-0.4.0.tar.gz
Algorithm Hash digest
SHA256 5baa3ecc8d130fc2ee1c80b1ff7cff9e4cedc85d3cd08008e6f92018a00d5e0a
MD5 32f162334b39a691f96e506ec48b61b2
BLAKE2b-256 b63f9e8f7ee9d77b2b8967414c89a9420ff08e7c288a49053961b4b777a7bf4a

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for pyrift-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2af493056ecb10d2cb60c679af54a07d413f8a8c28c695c01d2bee47695ef777
MD5 0b627a40b735aa3ee1f6799065a784de
BLAKE2b-256 215ce3a1809b15776f91b8962fd982fe9b9f4bfe5195806b6fc956e6e7fb1341

See more details on using hashes here.

Release history Release notifications | RSS feed

0.5.0

2 files

This release

0.4.0 This release

2 files

0.3.1

2 files

0.3.0

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