Skip to content

Commit 0f3ed4c

Browse files
xdegayepradyunsgerlend-aaslandZackerySpytz
authored andcommitted
bpo-31046: ensurepip does not honour the value of $(prefix)
When cross-compiling, the local Python interpreter that is used to run `ensurepip` may not have the same value of `sys.prefix` as the value of the 'prefix' variable that is set in the Makefile. With the following values used to install Python locally for a later copy to the files hierarchy owned by the 'termux' application on an Android device: DESTDIR=/tmp/android prefix=/data/data/com.termux/files/usr/local 'make install' causes ensurepip to install pip in $(DESTDIR)/usr/local instead of the expected $(DESTDIR)/$(prefix) where is installed the standard library. The attached patch fixes the problem. The patch was implemented assuming that pip uses distutils for the installation (note that setup.py also uses the --prefix option in the Makefile), but I know nothing about pip so forgive me if the patch is wrong and please just assume it is just a way to demonstrate the problem. Fixes: #75229 Fixes: https://bugs.python.org/issue31046 Co-authored-by: Pradyun Gedam <pradyunsg@gmail.com> Co-authored-by: Erlend E. Aasland <erlend.aasland@protonmail.com> Co-authored-by: Zackery Spytz <zspytz@gmail.com> References: #17634 Signed-off-by: Matěj Cepl <mcepl@cepl.eu>
1 parent 7fe51ce commit 0f3ed4c

5 files changed

Lines changed: 45 additions & 9 deletions

File tree

Doc/library/ensurepip.rst

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,11 @@ is at least as recent as the one available in ``ensurepip``, pass the
6565
By default, ``pip`` is installed into the current virtual environment
6666
(if one is active) or into the system site packages (if there is no
6767
active virtual environment). The installation location can be controlled
68-
through two additional command line options:
68+
through some additional command line options:
69+
70+
.. option:: --prefix <dir>
71+
72+
Installs ``pip`` using the given directory prefix.
6973

7074
.. option:: --root <dir>
7175

@@ -108,7 +112,7 @@ Module API
108112

109113
.. function:: bootstrap(root=None, upgrade=False, user=False, \
110114
altinstall=False, default_pip=False, \
111-
verbosity=0)
115+
verbosity=0, prefix=None)
112116

113117
Bootstraps ``pip`` into the current or designated environment.
114118

@@ -136,6 +140,12 @@ Module API
136140
*verbosity* controls the level of output to :data:`sys.stdout` from the
137141
bootstrapping operation.
138142

143+
*prefix* specifies the directory prefix to use when installing.
144+
145+
.. versionadded:: 3.14
146+
147+
The *prefix* parameter.
148+
139149
.. audit-event:: ensurepip.bootstrap root ensurepip.bootstrap
140150

141151
.. note::

Lib/ensurepip/__init__.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,25 +109,25 @@ def _disable_pip_configuration_settings():
109109

110110
def bootstrap(*, root=None, upgrade=False, user=False,
111111
altinstall=False, default_pip=False,
112-
verbosity=0):
112+
verbosity=0, prefix=None):
113113
"""
114114
Bootstrap pip into the current Python installation (or the given root
115-
directory).
115+
and directory prefix).
116116
117117
Note that calling this function will alter both sys.path and os.environ.
118118
"""
119119
# Discard the return value
120120
_bootstrap(root=root, upgrade=upgrade, user=user,
121121
altinstall=altinstall, default_pip=default_pip,
122-
verbosity=verbosity)
122+
verbosity=verbosity, prefix=prefix)
123123

124124

125125
def _bootstrap(*, root=None, upgrade=False, user=False,
126126
altinstall=False, default_pip=False,
127-
verbosity=0):
127+
verbosity=0, prefix=None):
128128
"""
129129
Bootstrap pip into the current Python installation (or the given root
130-
directory). Returns pip command status code.
130+
and directory prefix). Returns pip command status code.
131131
132132
Note that calling this function will alter both sys.path and os.environ.
133133
"""
@@ -140,6 +140,8 @@ def _bootstrap(*, root=None, upgrade=False, user=False,
140140
"to install pip."
141141
) from None
142142

143+
if root is not None and prefix is not None:
144+
raise ValueError("Cannot use 'root' and 'prefix' together")
143145
if altinstall and default_pip:
144146
raise ValueError("Cannot use altinstall and default_pip together")
145147

@@ -172,6 +174,8 @@ def _bootstrap(*, root=None, upgrade=False, user=False,
172174
args = ["install", "--no-cache-dir", "--no-index", "--find-links", tmpdir]
173175
if root:
174176
args += ["--root", root]
177+
if prefix:
178+
args += ["--prefix", prefix]
175179
if upgrade:
176180
args += ["--upgrade"]
177181
if user:
@@ -249,6 +253,11 @@ def _main(argv=None):
249253
default=None,
250254
help="Install everything relative to this alternate root directory.",
251255
)
256+
parser.add_argument(
257+
"--prefix",
258+
default=None,
259+
help="Install everything using this prefix.",
260+
)
252261
parser.add_argument(
253262
"--altinstall",
254263
action="store_true",
@@ -268,6 +277,7 @@ def _main(argv=None):
268277

269278
return _bootstrap(
270279
root=args.root,
280+
prefix=args.prefix,
271281
upgrade=args.upgrade,
272282
user=args.user,
273283
verbosity=args.verbosity,

Lib/test/test_ensurepip.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,21 @@ def test_bootstrapping_with_root(self):
121121
unittest.mock.ANY,
122122
)
123123

124+
def test_bootstrapping_with_prefix(self):
125+
ensurepip.bootstrap(prefix="/foo/bar/")
126+
self.run_pip.assert_called_once_with(
127+
[
128+
"install", "--no-cache-dir", "--no-index", "--find-links",
129+
unittest.mock.ANY, "--prefix", "/foo/bar/", "pip",
130+
],
131+
unittest.mock.ANY,
132+
)
133+
134+
def test_root_and_prefix_mutual_exclusive(self):
135+
with self.assertRaises(ValueError):
136+
ensurepip.bootstrap(root="", prefix="")
137+
self.assertFalse(self.run_pip.called)
138+
124139
def test_bootstrapping_with_user(self):
125140
ensurepip.bootstrap(user=True)
126141

Makefile.pre.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2443,7 +2443,7 @@ install: @FRAMEWORKINSTALLFIRST@ @INSTALLTARGETS@ @FRAMEWORKINSTALLLAST@
24432443
install|*) ensurepip="" ;; \
24442444
esac; \
24452445
$(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \
2446-
$$ensurepip --root=$(DESTDIR)/ ; \
2446+
$$ensurepip --prefix=$(prefix) ; \
24472447
fi
24482448

24492449
.PHONY: altinstall
@@ -2454,7 +2454,7 @@ altinstall: commoninstall
24542454
install|*) ensurepip="--altinstall" ;; \
24552455
esac; \
24562456
$(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \
2457-
$$ensurepip --root=$(DESTDIR)/ ; \
2457+
$$ensurepip --prefix=$(prefix) ; \
24582458
fi
24592459

24602460
.PHONY: commoninstall
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
A directory prefix can now be specified when using :mod:`ensurepip`.

0 commit comments

Comments
 (0)