pypilot-cli 1.2.0__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. pypilot_cli-1.3.0/.gitattributes +5 -0
  2. pypilot_cli-1.3.0/.github/CODEOWNERS +9 -0
  3. pypilot_cli-1.3.0/.github/ISSUE_TEMPLATE/environment_problem.md +30 -0
  4. pypilot_cli-1.3.0/.github/workflows/ci.yml +76 -0
  5. pypilot_cli-1.3.0/.github/workflows/publish.yml +115 -0
  6. {pypilot_cli-1.2.0 → pypilot_cli-1.3.0}/.gitignore +2 -0
  7. {pypilot_cli-1.2.0 → pypilot_cli-1.3.0}/CONTRIBUTING.md +35 -23
  8. pypilot_cli-1.3.0/PKG-INFO +284 -0
  9. pypilot_cli-1.3.0/README.md +255 -0
  10. pypilot_cli-1.3.0/hatch_build.py +56 -0
  11. {pypilot_cli-1.2.0 → pypilot_cli-1.3.0}/pyproject.toml +10 -1
  12. pypilot_cli-1.3.0/scripts/build_wheels.py +139 -0
  13. pypilot_cli-1.3.0/scripts/sbom.py +75 -0
  14. pypilot_cli-1.3.0/src/pypilot/__init__.py +34 -0
  15. pypilot_cli-1.3.0/src/pypilot/api.py +151 -0
  16. pypilot_cli-1.3.0/src/pypilot/binary.py +90 -0
  17. pypilot_cli-1.3.0/src/pypilot/cli.py +117 -0
  18. pypilot_cli-1.3.0/src/pypilot/engine.py +548 -0
  19. pypilot_cli-1.3.0/tests/conftest.py +165 -0
  20. pypilot_cli-1.3.0/tests/test_api.py +110 -0
  21. pypilot_cli-1.3.0/tests/test_cli.py +212 -0
  22. pypilot_cli-1.3.0/tests/test_engine.py +288 -0
  23. {pypilot_cli-1.2.0 → pypilot_cli-1.3.0}/uv.lock +10 -10
  24. pypilot_cli-1.2.0/.github/workflows/ci.yml +0 -33
  25. pypilot_cli-1.2.0/.github/workflows/publish.yml +0 -39
  26. pypilot_cli-1.2.0/PKG-INFO +0 -179
  27. pypilot_cli-1.2.0/README.md +0 -151
  28. pypilot_cli-1.2.0/src/pypilot/__init__.py +0 -32
  29. pypilot_cli-1.2.0/src/pypilot/binary.py +0 -211
  30. pypilot_cli-1.2.0/src/pypilot/cli.py +0 -27
  31. pypilot_cli-1.2.0/tests/test_cli.py +0 -112
  32. {pypilot_cli-1.2.0 → pypilot_cli-1.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  33. {pypilot_cli-1.2.0 → pypilot_cli-1.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  34. {pypilot_cli-1.2.0 → pypilot_cli-1.3.0}/.python-version +0 -0
  35. {pypilot_cli-1.2.0 → pypilot_cli-1.3.0}/CODE_OF_CONDUCT.md +0 -0
  36. {pypilot_cli-1.2.0 → pypilot_cli-1.3.0}/LICENSE +0 -0
  37. {pypilot_cli-1.2.0 → pypilot_cli-1.3.0}/src/pypilot/py.typed +0 -0
@@ -0,0 +1,5 @@
1
+ # GitHub Linguist: documentation is left out of the repository's language
2
+ # statistics. This only changes GitHub's language breakdown; the files stay
3
+ # tracked and unchanged.
4
+ docs/** linguist-documentation
5
+ *.md linguist-documentation
@@ -0,0 +1,9 @@
1
+ # Every change is reviewed by the maintainer.
2
+ * @Abdullah-Masood-05
3
+
4
+ # The engine pin (DEFAULT_TAG / ENGINE_SHA256) decides which native binary
5
+ # every install downloads or bundles.
6
+ /src/pypilot/binary.py @Abdullah-Masood-05
7
+ /hatch_build.py @Abdullah-Masood-05
8
+ /scripts/ @Abdullah-Masood-05
9
+ /.github/workflows/ @Abdullah-Masood-05
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: Environment problem
3
+ about: PyPilot ran, but got your Python environment, packages or GPU setup wrong
4
+ title: ""
5
+ labels: environment
6
+ assignees: ""
7
+ ---
8
+
9
+ **What happened**
10
+ What PyPilot reported or did, and what you expected instead.
11
+
12
+ **`pypilot --version`**
13
+ Both lines, please: the engine (`pypilot X.Y.Z`) and the wrapper (`pypilot-cli X.Y.Z (engine: ...)`), plus any `warning:` lines.
14
+
15
+ ```
16
+ paste here
17
+ ```
18
+
19
+ **`pypilot doctor --json`**
20
+ Run it in the project folder. It lists your interpreter, virtual environment, manifests and GPU/CUDA facts; remove anything you consider private before posting.
21
+
22
+ ```json
23
+ paste here
24
+ ```
25
+
26
+ **Install method**
27
+ pip / pipx / `uv tool` / platform wheel or pure wheel (`pip show -f pypilot-cli` lists `pypilot/_engine/` if the engine is bundled).
28
+
29
+ **Anything else**
30
+ Proxy or offline setup (`PYPILOT_OFFLINE`, `HTTPS_PROXY`), `PYPILOT_ENGINE_VERSION`, or a `pypilot` engine on PATH or in `~/.cargo/bin`.
@@ -0,0 +1,76 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ test:
13
+ name: py${{ matrix.python }} (${{ matrix.os }})
14
+ runs-on: ${{ matrix.os }}
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ os: [ubuntu-latest]
19
+ python: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14", "3.15"]
20
+ include:
21
+ # The oldest and newest supported Pythons on the other platforms the
22
+ # engine ships for, since archive handling differs between them.
23
+ - { os: windows-latest, python: "3.8" }
24
+ - { os: windows-latest, python: "3.15" }
25
+ - { os: macos-latest, python: "3.8" }
26
+ - { os: macos-latest, python: "3.15" }
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+
30
+ - name: Install uv
31
+ uses: astral-sh/setup-uv@v5
32
+
33
+ # Warnings are errors so a deprecation that a new Python release turns
34
+ # into a behaviour change (as 3.14 did for tarfile) fails here first.
35
+ - name: Test
36
+ run: uv run --python ${{ matrix.python }} python -m pytest -W error
37
+
38
+ wheels:
39
+ name: Build all wheels
40
+ runs-on: ubuntu-latest
41
+ steps:
42
+ - uses: actions/checkout@v4
43
+
44
+ - name: Install uv
45
+ uses: astral-sh/setup-uv@v5
46
+
47
+ - name: Build the sdist, the pure wheel and the platform wheels
48
+ run: uv run --python 3.12 python scripts/build_wheels.py
49
+
50
+ - name: Check the metadata
51
+ run: uv run --python 3.12 twine check --strict dist/*
52
+
53
+ # The bundled engine must run with no network at all.
54
+ - name: Run the manylinux wheel offline
55
+ run: |
56
+ uv venv --python 3.12 "$RUNNER_TEMP/smoke"
57
+ uv pip install --python "$RUNNER_TEMP/smoke/bin/python" dist/*-manylinux_*.whl
58
+ HOME="$(mktemp -d)" XDG_CACHE_HOME="$(mktemp -d)" PYPILOT_OFFLINE=1 HTTPS_PROXY=http://127.0.0.1:9 \
59
+ "$RUNNER_TEMP/smoke/bin/pypilot" --version 2>&1 | tee version.txt
60
+ grep -q "engine: bundled" version.txt
61
+
62
+ audit:
63
+ name: Audit locked dependencies
64
+ runs-on: ubuntu-latest
65
+ steps:
66
+ - uses: actions/checkout@v4
67
+
68
+ - name: Install uv
69
+ uses: astral-sh/setup-uv@v5
70
+
71
+ # The package itself has no runtime dependencies; this covers the build
72
+ # and test tools in uv.lock.
73
+ - name: pip-audit
74
+ run: |
75
+ uv export --frozen --format requirements-txt --no-emit-project -o "$RUNNER_TEMP/requirements.txt"
76
+ uvx pip-audit --strict --disable-pip --require-hashes -r "$RUNNER_TEMP/requirements.txt"
@@ -0,0 +1,115 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ test:
14
+ name: Test
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Install uv
20
+ uses: astral-sh/setup-uv@v5
21
+
22
+ - name: Test
23
+ run: uv run --python 3.12 python -m pytest -W error
24
+
25
+ build:
26
+ name: Build sdist and wheels
27
+ needs: test
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - uses: actions/checkout@v4
31
+
32
+ - name: Install uv
33
+ uses: astral-sh/setup-uv@v5
34
+
35
+ - name: Audit locked dependencies
36
+ run: |
37
+ uv export --frozen --format requirements-txt --no-emit-project -o "$RUNNER_TEMP/requirements.txt"
38
+ uvx pip-audit --strict --disable-pip --require-hashes -r "$RUNNER_TEMP/requirements.txt"
39
+
40
+ # One Linux job builds every wheel: it only packs the pinned engine
41
+ # binaries (each checked against ENGINE_SHA256), and Linux keeps the
42
+ # executable bit the Linux and macOS wheels need.
43
+ - name: Build the sdist, the pure wheel and the platform wheels
44
+ run: uv run --python 3.12 python scripts/build_wheels.py
45
+
46
+ - name: Check the metadata
47
+ run: uv run --python 3.12 twine check --strict dist/*
48
+
49
+ - name: Run the manylinux wheel offline
50
+ run: |
51
+ uv venv --python 3.12 "$RUNNER_TEMP/smoke"
52
+ uv pip install --python "$RUNNER_TEMP/smoke/bin/python" dist/*-manylinux_*.whl
53
+ HOME="$(mktemp -d)" XDG_CACHE_HOME="$(mktemp -d)" PYPILOT_OFFLINE=1 HTTPS_PROXY=http://127.0.0.1:9 \
54
+ "$RUNNER_TEMP/smoke/bin/pypilot" --version 2>&1 | tee version.txt
55
+ grep -q "engine: bundled" version.txt
56
+
57
+ - name: Write the CycloneDX SBOM
58
+ run: |
59
+ mkdir sbom
60
+ uv export --frozen --no-dev --format cyclonedx1.5 --preview-features sbom-export -o "$RUNNER_TEMP/uv-sbom.json"
61
+ uv run --python 3.12 python scripts/sbom.py "$RUNNER_TEMP/uv-sbom.json" sbom/pypilot-cli.cdx.json
62
+
63
+ - uses: actions/upload-artifact@v4
64
+ with:
65
+ name: dist
66
+ path: dist/
67
+ if-no-files-found: error
68
+
69
+ - uses: actions/upload-artifact@v4
70
+ with:
71
+ name: sbom
72
+ path: sbom/
73
+ if-no-files-found: error
74
+
75
+ publish:
76
+ name: Publish to PyPI
77
+ needs: build
78
+ runs-on: ubuntu-latest
79
+ environment:
80
+ name: pypi
81
+ url: https://pypi.org/p/pypilot-cli
82
+ permissions:
83
+ id-token: write
84
+ steps:
85
+ - uses: actions/download-artifact@v4
86
+ with:
87
+ name: dist
88
+ path: dist/
89
+
90
+ - name: Publish to PyPI
91
+ uses: pypa/gh-action-pypi-publish@release/v1
92
+
93
+ github-release:
94
+ name: Attach wheels and SBOM to the GitHub release
95
+ needs: publish
96
+ if: startsWith(github.ref, 'refs/tags/v')
97
+ runs-on: ubuntu-latest
98
+ permissions:
99
+ contents: write
100
+ steps:
101
+ - uses: actions/download-artifact@v4
102
+ with:
103
+ path: artifacts/
104
+ merge-multiple: true
105
+
106
+ - name: Create or update the release
107
+ env:
108
+ GH_TOKEN: ${{ github.token }}
109
+ TAG: ${{ github.ref_name }}
110
+ run: |
111
+ if gh release view "$TAG" -R "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
112
+ gh release upload "$TAG" -R "$GITHUB_REPOSITORY" --clobber artifacts/*
113
+ else
114
+ gh release create "$TAG" -R "$GITHUB_REPOSITORY" --verify-tag --title "$TAG" --generate-notes artifacts/*
115
+ fi
@@ -7,6 +7,8 @@ venv/
7
7
  dist/
8
8
  build/
9
9
  *.egg-info/
10
+ # Engine packed into platform wheels by scripts/build_wheels.py
11
+ src/pypilot/_engine/
10
12
 
11
13
  # Python bytecode & cache
12
14
  __pycache__/
@@ -33,11 +33,16 @@ What is in this repo:
33
33
 
34
34
  | Path | What it is |
35
35
  |---|---|
36
- | `src/pypilot/binary.py` | Platform detection, the engine cache, version checks, download and extraction |
37
- | `src/pypilot/cli.py` | The `pypilot` console script: runs the engine and passes its exit code through |
38
- | `src/pypilot/__init__.py` | The package version and `pypilot.run()` for use from Python |
39
- | `tests/test_cli.py` | The tests |
40
- | `.github/workflows/` | `ci.yml` (test matrix) and `publish.yml` (PyPI release) |
36
+ | `src/pypilot/binary.py` | The engine pin: `DEFAULT_TAG` and `ENGINE_SHA256`. The release workflow edits exactly these two. The old function names are re-exported from here |
37
+ | `src/pypilot/engine.py` | Platform detection, the lookup order, the cache, download, SHA-256 verification, offline mode and proxy handling |
38
+ | `src/pypilot/api.py` | `run()`, `arun()` and `RunResult` for use from Python |
39
+ | `src/pypilot/cli.py` | The `pypilot` console script: answers `--version`, passes everything else to the engine along with its exit code |
40
+ | `src/pypilot/__init__.py` | The package version and the public API |
41
+ | `hatch_build.py` | Build hook that turns the wheel into a platform wheel bundling the engine |
42
+ | `scripts/build_wheels.py` | Builds the sdist, the pure wheel and the four platform wheels |
43
+ | `scripts/sbom.py` | Adds the bundled engine to uv's CycloneDX SBOM |
44
+ | `tests/` | The tests |
45
+ | `.github/workflows/` | `ci.yml` (tests, wheel build, `pip-audit`) and `publish.yml` (PyPI and GitHub release) |
41
46
 
42
47
  ## License
43
48
 
@@ -57,13 +62,15 @@ and include:
57
62
  prints `PyPilot: downloading native engine from <url> ...`, so include both lines.
58
63
  - Whether you are behind a proxy or offline, if the download failed.
59
64
 
60
- The engine is looked up in this order: the cache, then `~/.cargo/bin`, then `PATH`,
61
- then a fresh download. The cache is `%LOCALAPPDATA%\pypilot\bin\pypilot.exe` on
62
- Windows (falling back to `~\.cache\pypilot\bin` if `LOCALAPPDATA` is unset), and
63
- `$XDG_CACHE_HOME/pypilot/bin/pypilot` on Linux and macOS (falling back to
64
- `~/.cache/pypilot/bin/pypilot`). A cached engine older than the one this package
65
- ships is replaced. If you suspect a broken download, delete that file and run
66
- `pypilot --version` again.
65
+ The engine is looked up in this order: `PYPILOT_ENGINE_VERSION` if set, then the
66
+ engine bundled in a platform wheel, then the cache, then `~/.cargo/bin`, then `PATH`,
67
+ then a fresh download (never with `PYPILOT_OFFLINE=1`). The cache holds one folder per
68
+ engine release: `%LOCALAPPDATA%\pypilot\bin\<tag>\pypilot.exe` on Windows (falling
69
+ back to `~\.cache\pypilot\bin` if `LOCALAPPDATA` is unset), and
70
+ `$XDG_CACHE_HOME/pypilot/bin/<tag>/pypilot` on Linux and macOS (falling back to
71
+ `~/.cache/pypilot/bin/<tag>/pypilot`). Downloads are checked against the pinned
72
+ SHA-256 before they are extracted. If you suspect a broken download, delete that file
73
+ and run `pypilot --version` again: its stderr line says which engine is in use.
67
74
 
68
75
  If the problem is about an environment (the output of `pypilot doctor`, a wrong
69
76
  Python or CUDA choice), report it in the
@@ -80,7 +87,7 @@ engine does belong in the [engine repo](https://github.com/pypilot-dev/pypilot).
80
87
 
81
88
  ## Setting up for development
82
89
 
83
- You need [uv](https://docs.astral.sh/uv/). The supported Pythons are 3.8 to 3.14.
90
+ You need [uv](https://docs.astral.sh/uv/). The supported Pythons are 3.8 to 3.15.
84
91
 
85
92
  ```bash
86
93
  git clone https://github.com/pypilot-dev/pypilot-pip.git
@@ -92,17 +99,20 @@ uv sync
92
99
  |---|---|
93
100
  | `uv run python -m pytest -W error` | Run the tests, with warnings as errors (what CI runs) |
94
101
  | `uv run --python 3.8 python -m pytest -W error` | The same on a specific Python version |
95
- | `uv build` | Build the sdist and wheel into `dist/` |
102
+ | `uv run python -m pytest -W error -m "not network"` | Only the tests that need no network |
103
+ | `uv build` | Build the sdist and the pure wheel into `dist/` |
104
+ | `uv run python scripts/build_wheels.py` | Also build the platform wheels with the verified engine (the Linux and macOS ones only on Linux or macOS, which keep the executable bit) |
96
105
  | `uvx twine check dist/*` | Check the built package's metadata |
97
106
 
98
- CI runs the tests on Python 3.8 to 3.14 on Linux, and on 3.8 and 3.14 on Windows and
107
+ CI runs the tests on Python 3.8 to 3.15 on Linux, and on 3.8 and 3.15 on Windows and
99
108
  macOS, because archive handling differs between platforms. Warnings are errors so
100
109
  that a deprecation which a new Python release turns into a behaviour change fails
101
110
  there first.
102
111
 
103
- **The tests need network access.** Some of them call the real `ensure_binary()` and
104
- `pypilot --version`, so they download the real engine from GitHub on the first run
105
- (and cache it, see above).
112
+ **Some tests need network access.** The ones marked `network` call the real
113
+ `ensure_binary()` and `pypilot --version`, so they download the real engine from
114
+ GitHub on the first run (and cache it, see above). Everything else (verification,
115
+ offline mode, proxies, the API) runs against a local server or a stand-in engine.
106
116
 
107
117
  ## Code notes
108
118
 
@@ -126,7 +136,7 @@ there first.
126
136
  2. Fork the repo and create a branch from `master`.
127
137
  3. Keep the change focused. Match the style of the surrounding code, and explain *why*
128
138
  in comments rather than restating what the code does. Add or update a test in
129
- `tests/test_cli.py` for a behaviour change.
139
+ `tests/` for a behaviour change.
130
140
  4. Make small, logical commits with clear messages (for example `fix(binary): ...`
131
141
  or `test: ...`). Use LF line endings.
132
142
  5. Run `uv run python -m pytest -W error`.
@@ -140,7 +150,9 @@ The maintainer reviews pull requests as time allows, so a short wait is normal.
140
150
 
141
151
  Releases are cut by the maintainer. Contributors do not need to bump versions or
142
152
  create tags. Pushing a tag `vX.Y.Z` runs the publish workflow, which tests, builds
143
- and publishes to PyPI through trusted publishing. `DEFAULT_TAG` in
144
- `src/pypilot/binary.py` names the engine release this package ships, so a new pip
145
- release is made only after that engine release exists. PyPI never allows a version
146
- number to be reused.
153
+ the sdist, the pure wheel and the four platform wheels, publishes them to PyPI through
154
+ trusted publishing, and attaches them with a CycloneDX SBOM to the GitHub release.
155
+ `DEFAULT_TAG` and `ENGINE_SHA256` in `src/pypilot/binary.py` name the engine release
156
+ this package ships and the SHA-256 of each of its archives, so a new pip release is
157
+ made only after that engine release exists. PyPI never allows a version number to be
158
+ reused.
@@ -0,0 +1,284 @@
1
+ Metadata-Version: 2.5
2
+ Name: pypilot-cli
3
+ Version: 1.3.0
4
+ Summary: Deterministic Python environment doctor, dependency solver, and hardware compatibility manager.
5
+ Project-URL: Homepage, https://github.com/pypilot-dev/pypilot
6
+ Project-URL: Repository, https://github.com/pypilot-dev/pypilot
7
+ Project-URL: Issues, https://github.com/pypilot-dev/pypilot/issues
8
+ Author-email: Abdullah Masood <Abdullah-Masood-05@users.noreply.github.com>
9
+ License-Expression: AGPL-3.0-or-later
10
+ License-File: LICENSE
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Programming Language :: Python :: 3.15
25
+ Classifier: Topic :: Software Development :: Build Tools
26
+ Classifier: Topic :: Software Development :: Quality Assurance
27
+ Requires-Python: >=3.8
28
+ Description-Content-Type: text/markdown
29
+
30
+ # PyPilot (CLI & Python Package)
31
+
32
+ <p align="center">
33
+ <a href="https://pypi.org/project/pypilot-cli/"><img src="https://img.shields.io/pypi/v/pypilot-cli?color=blue&logo=pypi&logoColor=white" alt="PyPI version" /></a>
34
+ <a href="https://pypi.org/project/pypilot-cli/"><img src="https://img.shields.io/pypi/pyversions/pypilot-cli?logo=python&logoColor=white" alt="Supported Python versions" /></a>
35
+ <a href="https://pypi.org/project/pypilot-cli/"><img src="https://img.shields.io/pypi/dm/pypilot-cli?color=2ea44f" alt="Monthly downloads" /></a>
36
+ <a href="https://github.com/pypilot-dev/pypilot-pip/blob/master/LICENSE"><img src="https://img.shields.io/pypi/l/pypilot-cli?color=blue" alt="License: AGPL-3.0-or-later" /></a>
37
+ <a href="https://github.com/pypilot-dev/pypilot"><img src="https://img.shields.io/badge/engine-Rust-orange?logo=rust&logoColor=white" alt="Rust engine" /></a>
38
+ <a href="https://github.com/pypilot-dev/pypilot"><img src="https://img.shields.io/github/stars/pypilot-dev/pypilot?style=social" alt="GitHub stars" /></a>
39
+ </p>
40
+
41
+ > ⭐ **Enjoying PyPilot?** If it saved you from a broken environment, please [star it on GitHub](https://github.com/pypilot-dev/pypilot). It's free and it helps other Python developers find it.
42
+
43
+ **PyPilot** is a deterministic Python environment doctor, dependency solver, and toolchain manager. Powered by a high-speed compiled **Rust engine**, PyPilot calculates dependency intersections directly from PyPI wheel metadata, resolves hardware and CUDA build compatibility, and sets up working virtual environments without external AI or API keys.
44
+
45
+ 📚 **Documentation:** <https://pypilot-dev.github.io/pypilot/> (the [Python package](https://pypilot-dev.github.io/pypilot/python/), its [API](https://pypilot-dev.github.io/pypilot/python/api), the [engine CLI](https://pypilot-dev.github.io/pypilot/engine/), [pixi](https://pypilot-dev.github.io/pypilot/pixi/) and the [configuration reference](https://pypilot-dev.github.io/pypilot/reference/configuration)).
46
+
47
+ ---
48
+
49
+ ## ⚡ High-Speed Native Rust Architecture
50
+
51
+ PyPilot combines the ease of installation via `pip` with the raw execution speed and low memory footprint of compiled Rust:
52
+ - **Instant startup**: Binary execution starts in single-digit milliseconds.
53
+ - **Zero Python overhead**: CLI commands delegate directly to the native `pypilot` binary.
54
+ - **Engine included**: the wheels for Linux `x86_64`, macOS `Apple Silicon` / `Intel` and Windows `x64` bundle the native engine, so `pip install` is all it takes and nothing is downloaded at run time. On other platforms the engine is downloaded once, checked against a pinned SHA-256, and cached; a system-installed Rust binary on your `$PATH` is respected.
55
+
56
+ ---
57
+
58
+ ## 📥 Installation
59
+
60
+ Install via `pip`:
61
+ ```bash
62
+ pip install pypilot-cli
63
+ ```
64
+
65
+ Or install as an isolated global tool with `uv`:
66
+ ```bash
67
+ uv tool install pypilot-cli
68
+ ```
69
+
70
+ Or via `pipx`:
71
+ ```bash
72
+ pipx install pypilot-cli
73
+ ```
74
+
75
+ pip picks the right wheel for you:
76
+
77
+ | Platform | Wheel | Engine |
78
+ |---|---|---|
79
+ | Linux x86_64, glibc 2.34 or newer (Ubuntu 22.04+, Debian 12+, RHEL/Alma/Rocky 9+, Fedora 35+) | `manylinux_2_34_x86_64` | bundled |
80
+ | macOS 11+ on Apple Silicon | `macosx_11_0_arm64` | bundled |
81
+ | macOS 10.12+ on Intel | `macosx_10_12_x86_64` | bundled |
82
+ | Windows x64 | `win_amd64` | bundled |
83
+ | Anything else (older glibc, other CPUs) | `py3-none-any` | downloaded on first use, if a release exists for the platform |
84
+
85
+ There is no musl (Alpine) build of the engine. On Linux with an older glibc, build the engine from source (`cargo install --path helper` in the [engine repo](https://github.com/pypilot-dev/pypilot)) and the wrapper will find it in `~/.cargo/bin`.
86
+
87
+ ---
88
+
89
+ ## 📖 CLI Reference & Commands
90
+
91
+ PyPilot provides a complete suite of environment doctor and bootstrap tools:
92
+
93
+ ### 1. `pypilot doctor`
94
+ Analyzes your current workspace, virtual environment, and dependency manifests (`requirements.txt`, `pyproject.toml`, `environment.yml`). Displays a read-only health check without modifying any files.
95
+ ```bash
96
+ pypilot doctor
97
+ # Target a specific workspace folder:
98
+ pypilot doctor --path /path/to/project
99
+ ```
100
+
101
+ ### 2. `pypilot setup`
102
+ Bootstraps a deterministic virtual environment. Automatically detects existing system tools:
103
+ - Uses system `uv` if present on `$PATH`.
104
+ - Supports **pip-compatible mode** (`uv venv` + `uv pip`) to accelerate installations without forcing a `pyproject.toml` migration.
105
+ - Falls back cleanly to standard `python -m venv` + `pip` if `uv` is not installed.
106
+ ```bash
107
+ pypilot setup
108
+ ```
109
+
110
+ ### 3. `pypilot check <package>`
111
+ Verifies whether a specific package and its wheels support your project's current Python interpreter version and operating system.
112
+ ```bash
113
+ pypilot check mediapipe
114
+ pypilot check torch
115
+ pypilot check tensorflow
116
+ ```
117
+
118
+ ### 4. `pypilot install <package>`
119
+ Installs a package into your virtual environment and records it in your manifest (`requirements.txt` or `pyproject.toml`), preserving version constraints.
120
+ ```bash
121
+ pypilot install requests
122
+ pypilot install numpy
123
+ ```
124
+
125
+ ### 5. `pypilot fix python`
126
+ Recomputes dependency version intersection and rebuilds the virtual environment on a Python version supported by all dependencies.
127
+ ```bash
128
+ pypilot fix python
129
+ ```
130
+
131
+ ### 6. `pypilot fix cuda`
132
+ Scans system NVIDIA driver version and CUDA runtime, then re-pins PyTorch or TensorFlow wheels to the exact hardware-matched CUDA build.
133
+ ```bash
134
+ pypilot fix cuda
135
+ ```
136
+
137
+ ### 7. `pypilot update-data`
138
+ Forces an immediate update of bundled hardware driver, CUDA compatibility matrices, and package wheel metadata.
139
+ ```bash
140
+ pypilot update-data
141
+ ```
142
+
143
+ ### 8. `pypilot migrate-conda`
144
+ Translates legacy Anaconda / Miniconda `environment.yml` configuration files into a standard modern `pyproject.toml`. With `--to pixi`, previews a `pixi.toml` instead (`--write` writes it; see [pixi support](#-pixi-support)).
145
+ ```bash
146
+ pypilot migrate-conda
147
+ pypilot migrate-conda --to pixi --write
148
+ ```
149
+
150
+ ### 9. `pypilot lsp`
151
+ Runs PyPilot as a Language Server Protocol (LSP) server over `stdio`. Used natively by editor extensions ([Zed](https://zed.dev) and [VS Code](https://marketplace.visualstudio.com/items?itemName=AbdullahMasood-005.pypilot-vscode)) for live import diagnostics and automated environment actions.
152
+ ```bash
153
+ pypilot lsp
154
+ ```
155
+
156
+ ### 10. `pypilot --version`
157
+ Prints the engine's version (`pypilot X.Y.Z`) on stdout, which is what editor extensions read, and the wrapper's own line on stderr: `pypilot-cli X.Y.Z (engine: <where>, <path>)`. `<where>` is `bundled`, `cache`, `download`, `cargo`, `path` or `override`. It also warns when the engine in use is older than the one this release of `pypilot-cli` pins, or comes from `~/.cargo/bin` / `PATH` with a different version.
158
+
159
+ ### 11. `pypilot completions <shell>`
160
+ Prints a shell completion script (generated by the engine), e.g. `pypilot completions bash > ~/.local/share/bash-completion/completions/pypilot`. Every argument except a lone `--version` / `-V` goes to the engine unchanged.
161
+
162
+ ---
163
+
164
+ ## 🐍 Python Programmatic API
165
+
166
+ PyPilot can also be imported and used directly inside Python code:
167
+
168
+ ```python
169
+ import pypilot
170
+
171
+ # Run any PyPilot command programmatically
172
+ result = pypilot.run(["doctor"], capture_output=True)
173
+ print(result.returncode, result.stdout)
174
+
175
+ # Commands with --json print {"pypilot": ..., "command": ..., "ok": ..., ...}
176
+ report = pypilot.run(["doctor", "--json"], capture_output=True).json()
177
+
178
+ # Raise subprocess.CalledProcessError on a non-zero exit
179
+ pypilot.run(["check", "torch"], check=True)
180
+
181
+ # Locate or ensure native engine is available
182
+ bin_path = pypilot.ensure_binary()
183
+ info = pypilot.locate_engine() # EngineInfo(path, source, version)
184
+ ```
185
+
186
+ From async code, `await pypilot.arun([...])` takes the same arguments and does not block the event loop.
187
+
188
+ - `run(args=None, capture_output=False, check=False, *, cwd=None, env=None, input=None, timeout=None)` returns a `RunResult`, a subclass of `subprocess.CompletedProcess`, so `.returncode`, `.stdout`, `.stderr` and `.check_returncode()` work as before. It adds `.ok` and `.json()`. Output is decoded as UTF-8, which is what the engine writes.
189
+ - Without `check=True` a failing command does not raise. Look at `.returncode`.
190
+ - Engine problems raise `pypilot.EngineError` subclasses: `EngineNotFoundError` (offline and no engine), `EngineDownloadError`, `EngineVerificationError`.
191
+ - The package ships `py.typed`, so type checkers see these signatures.
192
+
193
+ ---
194
+
195
+ ## 📦 pixi support
196
+
197
+ [pixi](https://pixi.sh) installs packages from conda-forge and PyPI into a per-project environment, with a lock file. It helps where pip and uv stop:
198
+
199
+ - **System libraries** (GDAL, PROJ, GEOS, libGL...): pip and uv cannot install them; conda-forge ships them next to the Python bindings.
200
+ - **No wheel for your platform or Python**: conda-forge often has a prebuilt build, so no compiler is needed.
201
+ - **The CUDA toolkit**: pip wheels carry only the CUDA runtime, not `nvcc`; conda-forge provides it per project.
202
+ - **One manifest** for Python together with R, C++ or Rust, **one lock file** (`pixi.lock`) covering native dependencies on every listed OS, and **several environments** (for example `default` and `cuda`) in one project.
203
+
204
+ **pixi projects.** A folder with a `pixi.toml`, or `[tool.pixi.workspace]` in `pyproject.toml`, is managed through pixi whatever `package_manager` says. PyPilot uses the environment in `.pixi/envs/<name>` (`default`, or `pixi_environment` / `--pixi-env <name>`), runs `pixi install` for setup and `pixi add --pypi` for installs, explains pixi's install errors, and never creates a `.venv`, runs uv or writes `pixi.lock`. `pypilot doctor` lists every environment and reports environments on different Pythons, a stale `pixi.lock` (a read-only check) and PyPI dependencies with no wheel for one of the manifest's platforms.
205
+
206
+ **When PyPilot suggests pixi.** In a pip or uv project, PyPilot recognises problems pip and uv cannot solve (a dependency with no wheel whose build needs native libraries, a failed build missing a header such as `gdal.h`, CUDA sources without `nvcc`, a repository mixing Python with R, Rust or C++) and suggests pixi. It never converts anything on its own. With `numpy`, `requests` and `gdal` in `requirements.txt` on Windows:
207
+
208
+ ```text
209
+ $ pypilot doctor
210
+ ...
211
+ [WARN ] GDAL 3.13.3 needs native libraries pip cannot install
212
+ GDAL 3.13.3 has no wheel for Windows x64, so pip and uv build it from source. [...] pixi installs gdal 3.13.3 from conda-forge with its native libraries (libgdal, proj, geos), built for win-64 and Python 3.15. Run `pypilot migrate-to-pixi` to set the project up with pixi.
213
+
214
+ $ pypilot migrate-to-pixi
215
+ Dry run: nothing was written.
216
+ ...
217
+ +[dependencies]
218
+ +python = "3.15.*"
219
+ +numpy = "*"
220
+ +requests = "*"
221
+ +gdal = "*"
222
+
223
+ Would write ...\geo\pixi.toml: python 3.15.*, 3 conda-forge and 0 PyPI dependencies.
224
+
225
+ Next: pypilot migrate-to-pixi --write
226
+ ```
227
+
228
+ **Moving to pixi.** `pypilot migrate-to-pixi` previews a `pixi.toml`; `--write` writes it and `--write --install` also runs `pixi install`. `pypilot migrate-conda --to pixi` does the same from an `environment.yml`. A separate `pixi.toml` is written; `pyproject.toml`, `requirements.txt` and `environment.yml` are never edited, so pip and CI keep working. `pypilot install-pixi` installs pixi with its official installer, and `package_manager = "pixi"` makes `setup` write the `pixi.toml` itself.
229
+
230
+ Guides: [pixi and PyPilot](https://pypilot-dev.github.io/pypilot/pixi/), [the advisory](https://pypilot-dev.github.io/pypilot/pixi/advisory), [migrating to pixi](https://pypilot-dev.github.io/pypilot/pixi/migrate).
231
+
232
+ > Engine 1.2.2, the one `pypilot-cli` 1.2.2 runs, already detects pixi projects and works through `pixi install` and `pixi add --pypi`. The environment choice, doctor's pixi checks, the advisory, `migrate-to-pixi`, `migrate-conda --to pixi`, `install-pixi` and `package_manager = "pixi"` need a newer engine: coming in the next release.
233
+
234
+ ---
235
+
236
+ ## ⚙️ Configuration
237
+
238
+ PyPilot respects workspace settings in `.pypilot.toml` or your editor configuration:
239
+ - `package_manager`: `"auto"` (default), `"uv"`, `"uv-pip"`, `"pip"`, or `"pixi"` (manage with pixi; a project without a pixi manifest gets a `pixi.toml` from setup). pixi projects are detected whatever this says.
240
+ - `notifications`: `"all"`, `"problems-only"`, or `"off"`.
241
+
242
+ ---
243
+
244
+ ## 🔒 The native engine: lookup, verification, offline and proxies
245
+
246
+ **Where the engine comes from.** The first match wins:
247
+
248
+ 1. `PYPILOT_ENGINE_VERSION=vX.Y.Z`, if set: that engine release, from the cache or downloaded (for testing other engines).
249
+ 2. The engine bundled in a platform wheel (`site-packages/pypilot/_engine/`).
250
+ 3. An earlier verified download of the pinned release, in the cache: `%LOCALAPPDATA%\pypilot\bin\<tag>\` on Windows, `$XDG_CACHE_HOME/pypilot/bin/<tag>/` (default `~/.cache/...`) elsewhere.
251
+ 4. `~/.cargo/bin/pypilot`, a source build, if it is at least 1.0.2.
252
+ 5. A `pypilot` engine on `PATH`, if it is at least 1.0.2. The wrapper skips its own `pypilot` launcher.
253
+ 6. A download of the pinned release, unless offline mode is on.
254
+
255
+ **Verification.** Each `pypilot-cli` release pins one engine release (`DEFAULT_TAG` in `pypilot/binary.py`) and the SHA-256 of each of its archives (`ENGINE_SHA256`). A download is checked before it is extracted or run. On a mismatch the file is deleted and the command fails with `SHA-256 mismatch`. With `PYPILOT_ENGINE_VERSION`, the archive is checked against that release's `SHA256SUMS` file instead. A release without one is refused unless you also set `PYPILOT_ALLOW_UNVERIFIED=1`, which prints a warning. The bundled wheels contain the same verified binaries.
256
+
257
+ **Offline.** `PYPILOT_OFFLINE=1` forbids every download. If no engine is available locally, PyPilot fails at once and tells you so, without waiting on the network. With a platform wheel, offline mode just works.
258
+
259
+ **Proxies.** Downloads use the standard proxy settings: `HTTPS_PROXY` / `HTTP_PROXY` and `NO_PROXY` (either case), or, when none is set, the system settings (Windows Internet Options, macOS network settings). A failed download says which proxy it went through. `PYPILOT_DOWNLOAD_TIMEOUT` sets the network timeout in seconds (default 60).
260
+
261
+ | Variable | Effect |
262
+ |---|---|
263
+ | `PYPILOT_OFFLINE=1` | Never download; fail fast if no engine is available |
264
+ | `PYPILOT_ENGINE_VERSION=vX.Y.Z` | Use this engine release instead of the pinned one |
265
+ | `PYPILOT_ALLOW_UNVERIFIED=1` | Allow a `PYPILOT_ENGINE_VERSION` release that has no `SHA256SUMS` |
266
+ | `PYPILOT_DOWNLOAD_TIMEOUT=<seconds>` | Network timeout for downloads (default 60) |
267
+ | `HTTPS_PROXY`, `NO_PROXY` | Proxy for downloads, and hosts that bypass it |
268
+
269
+ Each GitHub release of `pypilot-cli` also carries a CycloneDX SBOM (`pypilot-cli.cdx.json`) that lists the bundled engine archives with their hashes.
270
+
271
+ ---
272
+
273
+ ## 💙 Support the project
274
+
275
+ PyPilot is free and open source, built and maintained in spare time. If it helps you:
276
+
277
+ - ⭐ [Star it on GitHub](https://github.com/pypilot-dev/pypilot): it's the easiest way to show support.
278
+ - 🐛 [Report a bug or request a feature](https://github.com/pypilot-dev/pypilot/issues): reproducible environment problems are especially welcome.
279
+
280
+ ---
281
+
282
+ ## 📄 License
283
+
284
+ PyPilot is licensed under the **GNU Affero General Public License v3.0 (AGPL-3.0-or-later)**. See the [LICENSE](https://github.com/pypilot-dev/pypilot-pip/blob/master/LICENSE) file for the full license text.