Metadata-Version: 2.4
Name: compatforge
Version: 0.2.0
Summary: Smart Python dependency auditor, conflict resolver, and environment pruner
Home-page: https://github.com/sanjay8523/compatforge
Author: Sanjay
Author-email: you@example.com
Keywords: dependency,package manager,audit,virtualenv,pip,requirements
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Systems Administration
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: packaging>=23.0
Requires-Dist: requests>=2.28.0
Requires-Dist: click>=8.0.0
Requires-Dist: rich>=13.0.0
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# 🛠️ compatforge

**Smart Python dependency auditor, conflict resolver, and environment pruner.**

> *Tired of `pip` dependency hell? `compatforge` reads your actual Python code — not just what you told pip to install — and automatically fixes your environment.*

[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
[![PyPI](https://img.shields.io/pypi/v/compatforge)](https://pypi.org/project/compatforge/)

---

## The Problem

Standard `pip` is dumb. It installs what you tell it to, but it has no idea what your code actually *needs*. The result:

- **Broken environments**: Two packages require different versions of `numpy`, your app crashes with a cryptic C++ exception.
- **Bloated venvs**: You installed `torch` to experiment 3 months ago, forgot about it, now it's conflicting with everything.
- **Bad lockfiles**: `pip freeze` dumps 150 packages including dev tools, CI runners, and junk your code never touches.

## The Solution

`compatforge` **reads your `.py` files** (safely, without executing them), maps every `import` statement to a PyPI package, builds the full transitive dependency graph, and calculates the mathematically perfect set of compatible versions.

---

## Installation

```bash
pip install compatforge
```

Or from source:

```bash
git clone https://github.com/sanjay8523/compatforge.git
cd compatforge
pip install -e .
```

---

## Commands

### `compatforge doctor`
Full health check — checks Python version, virtual environment, pip version, then runs a full audit.

```
$ compatforge doctor

Python version:      3.11.9
Virtual environment: Active
pip version:         24.0

╭──────────────────────────────────────────────╮
│ System Health: EXCELLENT                     │
╰──────────────────────────────────────────────╯

─── Initiating project audit ───

Step 1  Scanning Python files for imports...
Step 2  Reading installed environment...
Step 3  Building dependency tree...
Step 4  Checking for version conflicts...

✓ No missing packages
✓ No obviously unused packages
✓ No version conflicts detected

Summary: 11 needed  |  0 missing  |  0 unused  |  0 conflict(s)
```

---

### `compatforge audit`
Read-only X-ray of your project. Detects missing, unused, and conflicting packages without changing anything.

```bash
compatforge audit
compatforge audit --report    # also writes requirements.txt, compatforge.lock, compat-report.md
compatforge audit --json      # output as JSON
```

Example output on a messy ML environment:

```
╭─────────── Missing packages ──────────────╮
│  ✗ mediapipe                              │
╰───────────────────────────────────────────╯

Possibly unused packages
  torch              2.11.0   not imported + not a transitive dep
  ultralytics        8.4.42   not imported + not a transitive dep
  polars             1.40.1   not imported + not a transitive dep

Version conflicts
  opencv-contrib-python   numpy>=2           numpy==1.26.4
  tensorflow              numpy<=1.24.3      numpy==1.26.4

Summary: 12 needed  |  1 missing  |  26 unused  |  4 conflict(s)
```

---

### `compatforge freeze` ✨ New
Creates a **clean, minimal lockfile** of your project's real dependencies.

Unlike `pip freeze` (which dumps everything), this only locks what your code actually uses.

```bash
compatforge freeze                     # writes project.forge
compatforge freeze --format pip        # writes requirements-frozen.txt
compatforge freeze --format conda      # writes environment.yml
compatforge freeze --dry-run           # preview without writing
```

The `.forge` file format:

```ini
# compatforge freeze file
# Generated by compatforge on 2026-04-30

[metadata]
generated_at = 2026-04-30 10:00 UTC
project = my-ml-project

[direct]
# These packages are imported directly by your Python files.
tensorflow==2.15.0
opencv-python==4.9.0.80
pandas==2.1.0
streamlit==1.28.0

[transitive]
# Sub-dependencies. Do not edit manually.
numpy==1.24.3
protobuf==3.20.3
grpcio==1.58.0
# ... (auto-managed)
```

To restore this environment on any machine:

```bash
compatforge sync --from my-project.forge
```

---

### `compatforge sync`
Installs and fixes packages based on what your code actually imports. Uses a **backtracking resolver** to automatically solve version conflicts.

```bash
compatforge sync
compatforge sync --dry-run            # preview changes
compatforge sync --from myenv.forge   # sync from a lockfile
```

#### Preventing the "Bleeding-Edge Trap"

By default, the resolver grabs the newest version of each package. Sometimes this breaks things (like when TensorFlow 2.16+ deleted the old Keras engine).

Create a `.compatforge-pins` file in your project root to lock specific versions:

```
# .compatforge-pins
# Lock TensorFlow to a stable version to avoid breaking Keras
tensorflow==2.15.0

# Keep NumPy below 2.0 for compatibility
numpy==1.24.3
```

The resolver will respect these pins while still finding compatible versions of everything else.

---

### `compatforge prune`
Safely removes installed packages that aren't needed by your code.

```bash
compatforge prune
compatforge prune --yes          # skip confirmation prompt
compatforge prune --dry-run      # preview without removing
```

**Shared namespace protection**: If you try to remove a package that shares an import namespace with another (like `opencv-contrib-python` and `opencv-python` both providing `cv2`), compatforge warns you before proceeding.

---

## How It Works

### 1. AST Import Scanning
Instead of guessing, compatforge uses Python's built-in `ast` module to safely parse your `.py` and `.ipynb` files and extract every `import` statement — without executing any code.

```python
# Your code
import tensorflow
import cv2
from sklearn.ensemble import RandomForestClassifier
```

Detected: `tensorflow`, `opencv-python`, `scikit-learn`

### 2. Smart Normalization
The import name often doesn't match the PyPI package name:

| Import name | PyPI package |
|---|---|
| `cv2` | `opencv-python` |
| `PIL` | `Pillow` |
| `sklearn` | `scikit-learn` |
| `bs4` | `beautifulsoup4` |
| `yaml` | `PyYAML` |

compatforge has a built-in mapping for 50+ known mismatches, and uses Python 3.10+'s `sys.stdlib_module_names` for exhaustive standard library detection.

### 3. Transitive Dependency Graph
When your code imports `tensorflow`, compatforge also knows it needs `numpy`, `protobuf`, `grpcio`, and 20+ other packages. It builds this tree using the installed package metadata — no network calls needed.

This is how it knows that `numpy` is NOT unused even if you never write `import numpy` — TensorFlow needs it.

### 4. Backtracking Resolver
The resolver solves the constraint satisfaction problem automatically.

Example conflict:
- `tensorflow==2.13.0` requires `protobuf<4.0.0`
- `mediapipe==0.10.8` requires `protobuf>=3.20.0`

The resolver intersects: `<4.0.0 AND >=3.20.0` → `3.20.3` ✓

If the latest version of a package causes a conflict, it backtracks to older versions until it finds a combination that satisfies all constraints.

---

## Known Limitations

### Shared Namespace Packages
Some PyPI packages install into the same Python namespace. The most common is OpenCV:

- `opencv-python` → installs `cv2/`
- `opencv-contrib-python` → also installs `cv2/`

If you uninstall one, the other's files may also be removed. `compatforge prune` warns you when this situation is detected, but always run `pip install --force-reinstall <package>` if your `cv2` import breaks after pruning.

### Bleeding-Edge Resolver
The resolver defaults to the newest compatible version of each package. For large ML frameworks (TensorFlow, PyTorch, Keras), this can grab versions that have breaking API changes. Use a `.compatforge-pins` file to prevent this.

### Dynamic Imports
Dynamically constructed import strings can't always be detected:

```python
# This IS detected:
importlib.import_module("requests")

# This CANNOT be detected:
module_name = get_config("module")
importlib.import_module(module_name)
```

---

## Contributing

Pull requests welcome. Key areas that need work:

- Expanding the `IMPORT_TO_PACKAGE` mapping in `normalizer.py`
- Adding more platform-specific stdlib modules
- Async resolver for faster resolution (currently sequential HTTP calls)
- GUI/web interface

```bash
git clone https://github.com/sanjay8523/compatforge.git
cd compatforge
python -m venv venv
venv\Scripts\activate   # Windows
pip install -e .
```

---

## License

MIT License — free and open source. See [LICENSE](LICENSE).

---

*Built to solve a real problem: dependency hell in Python ML projects.*
