Skip to content

Commit b576e23

Browse files
authored
Fix using Poetry with outdated Python patch versions (#1687)
The existing Poetry bootstrap process added in #1682 used the pip wheel bundled within the Python stdlib. This required use of pip's `--python` option, which was added to pip in v22.3 in 2022. All of the major Python versions we support have been updated to that pip version or newer, however, the older patch releases of some of those major Python versions can contain pip versions that are older (for example, whilst latest Python 3.9.x bundles pip v23.0.1, Python 3.9.0 bundles pip v20.2.1). Previously, using those older patch versions would result in: ``` -----> Installing Poetry 1.8.4 Usage: pip <command> [options] no such option: --python ! Error: Unable to install Poetry. ``` Whilst we strongly recommend users upgrade to newer patch releases (since older versions are missing security updates and so likely insecure), we still want to support using Poetry on these versions, so the I've adjusted the bootstrap process to no longer use `--python` to prevent that error.
1 parent 158def0 commit b576e23

File tree

7 files changed

+66
-15
lines changed

7 files changed

+66
-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+
- Fixed Poetry installation when using outdated patch versions of Python 3.8, 3.9 and 3.10, whose bundled pip doesn't support the `--python` option. ([#1687](https://github.com/heroku/heroku-buildpack-python/pull/1687))
56

67
## [v264] - 2024-11-06
78

bin/compile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ case "${package_manager}" in
168168
pipenv::install_pipenv
169169
;;
170170
poetry)
171-
poetry::install_poetry "${python_home}" "${CACHE_DIR}" "${EXPORT_PATH}"
171+
poetry::install_poetry "${CACHE_DIR}" "${EXPORT_PATH}"
172172
;;
173173
*)
174174
utils::abort_internal_error "Unhandled package manager: ${package_manager}"

lib/poetry.sh

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

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

1413
# We store Poetry in the build cache, since we only need it during the build.
1514
local poetry_root="${cache_dir}/.heroku/python-poetry"
@@ -39,19 +38,17 @@ function poetry::install_poetry() {
3938
# The Poetry directory will already exist in the relocated cache case mentioned above.
4039
rm -rf "${poetry_root}"
4140

42-
python -m venv --without-pip "${poetry_venv_dir}"
43-
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-
local bundled_pip_module_path
50-
bundled_pip_module_path="$(utils::bundled_pip_module_path "${python_home}")"
41+
# We can't use the pip wheel bundled within Python's standard library to install Poetry
42+
# (which would allow us to use `--without-pip` here to skip the pip install), since it
43+
# requires using the `--python` option, which was only added in pip v22.3. And whilst
44+
# all major Python versions we support now bundled a newer pip than that, some apps
45+
# are still using outdated patch releases of those Python versions, whose bundled pip
46+
# can be older (for example Python 3.9.0 ships with pip v20.2.1). Once Python 3.10 EOLs
47+
# we can switch back to the previous approach since Python 3.11.0 ships with pip v22.3.
48+
python -m venv "${poetry_venv_dir}"
5149

5250
if ! {
53-
python "${bundled_pip_module_path}" \
54-
--python "${poetry_venv_dir}" \
51+
"${poetry_venv_dir}/bin/pip" \
5552
install \
5653
--disable-pip-version-check \
5754
--no-cache-dir \
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.9.0

spec/fixtures/poetry_oldest_python/poetry.lock

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[tool.poetry]
2+
package-mode = false
3+
4+
[tool.poetry.dependencies]
5+
python = "^3.9"
6+
typing-extensions = "*"

spec/hatchet/poetry_spec.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,35 @@
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.
190+
context 'when using the oldest supported Python version' do
191+
let(:app) { Hatchet::Runner.new('spec/fixtures/poetry_oldest_python') }
192+
193+
it 'installs successfully' do
194+
app.deploy do |app|
195+
expect(clean_output(app.output)).to include(<<~OUTPUT)
196+
remote: -----> Python app detected
197+
remote: -----> Using Python 3.9.0 specified in .python-version
198+
remote: -----> Installing Python 3.9.0
199+
remote:
200+
remote: ! Warning: A Python security update is available!
201+
remote: !
202+
remote: ! Upgrade as soon as possible to: Python #{LATEST_PYTHON_3_9}
203+
remote: ! See: https://devcenter.heroku.com/articles/python-runtimes
204+
remote:
205+
remote: -----> Installing Poetry #{POETRY_VERSION}
206+
remote: -----> Installing dependencies using 'poetry install --sync --only main'
207+
remote: Installing dependencies from lock file
208+
remote:
209+
remote: Package operations: 1 install, 0 updates, 0 removals
210+
remote:
211+
remote: - Installing typing-extensions (4.12.2)
212+
OUTPUT
213+
end
214+
end
215+
end
216+
188217
context 'when poetry.lock is out of sync with pyproject.toml' do
189218
let(:app) { Hatchet::Runner.new('spec/fixtures/poetry_lockfile_out_of_sync', allow_failure: true) }
190219

0 commit comments

Comments
 (0)