fix(poetry plugin): activate the in-project virtualenv so scripts land on PATH - #2958
mikeland73 wants to merge 2 commits into
Conversation
…d on PATH Since Poetry 2.0.0 removed the bundled `poetry shell` command, the poetry plugin relies on `poetry env use` (in initHook.sh) to point Poetry at the Devbox-provided Python. That selects the virtualenv but never activates it, so console scripts and entry points installed by `poetry install` live in `<project>/.venv/bin` and are not on the Devbox shell's PATH. Users are forced to prefix everything with `poetry run`. The plugin already sets POETRY_VIRTUALENVS_IN_PROJECT=true, so the virtualenv is always created at `<pyproject-dir>/.venv`. Activate it from the init_hook (which runs in the sourced shellrc context, unlike the executed initHook.sh) by exporting VIRTUAL_ENV and prepending its `bin` to PATH once the directory exists. Plugin init hooks run before the user's hooks, and `poetry env use` creates `.venv`, so the guard passes by the time the user's `poetry install` populates `.venv/bin`. The path templates are env-var based and fully double-quoted, so project directories containing spaces are handled correctly. Bump the plugin version so existing environments pick up the new hook. Fixes #2676
|
@claude please review this PR for correctness, and flag anything that would block merging. |
|
Claude finished @mikeland73's task in 4m 30s —— View job Review: correctness check on the poetry plugin fix
The core idea is sound — sourcing the init hook (rather than executing 🔴 Blocking: the new hook line will break
|
Review: correctness & merge-blockersI reviewed the change adversarially. No correctness blockers — a few non-blocking notes below for your call. Verified correct
Non-blocking considerations
CI caveatNo CI checks have reported on this PR (status is Generated by Claude Code |
The previous approach inlined a POSIX `if [ -d … ]; then … fi` compound
statement in the plugin's init_hook. That breaks the fish shell: fish
sources the combined .hooks file natively (internal/devbox/shellrc_fish.tmpl),
and fish has no `then`/`fi` keywords (its blocks close with `end`), so the
unterminated `if` is a parse error that aborts the entire hooks file — not
just poetry's activation — for any fish user with the poetry plugin.
Prepend the in-project virtualenv's bin directory to PATH via the plugin's
`env` field instead, matching the existing, shell-portable convention used
by the nodejs and ruby plugins (e.g. nodejs `"PATH": "{{ .Virtenv }}/corepack-bin:$PATH"`).
Devbox expands the value with os.Expand and emits it as a literal export,
so it is applied uniformly across bash, zsh, and fish with no inline shell
syntax. The path uses the {{ .DevboxProjectDir }} template (POETRY_VIRTUALENVS_IN_PROJECT
is true, so the venv lives at <project>/.venv); a not-yet-created dir on
PATH is harmless and resolves once `poetry install` populates it.
Fixes #2676
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aiRPVpidRdyKDJiUQJhxN
|
Good catch on the fish-shell breakage — that's a real blocker, and I've verified and fixed it in Confirmed the mechanism: fish sources the combined Rather than rewrite it as "env": {
...
"PATH": "{{ .DevboxProjectDir }}/.venv/bin:$PATH"
}This matches what the One deliberate trade-off worth flagging: because Generated by Claude Code |
Summary
Fixes #2676.
Since Poetry 2.0.0 removed the bundled
poetry shellcommand, the poetry plugin relies onpoetry env use(ininitHook.sh) to point Poetry at the Devbox-provided Python. That selects the virtualenv but never activates it, so console scripts and entry points installed bypoetry installlive in<project>/.venv/binand are not on the Devbox shell's PATH. Users are forced to prefix everything withpoetry run, which is the regression reported in the issue:Fix
The plugin already sets
POETRY_VIRTUALENVS_IN_PROJECT=true, so the virtualenv is always created at<pyproject-dir>/.venv. I activate it from the plugin'sinit_hook— which runs in the sourced shellrc context, unlike the executedinitHook.sh, so it can actually modify the shell'sPATH:Ordering makes this robust:
Config.InitHook()appends included-plugin hooks ahead of the root config's hooks).poetry env useinsideinitHook.shcreates.venv, so the[ -d … ]guard already passes when the activation line runs.poetry installexecutes,.venv/binis already onPATH, so the freshly installed scripts resolve by name.The path is derived from env vars and every expansion is double-quoted, so project directories containing spaces are handled correctly. The plugin
versionis bumped0.0.5→0.0.6so existing environments regenerate with the new hook, matching the convention used by prior plugin behavior changes.How was it tested?
go test ./plugins/ ./internal/plugin/passes, includingplugins/init_hook_quoting_test.go(the new line uses no{{ }}templates, and all path expansions are quoted).bash -nsyntax-checked the rendered activation line.DEVBOX_DEFAULT_PYPROJECT_DIR="/tmp/pdir with space", placed an executable at.venv/bin/myscript, ran the activation line, and confirmedVIRTUAL_ENVwas set correctly andmyscriptresolved and ran by name fromPATH.cc @tlelson — thanks for the clear root-cause analysis and reproduction in the issue.
Community Contribution License
All community contributions in this pull request are licensed to the project
maintainers under the terms of the
Apache 2 License.
By creating this pull request, I represent that I have the right to license the
contributions to the project maintainers under the Apache 2 License as stated in
the
Community Contribution License.
Generated by Claude Code