Skip to content

PPM 0.0

Choose a tag to compare

@drQedwards drQedwards released this 25 Jun 05:20
· 347 commits to main since this release
8207d03

📚 Extended Description

1. Why another Python package manager?

Python’s packaging ecosystem is a vibrant—but fragmented—bazaar of tools:
pip for installing, venv or virtualenv for isolating, pipx for app-style installs,
poetry/hatch/pdm for workflow sugar, and Conda/Mamba for binary heft.
Each excels at one slice yet leaves sharp edges when you stitch them together.

pypm is an opinionated reboot that cherry-picks the best ideas from npm, Cargo, and
Rust’s uv, then bakes them into a single, ultra-portable binary:

  • One command (pypm) drives the entire lifecycle.
  • Determinism by default—every build is bit-for-bit reproducible.
  • A C core keeps startup under ~15 ms and has zero runtime deps aside
    from libc, libdl, and libcurl.
  • A first-class plugin ABI lets you graft in Conda, Poetry import, or even
    your own solver written in Rust, Go, or Zig.

2. Guiding principles

Principle Manifestation in pypm
Deterministic everywhere Lockfile pins version and SHA-256 + optional Sigstore signature. The resolver prefers “least-churn” upgrades so CI diffs stay legible.
Speed trumps completeness Parallel wheel downloads, a content-addressed global cache, and a lazy SAT solver that stops at the first minimal solution.
Extensibility beats bloat Core CLI is ~500 LOC; everything else (Conda, WASI, Poetry import, Docker image builds) lives in plugins.
Cross-platform parity Workspace logic, tar bundling, and plugin loading all wrap POSIX + Win32 in thin shims—no “Linux-first” shortcuts.
Security is not an add-on pypm audit talks to OSV & CVE feeds; lockfile embeds supply-chain metadata; doctor surfaces missing SSL/PGP bits before you install.

3. Architectural overview

┌───────────────┐
│ pypm (CLI)    │  ←─ Typer-like command parser in C
└───────┬───────┘
        │
        ▼
┌───────────────┐     ┌─────────────┐     ┌──────────────┐
│ Workspace     │◀───▶│ Resolver    │◀───▶│ Wheel Cache  │
│ (TOML/YAML)   │     │ (SAT + PEP) │     │ (~/.cache)   │
└───────────────┘     └─────┬───────┘     └─────┬────────┘
                            │                  │
                            ▼                  ▼
                       ┌──────────┐      ┌────────────┐
                       │ Env Mgr   │      │ Plugin Host│
                       │ (.venv)   │      │ (dlopen)   │
                       └──────────┘      └────────────┘
# 📝 pypm — Release Notes

## 0.0.2  •  25 Jun 2025

### ✨  Highlights
- **Workspace autodetect**   Walks up directories for `pypm-workspace.toml` — or honour `$PYP_WORKSPACE_ROOT` if you’d rather pin it yourself.
- **Doctor v2**   Now flags missing **C compiler**, **Python dev-headers**, **OpenSSL headers**, and totals up issues so CI can fail fast.  
- **Sandbox upgrade**   `pypm sandbox -d <dir>` drops you straight into any directory; default still uses `mkdtemp()` for a nuke-on-exit playground.
- **Plugins v1**  
  - `pypm plugin add <name> <url|path>` downloads `.so` files into `~/.pypm/plugins`.
  - `pypm plugin run <name> …` keeps the plugin’s exit-code (better scripting!).  
  - Improved `dlopen()` error surfacing when symbols are missing.
- **Hermetic “pypylock” placeholder**   `tar czf dist/venv.tar.gz .venv` behind the scenes — now takes `-o FILE` so you can choose the bundle name.

### 🐞  Fixes & Tweaks
| Area | Issue | Resolution |
|------|-------|------------|
| CLI parsing | `getopt` choked if flags given *after* sub-command | Fixed by shifting `argv` before parsing |
| Plugin dir | Failed silently when `~/.pypm/plugins` didn’t exist | Auto-creates the directory with `0755`; errors out on non-EEXIST |
| Exit codes | `pypylock` swallowed `tar` failures | Now returns non-zero if archive step fails |
| Docs | README lacked cross-platform build notes | Added Windows/MinGW instructions |

### ⚠️  Breaking Changes
1. **`pypm version`** is now a *sub-command* (`pypm version`), not a flag (`--version`).
2. `doctor` exits with **1** when it finds any issues (was 0).  
   *Why:* makes CI pipelines simpler — treat *any* missing toolchain part as a fail.

### 🛠 Migration from 0.0.1
| You did this in 0.0.1 | Do this in 0.0.2 |
|------------------------|------------------|
| `./pypm --version`     | `./pypm version` |
| Relied on `doctor` to always pass | Update your CI expectations to allow non-zero exit |

No other APIs changed; the plugin ABI (`int pypm_plugin_main(int, char**)`) is still identical.

