Metadata-Version: 2.4
Name: venvdrop
Version: 0.2.0
Summary: Bundle Python projects and all pip dependencies into a portable archive for offline, air-gapped deployment.
Author: Sasidhar Akurathi
License: MIT
Project-URL: Homepage, https://github.com/sasidharakurathi/venvdrop
Project-URL: Bug Tracker, https://github.com/sasidharakurathi/venvdrop/issues
Project-URL: Changelog, https://github.com/sasidharakurathi/venvdrop/blob/main/CHANGELOG.md
Keywords: venv,virtual environment,offline,air-gapped,deployment,bundle,wheelhouse,packaging,pip,dependencies,portable,isolated
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
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: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: System :: Software Distribution
Classifier: Topic :: System :: Archiving :: Packaging
Classifier: Topic :: Utilities
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: twine>=5.0; extra == "dev"
Dynamic: license-file

# VenvDrop

**Deploy massive Python environments — `torch`, `llama_cpp`, anything — to completely offline, air-gapped machines. Then wirelessly beam the archive to any machine on the same network, AirDrop-style.**

[![PyPI](https://img.shields.io/pypi/v/venvdrop)](https://pypi.org/project/venvdrop/)
[![Python](https://img.shields.io/pypi/pyversions/venvdrop)](https://pypi.org/project/venvdrop/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Zero Dependencies](https://img.shields.io/badge/dependencies-zero-brightgreen)](pyproject.toml)

VenvDrop uses the **Offline Wheelhouse** method: download all your pip dependencies as pre-built binary wheels on an internet-connected machine, bundle them with your source code into a single portable `.zip`, transfer it to the target, and deploy in one command — entirely offline.

---

## Installation

```bash
pip install venvdrop
```

```bash
venvdrop --version      # venvdrop 0.2.0
venvdrop --commands     # full command cheat sheet
venvdrop --help         # overview
```

---

## Quick Start

### 1 — Pack (internet machine)

```bash
# Standard: download wheels fresh from PyPI
venvdrop pack -r requirements.txt -s . -o my_app.zip

# Faster: reuse your existing venv — no re-download needed
venvdrop pack -r requirements.txt -s . -o my_app.zip --from-venv .venv
```

### 2 — Transfer to the offline machine

**Option A — AirDrop-like wireless (same Wi-Fi / LAN):**
```bash
# Machine A (has the zip):
venvdrop send -a my_app.zip

# Machine B (offline target) — at the same time:
venvdrop receive -d ./
```

**Option B — Manually** copy `my_app.zip` via USB, SCP, or shared drive.

### 3 — Deploy (offline machine)

```bash
venvdrop unpack -a my_app.zip -d ./deployed_app
```

### 4 — Activate and run

```bash
# Windows
.\deployed_app\venv\Scripts\activate

# Linux / macOS
source ./deployed_app/venv/bin/activate
```

---

## Commands

### `venvdrop pack` — Create a portable archive

Downloads all pip dependencies as pre-built binary wheels, scans source for portability issues, embeds platform metadata, generates a SHA-256 integrity manifest, and zips everything into one self-contained archive.

| Flag | Short | Default | Description |
|------|-------|---------|-------------|
| `--requirements` | `-r` | `requirements.txt` | pip requirements file |
| `--source` | `-s` | `.` | Project source root |
| `--output` | `-o` | `app_bundle.zip` | Output archive name |
| `--from-venv` | | *(none)* | Reuse an existing venv's pip wheel cache instead of downloading |

**Auto-excluded from source:** `venv/`, `.venv/`, `.git/`, `__pycache__/`, `node_modules/`, `dist/`, `build/`, `*.pyc`, `*.pyd`, `*.so`, `*.dll`

**What happens:**
1. AST-scans every `.py` file for hardcoded absolute paths — warns before bundling
2. Downloads (or reuses) all pip dependency wheels into `bundle_cache/`
3. Warns if any `.tar.gz` source distributions are found (they need a compiler on target)
4. Embeds platform metadata → `bundle_meta.json` (Python version, OS, CPU arch)
5. Generates SHA-256 checksums for every file → `manifest.json`
6. Zips `bundle_cache/` + `source/` + `requirements.txt` + metadata into the output

```bash
# Examples
venvdrop pack -r requirements.txt -s . -o my_app.zip
venvdrop pack -r requirements.txt -s ./src -o releases/v1.2.zip --from-venv .venv
```

---

### `venvdrop unpack` — Deploy on the offline machine

Validates platform compatibility, verifies bundle integrity, creates a fresh virtual environment, and installs everything offline.

| Flag | Short | Default | Description |
|------|-------|---------|-------------|
| `--archive` | `-a` | *(required)* | Path to the `.zip` from `venvdrop pack` |
| `--dest` | `-d` | `./deployed_app` | Destination directory |

**What happens:**
1. Reads `bundle_meta.json` — validates OS, CPU arch, Python version
2. Auto-discovers compatible Python interpreter if version mismatches (prompts if not found)
3. Windows MAX_PATH guard: warns if destination path > 200 chars
4. Venv collision handling — interactive: **Overwrite / Backup / Abort**
5. Extracts archive and verifies SHA-256 of every file
6. Creates a fresh `venv/` with the correct Python interpreter
7. Upgrades pip inside the new venv (prevents PEP 517 issues)
8. Installs all packages offline: `pip install --no-index --find-links bundle_cache/`
9. Prints post-install checklist for system-level deps (CUDA, VC++ Redist, etc.)

```bash
# Examples
venvdrop unpack -a my_app.zip
venvdrop unpack -a my_app.zip -d C:\app       # Windows short path
venvdrop unpack -a my_app.zip -d /opt/myapp   # Linux/macOS
```

---

### `venvdrop send` — Wirelessly send an archive (AirDrop-like)

Announces the archive on the local network via UDP multicast so any `venvdrop receive` instance on the same Wi-Fi or LAN can discover and download it automatically.

| Flag | Short | Default | Description |
|------|-------|---------|-------------|
| `--archive` | `-a` | *(required)* | Archive to send |

**What happens:**
1. Computes SHA-256 of the archive
2. Generates a random **4-digit PIN** (shown prominently on screen)
3. Starts an HTTP file server on a local port (8900–8999)
4. Broadcasts a UDP multicast beacon every second — receivers discover it automatically
5. Streams the file with a live progress bar when a receiver connects
6. Shuts down cleanly after transfer or on Ctrl+C

```bash
venvdrop send -a my_app.zip
# Note the PIN displayed and tell it to the receiver
```

---

### `venvdrop receive` — Wirelessly receive an archive

Listens for `venvdrop send` beacons on the LAN, shows discovered senders, and downloads with a live progress bar.

| Flag | Short | Default | Description |
|------|-------|---------|-------------|
| `--dest` | `-d` | `./received` | Where to save the file |
| `--timeout` | | `30` | Seconds to scan for senders |

**What happens:**
1. Listens on UDP multicast for sender beacons
2. Displays each discovered sender (filename, size, IP address)
3. Prompts for the 4-digit PIN shown on the sender's terminal
4. Downloads via HTTP with a live ANSI progress bar
5. Verifies SHA-256 integrity after download — fails loudly if tampered

```bash
venvdrop receive                    # scan 30s, save to ./received
venvdrop receive -d C:\transfers    # custom destination
venvdrop receive --timeout 60       # scan longer
```

---

### Global Flags

| Flag | Short | Description |
|------|-------|-------------|
| `--help` | `-h` | Show help for any command |
| `--version` | `-V` | Print installed version (`venvdrop 0.2.0`) |
| `--commands` | `-c` | **Full color-coded cheat sheet** of all commands + examples |

```bash
venvdrop --commands    # prints the full reference sheet
venvdrop pack --help   # detailed help for a specific subcommand
```

---

## What Problems Does VenvDrop Solve?

| Problem | How VenvDrop Handles It |
|---------|------------------------|
| No internet on target machine | Downloads wheels upfront; installs with `--no-index` |
| Re-downloading wheels is slow | `--from-venv` reuses pip's local wheel cache — no download |
| Source distribution / compile trap | Detects `.tar.gz` sdists and warns: use `--only-binary=:all:` |
| Hardcoded absolute paths | AST-scans every `.py` file and warns before bundling |
| Python version mismatch | Auto-discovers the right interpreter; prompts if not found |
| OS / arch mismatch | Blocks deployment if wheels won't run (e.g. x86_64 → ARM) |
| Windows MAX_PATH (260 chars) | Warns if destination path > 200 characters |
| Windows command-line too long | Wheels staged into one flat dir; single `--find-links` arg |
| No USB / cable to transfer | `venvdrop send` + `venvdrop receive` over LAN — no cable needed |
| Transfer corruption | SHA-256 manifest verified on unpack; SHA-256 re-checked on receive |
| Existing venv collision | Interactive: Overwrite / Backup / Abort |
| Outdated pip in new venv | Bootstraps `pip install --upgrade pip` before offline install |
| Missing system drivers | Post-install checklist: CUDA, VC++ Redist, OpenSSL, ODBC |

---

## Why Not Just Copy the `venv` Folder?

Copying a `venv` directory breaks because:
- Absolute paths baked into scripts and `.pth` files point to the source machine
- Native extensions (`.pyd`, `.so`) are compiled for a specific OS + arch
- The Python interpreter path inside the venv is hardcoded

VenvDrop creates a **fresh** venv on the target machine and populates it from pre-built wheels, so all paths are correct from the start.

---

## Troubleshooting

| Issue | Fix |
|-------|-----|
| sdist warning during pack | Re-run pip download with `--only-binary=:all:` |
| Python version mismatch | Install required Python on target; VenvDrop will prompt for path |
| OS / arch mismatch on unpack | Pack on a machine that matches the target OS and CPU |
| Windows MAX_PATH error | Choose a shorter `--dest`, e.g. `C:\app` |
| `bundle_meta.json` missing | Archive wasn't created by VenvDrop; re-pack |
| Integrity check failures | Archive was corrupted in transit; re-transfer or re-send |
| `--from-venv` can't find Python | Pass the venv ROOT (folder containing `Scripts/` or `bin/`) |
| `venvdrop receive` finds no senders | Ensure both machines are on the **same** Wi-Fi/LAN; check firewall |
| Wrong PIN on receive | Sender rejects the connection — check the PIN on sender terminal |

---

## Requirements

- Python ≥ 3.8
- **Zero runtime dependencies** — pure Python stdlib only

---

## Development

```bash
git clone https://github.com/sasidharakurathi/venvdrop.git
cd venvdrop
pip install -e .          # editable install — changes to .py files apply immediately
venvdrop --version
venvdrop --commands
```

See [CONTRIBUTING.md](CONTRIBUTING.md) for full dev guide and PyPI release steps.

---

## License

MIT — see [LICENSE](LICENSE). Copyright © 2025 Sasidhar Akurathi.
