Skip to content

Commit 0bb90f7

Browse files
authored
Work around Pipenv bug when using --system (#1842)
After moving Pipenv to its own virtual environment in #1840 (to fix leaking Pipenv's dependencies into the app environment), apps that explicitly depend on a package that happen to also be a Pipenv dependency were seeing `ModuleNotFoundError` failures. For example: ``` ModuleNotFoundError: No module named 'certifi' ``` Or: ``` ModuleNotFoundError: No module named 'packaging' ``` It appears that Pipenv's `--system` feature has a bug whereby it sees its own dependencies (installed in its own environment) as already installed (even though they aren't actually installed in the app environment), so incorrectly skips installing them. In general, it seems Pipenv's support for `--system` is pretty buggy (for example, it doesn't work with `pipenv run` either): https://github.com/pypa/pipenv/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22--system%20flag%22 The classic Python buildpack doesn't currently use virtual environments (since it installs a dedicated Python install for the app, that's already separate from system Python), and switching to them would be a significant change that may cause other types of breakage (for example, to apps that hardcode the path to Python). As such for now, we need to continue to use `pipenv install --system` (as the buildpack has done for some time), but I have found the bug can be worked around if we set `VIRTUAL_ENV` to the Python install location, to trick Pipenv into thinking it's operating in a virtual environment. The Pipenv tests have been updated to confirm that an explicit `certifi` install now works. GUS-W-19118553.
1 parent 14f2d55 commit 0bb90f7

File tree

6 files changed

+33
-1
lines changed

6 files changed

+33
-1
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+
- Work around a Pipenv bug when using `--system`, that causes packages to not be installed correctly if they are also a dependency of Pipenv (such as `certifi` ). ([#1842](https://github.com/heroku/heroku-buildpack-python/pull/1842))
56

67
## [v292] - 2025-07-23
78

lib/pipenv.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,29 @@ function pipenv::install_pipenv() {
9393
export PATH="${pipenv_bin_dir}:${PATH}"
9494
# Force Pipenv to manage the system Python site-packages instead of using venvs.
9595
export PIPENV_SYSTEM="1"
96+
# Hide Pipenv's notice about finding/using an existing virtual environment.
97+
export PIPENV_VERBOSITY="-1"
98+
# Work around a Pipenv bug when using `--system`, whereby it doesn't correctly install
99+
# dependencies that happen to also be a dependency of Pipenv (such as `certifi`).
100+
# In general Pipenv's support for its `--system` mode seems very buggy. Longer term we
101+
# should explore moving to venvs, however, that will need to be coordinated across all
102+
# package managers and also change paths for Python which could break other use cases.
103+
export VIRTUAL_ENV="${python_home}"
96104

97105
# Set the same env vars in the environment used by later buildpacks.
98106
cat >>"${export_file}" <<-EOF
99107
export PATH="${pipenv_bin_dir}:\${PATH}"
100108
export PIPENV_SYSTEM="1"
109+
export PIPENV_VERBOSITY="-1"
110+
export VIRTUAL_ENV="${python_home}"
101111
EOF
102112

103113
# And the environment used at app run-time.
104114
cat >>"${profile_d_file}" <<-EOF
105115
export PATH="${pipenv_bin_dir}:\${PATH}"
106116
export PIPENV_SYSTEM="1"
117+
export PIPENV_VERBOSITY="-1"
118+
export VIRTUAL_ENV="${python_home}"
107119
EOF
108120
}
109121

spec/fixtures/pipenv_basic/Pipfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ verify_ssl = true
44
name = "pypi"
55

66
[packages]
7+
certifi = "*"
78
typing-extensions = "*"
89

910
[dev-packages]

spec/fixtures/pipenv_basic/Pipfile.lock

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spec/hatchet/ci_spec.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,18 +104,22 @@
104104
LIBRARY_PATH=/app/.heroku/python/lib
105105
PATH=/app/.heroku/python/pipenv/bin:/app/.heroku/python/bin::/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/app/.sprettur/bin/
106106
PIPENV_SYSTEM=1
107+
PIPENV_VERBOSITY=-1
107108
PKG_CONFIG_PATH=/app/.heroku/python/lib/pkg-config
108109
PYTHONUNBUFFERED=1
110+
VIRTUAL_ENV=/app/.heroku/python
109111
-----> Inline app detected
110112
LANG=en_US.UTF-8
111113
LD_LIBRARY_PATH=/app/.heroku/python/lib
112114
LIBRARY_PATH=/app/.heroku/python/lib
113115
PATH=/app/.heroku/python/bin:/app/.heroku/python/pipenv/bin:/usr/local/bin:/usr/bin:/bin:/app/.sprettur/bin/
114116
PIPENV_SYSTEM=1
117+
PIPENV_VERBOSITY=-1
115118
PYTHONHASHSEED=random
116119
PYTHONHOME=/app/.heroku/python
117120
PYTHONPATH=/app
118121
PYTHONUNBUFFERED=true
122+
VIRTUAL_ENV=/app/.heroku/python
119123
-----> No test-setup command provided. Skipping.
120124
-----> Running test command `./bin/print-env-vars.sh && pytest --version`...
121125
CI=true
@@ -127,10 +131,12 @@
127131
LIBRARY_PATH=/app/.heroku/python/lib
128132
PATH=/app/.heroku/python/bin:/app/.heroku/python/pipenv/bin:/usr/local/bin:/usr/bin:/bin:/app/.sprettur/bin/:/app/.sprettur/bin/
129133
PIPENV_SYSTEM=1
134+
PIPENV_VERBOSITY=-1
130135
PYTHONHASHSEED=random
131136
PYTHONHOME=/app/.heroku/python
132137
PYTHONPATH=/app
133138
PYTHONUNBUFFERED=true
139+
VIRTUAL_ENV=/app/.heroku/python
134140
WEB_CONCURRENCY=5
135141
pytest .+
136142
-----> test command `./bin/print-env-vars.sh && pytest --version` completed successfully

spec/hatchet/pipenv_spec.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@
2222
remote: LIBRARY_PATH=/app/.heroku/python/lib
2323
remote: PATH=/app/.heroku/python/bin:/app/.heroku/python/pipenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
2424
remote: PIPENV_SYSTEM=1
25+
remote: PIPENV_VERBOSITY=-1
2526
remote: PYTHONHASHSEED=random
2627
remote: PYTHONHOME=/app/.heroku/python
2728
remote: PYTHONPATH=/app
2829
remote: PYTHONUNBUFFERED=true
30+
remote: VIRTUAL_ENV=/app/.heroku/python
2931
remote:
3032
remote: \\['',
3133
remote: '/app',
@@ -37,6 +39,7 @@
3739
remote: pipenv, version #{PIPENV_VERSION}
3840
remote: Package Version
3941
remote: ----------------- -+
42+
remote: certifi 2025.7.14
4043
remote: typing_extensions 4.12.2
4144
remote:
4245
remote: <module 'typing_extensions' from '/app/.heroku/python/lib/python3.13/site-packages/typing_extensions.py'>

0 commit comments

Comments
 (0)