fix(agents): use venv for pip fallback in azd ai agent run#8787
Conversation
When uv is not available, installPythonDepsPip now creates a .venv using python -m venv (matching the uv path behavior) and installs packages into it using the venv's pip binary. Also adds pyproject.toml support via pip install -e . for the pip fallback path. Fixes #8280 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
📋 Prioritization NoteThanks for the contribution! The linked issue isn't in the current milestone yet. |
There was a problem hiding this comment.
Pull request overview
This PR makes the azd ai agent run Python dependency installation behavior consistent when uv is missing by ensuring the pip fallback installs into a project-local .venv (instead of the global Python environment), and adds editable installs for pyproject.toml projects.
Changes:
- Create
.venvviapython -m venvin the pip fallback path when missing, and run installs using the venv’spip. - Add
pyproject.tomlsupport to the pip fallback viapip install -e .. - Introduce helper functions for locating venv
pipand a system Python, plus unit tests for those helpers.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| cli/azd/extensions/azure.ai.agents/internal/cmd/run.go | Updates pip fallback to create/use .venv, adds pyproject.toml editable install support, and introduces venvPip/findSystemPython helpers. |
| cli/azd/extensions/azure.ai.agents/internal/cmd/run_test.go | Adds unit tests for venvPip and findSystemPython. |
- Handle non-IsNotExist stat errors and validate .venv is a directory - Change findSystemPython to return (string, error) with actionable message - Add 'py' launcher fallback on Windows - Rewrite TestFindSystemPython with controlled PATH for deterministic testing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jongio
left a comment
There was a problem hiding this comment.
Clean, well-scoped fix that brings the pip fallback in line with the uv path. The switch-based stat handling is solid, helper functions follow existing patterns (venvPython, venvBinDir), and tests use controlled PATH for determinism. Nice work addressing the earlier Copilot feedback in the follow-up commit.
One nit below about the version string in findSystemPython.
jongio
left a comment
There was a problem hiding this comment.
The pip fallback venv reuse has a gap when .venv was previously created by uv venv, which doesn't include pip by default. If uv later becomes unavailable, the pip path skips venv creation (.venv exists) but venvPip() returns a path to a missing binary. This produces a confusing exec error rather than actionable guidance.
Consider checking fileExists(pipPath) before invoking it and running python -m ensurepip --upgrade as a bootstrap, or surfacing a clear error pointing the user to delete .venv and retry.
Not blocking for this PR since the core fix (venv isolation for pip fallback) is correct and well-tested. The uv-to-pip transition is an edge case that can be addressed in a follow-up.
…3.13+ - Bootstrap pip via ensurepip when venv exists but pip binary is missing (handles venvs created by uv which omits pip by default) - Add checkPythonVersion to fail if system Python < 3.13, matching the uv path's --python '>=3.13' constraint - Add TestCheckPythonVersion Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jongio
left a comment
There was a problem hiding this comment.
Incremental review of 2 new commits (2225262, 7442f9c) since my last review.
Both prior findings are addressed:
- Version enforcement:
checkPythonVersionnow enforces>=3.13parity with the uv path's--python ">=3.13"constraint. Parsing logic handles standard CPython and non-standard (e.g. PyPy) version strings correctly. - uv-to-pip transition: the
ensurepipbootstrap detects a pip-less venv (fromuv venv) and runspython -m ensurepip --upgradebefore dependency installation. Placement after the venv existence check and beforepip installis correct.
No new issues in the incremental diff. The test for checkPythonVersion exercises the real system Python, which validates format parsing. It doesn't exercise the "too old" rejection path deterministically (would need a mock), but the version comparison logic is straightforward.
jongio
left a comment
There was a problem hiding this comment.
Incremental review of 996234b (cspell config relocation).
Moving ensurepip from the core cli/azd/.vscode/cspell.yaml to the extension's own cspell.yaml is correct per the extension-specific config convention.
All findings from prior reviews are addressed. No new issues.
One blocker before merge: conflict in cli/azd/extensions/azure.ai.agents/cspell.yaml where main added recordproxy to the same section. Trivial resolution (keep both entries).
|
@copilot resolve the merge conflicts in this pull request |
…-install Co-authored-by: trangevi <26490000+trangevi@users.noreply.github.com>
jongio
left a comment
There was a problem hiding this comment.
Incremental review: the merge from main resolved the cspell.yaml conflict (both ensurepip and recordproxy entries preserved). The pip-fallback venv logic doesn't interact with the predeploy/postdeploy migration (#8788) or model updates (#8789) merged since my last pass. Agents gate CI is still pending.
|
/check-enforcer override |
Why
When
uvis not installed,azd ai agent runfalls back topipfor Python dependency installation. However, the pip fallback path was installing packages into the global Python environment instead of a.venv, unlike theuvpath which always creates and uses a virtual environment. This inconsistency causes global package pollution and surprising behavior for users withoutuv.What changed
Updated
installPythonDepsPipto mirror theuvpath behavior:.venvusingpython -m venvif one doesn't already exist (uses stdlib, no extra tools needed)<venv>/bin/pipor<venv>/Scripts/pip.exe) instead of systempipfor all installspyproject.tomlsupport viapip install -e .-- theuvpath already supported this but the pip fallback did notAdded helper functions
venvPip()(returns the OS-appropriate path to the venv pip) andfindSystemPython()(locatespython3orpythonon PATH for initial venv creation).Testing
TestResolveVenvCommandtests continue to passTestVenvPipandTestFindSystemPythonunit testsFixes: #8280