Skip to content

Commit 498e2d2

Browse files
authored
Invoke python -m venv from a different working directory (#1698)
When `python -m venv` is run, after creating the virtual environment it invokes `ensurepip` to install pip. The `ensurepip` module in older Python versions didn't correctly run its Python subprocesses in isolated mode, meaning that the working directory is added to `sys.path`. This can cause issues if the app's build directory contains files/directories that shadow expected package names (such as a `brotli` directory). For example: ``` -----> Installing Poetry 1.8.4 Error: Command '['/tmp/codon/tmp/cache/.heroku/python-poetry/venv/bin/python', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1. ! Internal Error: Unable to create virtual environment for Poetry. ! ! The 'python -m venv' command to create a virtual environment did ! not exit successfully. ! ! See the log output above for more information. ``` The best fix is for apps to upgrade to newer Python patch versions (3.8.14+, 3.9.14+, 3.10.6+), since they include the upstream `ensurepip` fix as well as many other bug and security fixes. However, to ensure venv creation still works on these older Python versions, as a workaround we can run the `python -m venv` command from a different working directory (as an alternative to isolated mode). Fixes #1697. GUS-W-17215816.
1 parent ddf6aea commit 498e2d2

File tree

4 files changed

+12
-3
lines changed

4 files changed

+12
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## [Unreleased]
44

55
- Deprecated using Pipenv without a lockfile (`Pipfile.lock`). ([#1695](https://github.com/heroku/heroku-buildpack-python/pull/1695))
6+
- Fixed Poetry venv creation when using an outdated Python version whose `ensurepip` module doesn't enable isolated mode, and the app's build directory contents shadows a package imported by pip (such as `brotli`). ([#1698](https://github.com/heroku/heroku-buildpack-python/pull/1698))
67

78
## [v266] - 2024-11-08
89

lib/poetry.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ function poetry::install_poetry() {
3737

3838
# The Poetry directory will already exist in the relocated cache case mentioned above.
3939
rm -rf "${poetry_root}"
40+
mkdir -p "${poetry_root}"
4041

4142
# We can't use the pip wheel bundled within Python's standard library to install Poetry
4243
# (which would allow us to use `--without-pip` here to skip the pip install), since it
@@ -45,7 +46,10 @@ function poetry::install_poetry() {
4546
# are still using outdated patch releases of those Python versions, whose bundled pip
4647
# can be older (for example Python 3.9.0 ships with pip v20.2.1). Once Python 3.10 EOLs
4748
# we can switch back to the previous approach since Python 3.11.0 ships with pip v22.3.
48-
if ! python -m venv "${poetry_venv_dir}"; then
49+
# Changing the working directory away from the build dir is required to work around an
50+
# `ensurepip` bug in older Python versions, where it doesn't run Python in isolated mode:
51+
# https://github.com/heroku/heroku-buildpack-python/issues/1697
52+
if ! (cd "${poetry_root}" && python -m venv "${poetry_venv_dir}"); then
4953
output::error <<-EOF
5054
Internal Error: Unable to create virtual environment for Poetry.
5155
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The brotli directory tests the workaround for an `ensurepip` bug in older Python versions:
2+
https://github.com/heroku/heroku-buildpack-python/issues/1697

spec/hatchet/poetry_spec.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,10 @@
185185
end
186186
end
187187

188-
# This checks that the Poetry bootstrap works even with older bundled pip, and that
189-
# our chosen Poetry version also supports our oldest supported Python version.
188+
# This checks that the Poetry bootstrap works even with older bundled pip, and that our
189+
# chosen Poetry version also supports our oldest supported Python version. The fixture
190+
# also includes a `brotli` directory to test the workaround for an `ensurepip` bug in
191+
# older Python versions: https://github.com/heroku/heroku-buildpack-python/issues/1697
190192
context 'when using the oldest supported Python version' do
191193
let(:app) { Hatchet::Runner.new('spec/fixtures/poetry_oldest_python') }
192194

0 commit comments

Comments
 (0)