Metadata-Version: 2.5
Name: py-drift-check
Version: 0.2.6
Summary: Upgrade-impact analyzer: check your Python code against a future dependency version before you upgrade.
Project-URL: Homepage, https://github.com/IshankGera/drift-check
Project-URL: Repository, https://github.com/IshankGera/drift-check
Project-URL: Issues, https://github.com/IshankGera/drift-check/issues
Author-email: Ishank Gera <geraishank09@gmail.com>
License: MIT
License-File: LICENSE
Keywords: api-drift,breaking-changes,ci,dependencies,static-analysis,upgrade
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.9
Requires-Dist: packaging>=24.0
Requires-Dist: rich>=13.7.0
Requires-Dist: typer>=0.12.0
Requires-Dist: uv>=0.4.0
Description-Content-Type: text/markdown

# drift-check 🔎

**Stop guessing if a dependency upgrade will break your Python code.**

Upgrading Python packages in a large or legacy codebase often feels like a gamble. Will moving a dependency to a new major version break everything? `drift-check` is an experimental CLI tool that analyzes your code against a **future** dependency version *before* you actually upgrade.

Instead of generic linting, `drift-check` spins up an isolated sandbox, extracts the new API signatures, and reports exactly which lines of your codebase will break if you apply the upgrade.

## 🚀 How It Works

1. **Baseline Verification:** Parses your `requirements.txt` and active `.venv` to confirm the installed version matches what you declared.
2. **PyPI Resolution:** Validates and normalizes your target version (e.g., resolving `15` to `15.0.0` automatically).
3. **Targeted Sandboxing:** Uses `uv` (installed automatically as a dependency) to silently spin up a temporary virtual environment containing the future target package.
4. **AST Intersection Analysis:** Reads your Python files without executing them, identifying only the API calls your code actually makes, and cross-references them against the target sandbox.
5. **CI/CD Ready:** Exits with code `1` if breaking changes are found, blocking bad dependency updates from merging.

### Exit codes

| Code | Meaning |
|---|---|
| `0` | No breaking changes (warnings may be present) |
| `1` | Breaking changes found: a used method or parameter no longer exists |
| `2` | Setup error: package not declared/installed, version not found, invalid wheel, or sandbox build failed |

## 📦 Installation

Install globally via `uv` (recommended):
```bash
uv tool install py-drift-check

```

Or via pip:

```bash
pip install py-drift-check

```

## 💻 Quickstart

Navigate to your Python project directory and run the `upgrade` command:

```bash
# Check if upgrading 'openai' to v1.52.0 will break your current code
drift-check upgrade openai --to 1.52.0

```

### Testing Internal or Unpublished Packages

If you are developing an internal SDK or a private package, you can bypass PyPI entirely and analyze your code against a local `.whl` file:

```bash
drift-check upgrade mock-sdk --to 2.0.0 --local-wheel ./dist/mock_sdk-2.0.0-py3-none-any.whl

```

## 📊 Example Output

`drift-check` intentionally ignores new features in the target version to filter out noise, strictly reporting **actionable breaking changes**:

```text
Starting Upgrade Analysis for openai -> 1.52.0...
Verifying environment baseline...
✓ Baseline established: openai == 1.45.0

Resolving target version '1.52.0' on PyPI...
✓ Target resolved: 1.52.0

Building isolated sandbox for openai==1.52.0...
Scanning codebase for API calls...

Drift Check Results:
┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Status     ┃ Location      ┃ Package  ┃ Message                                                 ┃
┡━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ ❌ ERROR   │ service.py:42 │ openai   │ Parameter 'max_tokens' is no longer supported.          │
│ ❌ ERROR   │ test_api.py:8 │ openai   │ Method 'old_method' no longer exists in target version. │
│ ⚠ WARN     │ router.py:12  │ openai   │ Target API uses dynamic **kwargs. (Confidence: LOW)     │
└────────────┴───────────────┴──────────┴─────────────────────────────────────────────────────────┘

Build Failed: Incompatible API calls detected in target version.

```

## ⚠️ Features & Current Limitations

This tool is in active development.

**Supported Features:**

* Strict environment baseline enforcement.
* PyPI fallback resolution prompts.
* Unpacking modern `TypedDict` and `Unpack` type-hints for strict kwargs evaluation.
* Seamless `uv` sandbox management.
* Local `.whl` file bypass support (the wheel's name and version are validated against `--to`).
* Client-object SDKs (e.g. `client = OpenAI(); client.chat.completions.create(...)`) are resolved by following property and attribute type hints. When a hop has no type hint, the call is reported as a low-confidence warning instead of an error.

**Known Limitations:**

* **Dependency Files:** Currently only supports reading baselines from `requirements.txt` (support for `pyproject.toml` and `uv.lock` is planned).
* **Variable Inference:** Instances are traced within a single file only (`client = Client()` → `client.create()`). Objects passed between files or returned from functions are not traced yet.
* **Dynamic Kwargs:** Cannot statically verify dynamic arguments passed at the call site (e.g., `client.create(**my_dict)`).
* **Positional Arguments:** Only keyword arguments are checked today.
* **Import names:** The package name must match its import name (e.g. `openai`, `stripe`). Packages like `pyyaml` → `yaml` are not mapped yet.

## License

MIT

