Skip to content

Commit 64a6e51

Browse files
committed
skill: add gotcha 244 from the daft port
A "Test wheel" step ran `uv pip install` with PIP_EXTRA_INDEX_URL / PIP_ONLY_BINARY set, which uv silently ignores (it only reads UV_* names), so it source-built pyarrow against public PyPI and hit a missing Arrow C++ CMake package ~6.5h later.
1 parent 0385b95 commit 64a6e51

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

‎skills/python-project-porting/references/gotchas-index.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ The porting gotchas (221 of them) live in [`references/gotchas/`](gotchas/), spl
9494
- **221** — `quay.io/pypa/musllinux_1_2_riscv64` is a real, working image — every prior port
9595
- **225** — `CIBW_BEFORE_ALL_LINUX` and `CIBW_BEFORE_BUILD_LINUX` are two different hooks —
9696
- **227** — A build that touches `PyObject` internals directly (`ob_refcnt`, `ob_type`,
97+
- **245** — `actions/checkout` must run before `actions/download-artifact` in the same
9798

9899
### Rust, maturin & PyO3 — [`gotchas/rust-maturin-and-pyo3.md`](gotchas/rust-maturin-and-pyo3.md)
99100

@@ -195,6 +196,7 @@ The porting gotchas (221 of them) live in [`references/gotchas/`](gotchas/), spl
195196
- **232** — Matching upstream's newest interpreter tier can silently trade a fast port for a
196197
- **234** — A stock distro `pip` can be too old to *recognize* a riscv64 manylinux wheel at
197198
- **240** — A registry-hosted wheel that builds and installs cleanly can still be missing an
199+
- **244** — `uv pip install` only honors `UV_*` env vars, never the `PIP_*` names — a step
198200

199201
### Build-tool drift & pins — [`gotchas/build-tool-drift-and-pins.md`](gotchas/build-tool-drift-and-pins.md)
200202

‎skills/python-project-porting/references/gotchas/dependencies-and-registry.md‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ To pull up one entry: `grep -n '^N\. ' references/gotchas/dependencies-and-regis
2424
- **234** — A stock distro `pip` can be too old to *recognize* a riscv64 manylinux wheel at
2525
- **240** — A registry-hosted wheel that builds and installs cleanly can still be missing an
2626
*optional* component another test dependency imports unconditionally.
27+
- **244** — `uv pip install` only honors `UV_*` env vars, never the `PIP_*` names — a step
28+
written with `PIP_EXTRA_INDEX_URL`/`PIP_ONLY_BINARY` silently no-ops and source-builds.
2729

2830
---
2931

@@ -478,3 +480,40 @@ To pull up one entry: `grep -n '^N\. ' references/gotchas/dependencies-and-regis
478480
unconditional import and noting why in the PR (naming the module and the disabled
479481
flag) is the same move gotcha 215 makes for a per-interpreter registry gap, applied
480482
to a per-feature one instead.
483+
484+
244. **`uv pip install` only honors `UV_*` env vars, never the `PIP_*` names — a step
485+
written with `PIP_EXTRA_INDEX_URL`/`PIP_ONLY_BINARY` silently no-ops and source-builds
486+
(the daft port).** A "Test wheel" step ran `uv pip install pandas==2.3.3 numpy==2.3.4
487+
pyarrow==25.0.1 dist/*.whl` with `PIP_EXTRA_INDEX_URL: https://pypi.riseproject.dev/
488+
simple/` and `PIP_ONLY_BINARY: numpy,pandas,pyarrow` set as step `env:` — the same
489+
variable names gotcha 30 and friends use everywhere else in this repo, because most
490+
other test steps run inside cibuildwheel's `CIBW_TEST_ENVIRONMENT`, which shells out to
491+
plain `pip` and does read them. `uv`'s pip-compatible subcommand does not: it reads
492+
`UV_EXTRA_INDEX_URL`, `UV_INDEX_STRATEGY`, and `UV_ONLY_BINARY` instead (`uv help pip
493+
install` lists the `[env: UV_…]` name for every pip-shaped flag). With the `PIP_*` names
494+
unrecognized, uv silently fell back to its defaults — default index only (public PyPI,
495+
no riscv64 wheels), no only-binary restriction — resolved `pyarrow==25.0.1` against
496+
PyPI's sdist, and source-built it. pyarrow's sdist needs the real Apache Arrow C++
497+
library and its CMake config (`FindArrow.cmake`/`ArrowConfig.cmake`) to configure at
498+
all, which the manylinux image doesn't carry, so the failure surfaced ~6.5 hours later
499+
as `CMake Error … Could not find a package configuration file provided by "Arrow"` —
500+
a red herring that looks like a missing native C++ dependency of the package under
501+
test, when the actual break is a silently-ignored env var one step earlier. The
502+
registry already had the exact riscv64 wheel needed
503+
(`pyarrow-25.0.1-cp312-cp312-manylinux_2_39_riscv64.whl`); it was simply never
504+
consulted.
505+
- **The fix is renaming the three vars, not touching indexes or CMake.** Swap to
506+
`UV_EXTRA_INDEX_URL` / `UV_ONLY_BINARY`, and add `UV_INDEX_STRATEGY:
507+
unsafe-best-match` alongside them — uv's default `first-index` strategy stops at
508+
the first index that lists the package *name* at all (here, PyPI, which lists
509+
pyarrow but not a riscv64 build of it) and never reaches a second index for a
510+
platform-specific wheel, the same reasoning build-matplotlib.yml's and
511+
build-onnx.yml's `env:` blocks already document for their own `uv pip install`/
512+
`uv pip download` steps.
513+
- **Any bare `uv pip install`/`uv pip download` step is a signal to check this** —
514+
not just ones added fresh. cibuildwheel-driven steps (`CIBW_TEST_ENVIRONMENT`,
515+
`CIBW_ENVIRONMENT`) are unaffected since those still shell out to `pip`; the risk is
516+
specifically a workflow step that invokes `uv` directly (`setup-uv` + `uv pip
517+
install`, as build-daft.yml's and build-polars-runtime.yml's "Test wheel" steps do)
518+
and reuses the `PIP_*` names out of habit from the cibuildwheel case elsewhere in
519+
the same file.

0 commit comments

Comments
 (0)