Expose uv's libpython on LD_LIBRARY_PATH for PyO3 baselines (#372) - #379
Expose uv's libpython on LD_LIBRARY_PATH for PyO3 baselines (#372)#379leynos wants to merge 1 commit into
Conversation
PyO3 embedding crates (the auto-initialize pattern) link their test binaries against the interpreter PyO3's build script resolves from PATH. Setup uv puts a uv-managed CPython ahead of the system python3, and its libpython lives under uv's private install directory, off the loader's default search path. The unmutated baseline cargo test binary then aborts with "libpython3.NN.so: cannot open shared object file" and no mutant is ever scored. After provisioning Python, derive the interpreter's LIBDIR via sysconfig and add it to LD_LIBRARY_PATH for the later steps, before Run mutation testing. This is harmless for non-PyO3 callers: nothing links libpython, so nothing loads from the added directory. Pin a shape-test invariant that the export precedes the run step, and document the automatic handling in the caller guide.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
Summary
WalkthroughThe mutation workflow now exposes uv-managed Python’s ChangesPyO3 libpython runtime support
Sequence Diagram(s)sequenceDiagram
participant mutants_job
participant python3
participant LD_LIBRARY_PATH
participant cargo_mutants
mutants_job->>python3: Resolve Python LIBDIR
python3-->>mutants_job: Return library directory
mutants_job->>LD_LIBRARY_PATH: Append valid LIBDIR
mutants_job->>cargo_mutants: Run mutation testing
Possibly related issues
Possibly related PRs
Suggested labels: Poem
Caution Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional.
❌ Failed checks (1 error, 2 warnings)
✅ Passed checks (17 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/mutation-cargo-workflow.md`:
- Around line 102-106: Qualify the automatic PyO3 embedding-crate handling
description to apply only when the workflow resolves a valid interpreter LIBDIR
on hosted runners. Note that the LD_LIBRARY_PATH export is skipped when ACT=true
and remains unchanged when LIBDIR is unavailable, so avoid stating
unconditionally that no setup-commands workaround is needed.
In `@workflow_scripts/tests/test_mutation_workflow_shape.py`:
- Around line 72-78: Update the `exposers` predicate in the shape test to
require each matching run script to reference `GITHUB_ENV` and use `>>`, in
addition to the existing `LD_LIBRARY_PATH` and `get_config_var("LIBDIR")`
checks, ensuring the computed environment value is persisted for later steps.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 6e32f0e7-5822-4edf-ba84-614baa06cfac
📒 Files selected for processing (3)
.github/workflows/mutation-cargo.ymldocs/mutation-cargo-workflow.mdworkflow_scripts/tests/test_mutation_workflow_shape.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/polythene(auto-detected)
| - Callers with PyO3 embedding crates (the `auto-initialize` pattern) | ||
| are handled automatically: the workflow adds the uv-provisioned | ||
| interpreter's `LIBDIR` to `LD_LIBRARY_PATH` before running | ||
| cargo-mutants, so test binaries linked against `libpython` load it at | ||
| run time. No `setup-commands` workaround is needed. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Qualify the automatic-handling claim.
State that this applies when the workflow resolves a valid LIBDIR on hosted runners. The implementation skips the export under ACT=true and intentionally continues unchanged when LIBDIR is missing, so “No setup-commands workaround is needed” is not universally guaranteed.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/mutation-cargo-workflow.md` around lines 102 - 106, Qualify the
automatic PyO3 embedding-crate handling description to apply only when the
workflow resolves a valid interpreter LIBDIR on hosted runners. Note that the
LD_LIBRARY_PATH export is skipped when ACT=true and remains unchanged when
LIBDIR is unavailable, so avoid stating unconditionally that no setup-commands
workaround is needed.
| exposers = [ | ||
| index | ||
| for index, step in enumerate(steps) | ||
| if isinstance(step.get("run"), str) | ||
| and "LD_LIBRARY_PATH=" in typ.cast("str", step.get("run")) | ||
| and 'get_config_var("LIBDIR")' in typ.cast("str", step.get("run")) | ||
| ] |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Assert persistence through GITHUB_ENV.
Require the shape test to verify that the export script writes to GITHUB_ENV, not merely that it contains the relevant strings. Otherwise, a command that computes or prints LD_LIBRARY_PATH could pass while Run mutation testing still receives no updated environment.
and "LD_LIBRARY_PATH=" in typ.cast("str", step.get("run"))
and 'get_config_var("LIBDIR")' in typ.cast("str", step.get("run"))
+ and "GITHUB_ENV" in typ.cast("str", step.get("run"))
+ and ">>" in typ.cast("str", step.get("run"))🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@workflow_scripts/tests/test_mutation_workflow_shape.py` around lines 72 - 78,
Update the `exposers` predicate in the shape test to require each matching run
script to reference `GITHUB_ENV` and use `>>`, in addition to the existing
`LD_LIBRARY_PATH` and `get_config_var("LIBDIR")` checks, ensuring the computed
environment value is persisted for later steps.
Summary
mutation-cargo.yml's unmutated baseline fails deterministically for callerswhose crates embed a Python interpreter via PyO3 (the
auto-initializepattern), such as leynos/tei-rapporteur's
tei-pyand stilyagi. PyO3's buildscript resolves the interpreter from
PATH;Setup uvplaces a uv-managedCPython ahead of the system
python3, and itslibpython3.NN.so.1.0livesunder uv's private install directory, off the dynamic loader's default search
path. The baseline
cargo testbinary then aborts with "libpython3.13.so.1.0:cannot open shared object file" (exit 127) and no mutant is ever scored.
This adds a step, after Python provisioning and before
Run mutation testing,that derives the resolved interpreter's
LIBDIRviasysconfig.get_config_var("LIBDIR")and prepends it toLD_LIBRARY_PATHforthe later steps. It is harmless for non-PyO3 callers: no test binary links
libpython, so nothing loads from the added directory.Closes #372.
Supersedes the caller-side mitigation tracked in leynos/stilyagi#90 (which
worked around this with
setup-commands); that issue can stay open for thecaller to drop its workaround once this lands — this PR does not close it.
Review walkthrough
.github/workflows/mutation-cargo.yml— newExpose libpython for PyO3 test binariesstep in themutantsjob (guardedenv.ACT != 'true'), betweenSetup uvandRelocate workflow source. It skips cleanly when no LIBDIRresolves.
docs/mutation-cargo-workflow.md— documents the automatic handling.workflow_scripts/tests/test_mutation_workflow_shape.py— new invarianttest_mutants_job_exposes_libpython_before_runningpins that the exportprecedes the run step.
Validation
pytest workflow_scripts/tests/test_mutation_workflow_shape.py— 5 passed.ruff format --check/ruff check— clean;markdownlint/typoson thechanged doc — clean.