Skip to content

Commit 992f51d

Browse files
authored
Stop installing pip into Poetry's virtual environment (#1761)
This is an alternative approach to installing Poetry that means we can skip installing pip into its virtual environment, but still support the outdated Python versions which bundle older pip (that don't support the `--python` option; see #1687) or that don't correctly isolate the environment when running `ensurepip` (see #1698). Skipping installing pip speeds up the cold cache build for Poetry slightly, and also reduces the build cache size (which will help with the cache save and restore times for warm builds too). The pip installed in the Poetry venv wasn't exposed to apps (since it wasn't on `PATH`) so is safe to remove. GUS-W-17895154.
1 parent 53a59ae commit 992f51d

File tree

3 files changed

+19
-15
lines changed

3 files changed

+19
-15
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## [Unreleased]
44

5+
- Stopped installing pip into Poetry's virtual environment. ([#1761](https://github.com/heroku/heroku-buildpack-python/pull/1761))
56

67
## [v278] - 2025-02-24
78

bin/compile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ case "${package_manager}" in
205205
pipenv::install_pipenv
206206
;;
207207
poetry)
208-
poetry::install_poetry "${CACHE_DIR}" "${EXPORT_PATH}"
208+
poetry::install_poetry "${python_home}" "${python_major_version}" "${CACHE_DIR}" "${EXPORT_PATH}"
209209
;;
210210
*)
211211
utils::abort_internal_error "Unhandled package manager: ${package_manager}"

lib/poetry.sh

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ set -euo pipefail
77
POETRY_VERSION=$(utils::get_requirement_version 'poetry')
88

99
function poetry::install_poetry() {
10-
local cache_dir="${1}"
11-
local export_file="${2}"
10+
local python_home="${1}"
11+
local python_major_version="${2}"
12+
local cache_dir="${3}"
13+
local export_file="${4}"
1214

1315
# We store Poetry in the build cache, since we only need it during the build.
1416
local poetry_root="${cache_dir}/.heroku/python-poetry"
@@ -39,17 +41,12 @@ function poetry::install_poetry() {
3941
rm -rf "${poetry_root}"
4042
mkdir -p "${poetry_root}"
4143

42-
# We can't use the pip wheel bundled within Python's standard library to install Poetry
43-
# (which would allow us to use `--without-pip` here to skip the pip install), since it
44-
# requires using the `--python` option, which was only added in pip v22.3. And whilst
45-
# all major Python versions we support now bundled a newer pip than that, some apps
46-
# are still using outdated patch releases of those Python versions, whose bundled pip
47-
# can be older (for example Python 3.9.0 ships with pip v20.2.1). Once Python 3.10 EOLs
48-
# we can switch back to the previous approach since Python 3.11.0 ships with pip v22.3.
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
44+
# We use the pip wheel bundled within Python's standard library to install Poetry.
45+
# Whilst Poetry does still require pip for some tasks (such as package uninstalls),
46+
# it bundles its own copy for use as a fallback. As such we don't need to install pip
47+
# into the Poetry venv (and in fact, Poetry wouldn't use this install anyway, since
48+
# it only finds an external pip if it exists in the target venv).
49+
if ! python -m venv --without-pip "${poetry_venv_dir}"; then
5350
output::error <<-EOF
5451
Internal Error: Unable to create virtual environment for Poetry.
5552
@@ -62,8 +59,14 @@ function poetry::install_poetry() {
6259
exit 1
6360
fi
6461

62+
local bundled_pip_module_path
63+
bundled_pip_module_path="$(utils::bundled_pip_module_path "${python_home}" "${python_major_version}")"
64+
65+
# We must call the venv Python directly here, rather than relying on pip's `--python`
66+
# option, since `--python` was only added in pip v22.3, so isn't supported by the older
67+
# pip versions bundled with Python 3.9/3.10.
6568
if ! {
66-
"${poetry_venv_dir}/bin/pip" \
69+
"${poetry_venv_dir}/bin/python" "${bundled_pip_module_path}" \
6770
install \
6871
--disable-pip-version-check \
6972
--no-cache-dir \

0 commit comments

Comments
 (0)