Skip to content

Commit c43ab14

Browse files
committed
bpo-31046: Fix ensurepip script shebangs with --root
When using `python -m ensurepip` with the `--root` option for staged installations, the generated pip script contained an incorrect shebang that pointed into the staging directory. This made the installation unusable once the staging directory was removed. This commit fixes the issue by using the internal pip `--executable` option to force the shebang to point to the correct, final interpreter path. It also corrects related pathing issues: - Removes the check that incorrectly disallowed using --root and --prefix together. - Defaults the installation prefix to `/` when --root is used alone, ensuring installation occurs at the base of the staging directory. References: #17634 (comment) Signed-off-by: Matěj Cepl <mcepl@cepl.eu>
1 parent 01d546e commit c43ab14

File tree

1 file changed

+27
-8
lines changed

1 file changed

+27
-8
lines changed

Lib/ensurepip/__init__.py

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,6 @@ def _bootstrap(*, root=None, upgrade=False, user=False,
130130
131131
Note that calling this function will alter both sys.path and os.environ.
132132
"""
133-
if root is not None and prefix is not None:
134-
raise ValueError("Cannot use 'root' and 'prefix' together")
135133
if altinstall and default_pip:
136134
raise ValueError("Cannot use altinstall and default_pip together")
137135

@@ -162,17 +160,38 @@ def _bootstrap(*, root=None, upgrade=False, user=False,
162160

163161
# Construct the arguments to be passed to the pip command
164162
args = ["install", "--no-cache-dir", "--no-index", "--find-links", tmpdir]
165-
if root:
166-
args += ["--root", root]
167-
if prefix:
168-
args += ["--prefix", prefix]
169163
if upgrade:
170164
args += ["--upgrade"]
171-
if user:
172-
args += ["--user"]
173165
if verbosity:
174166
args += ["-" + "v" * verbosity]
175167

168+
        if user:
169+
            # --user is mutually exclusive with --root/--prefix,
170+
            # pip will enforce this.
171+
            args += ["--user"]
172+
        else:
173+
            # Handle installation paths.
174+
            # If --root is given but not --prefix, we default to a prefix of "/"
175+
            # so that the install happens at the root of the --root directory.
176+
            # Otherwise, pip would use the configured sys.prefix, e.g.
177+
            # /usr/local, and install into ${root}/usr/local/.
178+
            effective_prefix = prefix
179+
            if root and not prefix:
180+
                effective_prefix = "/"
181+
182+
            if root:
183+
                args += ["--root", root]
184+
185+
            if effective_prefix:
186+
                args += ["--prefix", effective_prefix]
187+
188+
                # Force the script shebang to point to the correct, final
189+
                # executable path. This is necessary when --root is used.
190+
                executable_path = (
191+
                    Path(effective_prefix) / "bin" / Path(sys.executable).name
192+
                )
193+
                args += ["--executable", os.fsdecode(executable_path)]
194+
176195
return _run_pip([*args, "pip"], [os.fsdecode(tmp_wheel_path)])
177196

178197

0 commit comments

Comments
 (0)