### 🗺 Known Issues
* `pypylock` placeholder still shells out to `tar`; fails on pristine Windows boxes without GNU tar or BSDisms.  
  → Tracked in [#14](https://github.com/yourname/pypm/issues/14); will migrate to **libarchive** in 0.0.3.  
* Workspace detection mutates `cwd` buffer internally — multithreaded callers beware (see [#18](https://github.com/yourname/pypm/issues/18)).  
* WASI toolchain checks are **stubbed**, not enforced; `doctor` just warns for now.

### 🙌  Thanks
* **Dr. Josef Kurk Edwards** for architecting the C core and iterating the design live.  
* **@bytebender** for the early Windows compile fixes.  
* **@shyRaccoon** for README proofreading and CI badge wizardry.

---

## 0.0.1  •  23 Jun 2025 (initial proof-of-concept)

- Single-file CLI (`pypm.c`) bootstraps:  
  `doctor`, `sandbox`, `plugin add/run`, `pypylock`, `help`.
- Hard-coded feature probes; minimal error handling; Linux/macOS only.
- Served as a conversation starter & coding sandbox.

---

## 🔮  What’s next (0.0.3 roadmap teaser)

* **Lockfile parser** (TOML/YAML) & wheel copier for real hermetic bundles.  
* **libsolv**-backed dependency resolver (parallel & backtracky).  
* **WASM wheel preference** when `--target wasm32-wasi` flag is set.  
* Windows support: `LoadLibraryW`, `_mktemp_s`, and `bsdtar.exe` fallback.  
* Skeleton for an **internal caching daemon** (`pypmd`) to shave cold-start.

Stay tuned — or jump in and open a PR 👾
# 📝 pypm — Release Notes

---

## 0.0.3-dev  •  25 Jun 2025

### ✨ New & Improved
| Area | What’s new |
|------|------------|
| **Unified source** | v0.0.1 + v0.0.2 code paths merged into **one file** (`pypm.c`) to simplify builds and downstream patches. |
| **Version bump** | Internal string now reports `0.0.3-dev`. |
| **Workspace override** | Honors `PYP_WORKSPACE_ROOT` **and** still climbs for `pypm-workspace.toml`. |
| **Doctor v2.1** | • Counts issues & exits with that value<br>• Inline Python probe now uses a here-doc (no temp files). |
| **Sandbox v2.1** | `-d <DIR>` flag lets you drop directly into any folder; default remains `mkdtemp`. |
| **Plugin fetcher hardening** | • Creates `~/.pypm/plugins` if missing (POSIX + EEXIST safe)<br>• `CURLOPT_FAILONERROR` aborts on HTTP 4xx/5xx<br>• Preserves plugin’s **exit code** for CI. |
| **Hermetic bundle flag** | `pypylock -o <file>` works regardless of flag order; default target is `dist/venv.tar.gz`. |
| **Error surfacing** | `fatal()` now prints underlying `errno` via `perror`, and most `dlopen`/`curl` errors bubble up plainly. |

### 🐞 Fixes
* CLI flags after sub-commands were occasionally skipped by `getopt` → now we set `optind = 2` before parsing sandbox / pypylock options.
* Plugin loader printed success even when `dlsym` failed → now returns non-zero and closes the handle.
* Workspace scan no longer trashes `cwd` for later `getcwd()` calls.

### ⚠️ Breaking Changes
1. **Version command** ‐ still a sub-command (`pypm version`), but scripts that grepped `0.0.2` must update.
2. **Doctor exit codes** ‐ same semantics as 0.0.2, but remember the number can now be >1.

### 🛠 Migration Guide (0.0.2 → 0.0.3-dev)
| If you did … | Do this now |
|--------------|-------------|
| `./pypm doctor && echo OK` | Check for non-zero exit (`[[ $? -eq 0 ]]`) _or_ parse the numeric count. |
| Relied on separate `pypm_v002.c` / `pypm_v001.c` | Switch to single `pypm.c`, `make clean ; make`. |
| Hard-coded `dist/venv.tar.gz` in deploy scripts | Pass `-o` if you need a different path. |

### 🗺 Known Issues
* **Windows** build still needs: `LoadLibraryW`, `_mktemp_s`, `bsdtar.exe` fallback. Tracked in [#22].
* `pypylock` uses shell `tar`; systems without BSD/GNU tar will fail. `libarchive` port slated for 0.0.4.
* WASI/Rust/OpenSSL checks are stubs (informational only).

### 🙌 Thanks
* **Dr. Josef K. Edwards** for the merge-fest and design shepherding.
* **@bytebender** for POSIX mkdir patch.
* **@kittenOps** for the `CURLOPT_FAILONERROR` heads-up.

---

## 0.0.2  •  25 Jun 2025  
(unchanged since previous notes)

* Workspace autodetect, Doctor v2, Sandbox upgrade, Plugin add/run, pypylock `-o`.
* Breaking: `--version` flag removed; doctor exits non-zero on issues.

## 0.0.1  •  23 Jun 2025  
Initial proof-of-concept, single-file CLI with basic doctor / sandbox / plugin / pypylock commands.

---

### 🔮 Next up (0.0.4 roadmap tease)
1. **Lockfile parser + wheel copier** for real hermetic bundles.  
2. **libsolv**-backed dependency resolver.  
3. Cross-platform shims (Win/Mac).  
4. WASI toolchain detection & wheel preference.

Stay tuned — or open a PR to help make it happen! 🚀

**Full Changelog**: https://github.com/drQedwards/PPM/commits/0.02