feat(python): auto-activate venv before hook execution#347
feat(python): auto-activate venv before hook execution#347mwbrooks wants to merge 7 commits intomwbrooks-python-venvfrom
Conversation
Set VIRTUAL_ENV, prepend venv bin to PATH, and unset PYTHONHOME on the CLI process before any hooks run. This lets hook scripts (e.g. get-hooks, start, deploy) resolve the venv's Python and installed packages without requiring developers to manually activate the venv. Activation happens in InitSDKConfig after finding the project root and before reading/executing hooks. It is a no-op when no .venv exists, so non-Python projects are unaffected. Failure is non-fatal (debug log).
Return a boolean from ActivateVenvIfPresent to indicate whether activation occurred, and log a debug message on success.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## mwbrooks-python-venv #347 +/- ##
========================================================
- Coverage 64.77% 64.70% -0.08%
========================================================
Files 212 212
Lines 17860 17884 +24
========================================================
+ Hits 11569 11571 +2
- Misses 5212 5224 +12
- Partials 1079 1089 +10 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
mwbrooks
left a comment
There was a problem hiding this comment.
Comments for those kind reviewers! 🙇🏻
internal/runtime/python/python.go
Outdated
| if err := os.Setenv("VIRTUAL_ENV", venvPath); err != nil { | ||
| return false, err | ||
| } | ||
| if err := os.Setenv("PATH", binDir+string(filepath.ListSeparator)+os.Getenv("PATH")); err != nil { | ||
| return false, err | ||
| } | ||
| os.Unsetenv("PYTHONHOME") |
There was a problem hiding this comment.
note: I imagine we should create wrappers for these calls in our slackdeps.Os 🤔
There was a problem hiding this comment.
note: I updated this PR to use slackdeps.Os and added slackdeps.Os.lookupEnv.
| // ActivatePythonVenvIfPresent activates a Python virtual environment if one | ||
| // exists in the given project directory. This sets VIRTUAL_ENV, prepends the | ||
| // venv bin directory to PATH, and unsets PYTHONHOME on the current process so | ||
| // that child processes (hook scripts) inherit the activated venv. | ||
| func ActivatePythonVenvIfPresent(fs afero.Fs, projectDir string) (bool, error) { | ||
| return python.ActivateVenvIfPresent(fs, projectDir) | ||
| } | ||
|
|
There was a problem hiding this comment.
note: While it feels wrong to have Python in the generic runtime this allows us to activate it for any project. We could move this into the Python runtime and think of a more general function that could be used across all runtimes.
Upside of this approach is that JS projects that include a .venv (perhaps for scripts) can be activated automatically.
| if activated, err := runtime.ActivatePythonVenvIfPresent(c.Fs, dirPath); err != nil { | ||
| c.IO.PrintDebug(ctx, "failed to activate Python virtual environment: %s", err) | ||
| } else if activated { | ||
| c.IO.PrintDebug(ctx, "Activated Python virtual environment .venv") |
There was a problem hiding this comment.
note: I'd love to display this in the regular output, but it's tough to get a nice format because it can be displayed in many different situations.
…bility Add Unsetenv to the Os interface/implementation/mock and refactor ActivateVenvIfPresent to accept types.Os instead of calling the os package directly. This allows the test to use mocks instead of mutating the real process environment.
Changelog
Summary
This pull request gives Python the "create and run" experience that Node and Deno enjoy.
It enables auto-activation of venv, when it exists, so that commands can run safely and successfully even when the terminal session doesn't have a virtual environment activated. When the
.venvis missing, the CLI will continue like normal.Test coverage:
mwbrooks-python-venvis merged, this branch will report higher coverageMerge order:
mwbrooks-python-venvmwbrooks-python-venvthen merge this PR intomainPreview
2026-02-20-create-run-python.mov
Reviewers
Bolt for Python:
Bolt for JavaScript:
Requirements