Skip to content

Commit 01d546e

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 747d390 commit 01d546e

File tree

5 files changed

+45
-9
lines changed

5 files changed

+45
-9
lines changed

Doc/library/ensurepip.rst

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

6670
.. option:: --root <dir>
6771

@@ -104,7 +108,7 @@ Module API
104108

105109
.. function:: bootstrap(root=None, upgrade=False, user=False, \
106110
altinstall=False, default_pip=False, \
107-
verbosity=0)
111+
verbosity=0, prefix=None)
108112

109113
Bootstraps ``pip`` into the current or designated environment.
110114

@@ -132,6 +136,12 @@ Module API
132136
*verbosity* controls the level of output to :data:`sys.stdout` from the
133137
bootstrapping operation.
134138

139+
*prefix* specifies the directory prefix to use when installing.
140+
141+
.. versionadded:: 3.14
142+
143+
The *prefix* parameter.
144+
135145
.. audit-event:: ensurepip.bootstrap root ensurepip.bootstrap
136146

137147
.. note::

Lib/ensurepip/__init__.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,28 +108,30 @@ def _disable_pip_configuration_settings():
108108

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

123123

124124
def _bootstrap(*, root=None, upgrade=False, user=False,
125125
altinstall=False, default_pip=False,
126-
verbosity=0):
126+
verbosity=0, prefix=None):
127127
"""
128128
Bootstrap pip into the current Python installation (or the given root
129-
directory). Returns pip command status code.
129+
and directory prefix). Returns pip command status code.
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")
133135
if altinstall and default_pip:
134136
raise ValueError("Cannot use altinstall and default_pip together")
135137

@@ -162,6 +164,8 @@ def _bootstrap(*, root=None, upgrade=False, user=False,
162164
args = ["install", "--no-cache-dir", "--no-index", "--find-links", tmpdir]
163165
if root:
164166
args += ["--root", root]
167+
if prefix:
168+
args += ["--prefix", prefix]
165169
if upgrade:
166170
args += ["--upgrade"]
167171
if user:
@@ -237,6 +241,11 @@ def _main(argv=None):
237241
default=None,
238242
help="Install everything relative to this alternate root directory.",
239243
)
244+
parser.add_argument(
245+
"--prefix",
246+
default=None,
247+
help="Install everything using this prefix.",
248+
)
240249
parser.add_argument(
241250
"--altinstall",
242251
action="store_true",
@@ -256,6 +265,7 @@ def _main(argv=None):
256265

257266
return _bootstrap(
258267
root=args.root,
268+
prefix=args.prefix,
259269
upgrade=args.upgrade,
260270
user=args.user,
261271
verbosity=args.verbosity,

Lib/test/test_ensurepip.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,21 @@ def test_bootstrapping_with_root(self):
100100
unittest.mock.ANY,
101101
)
102102

103+
def test_bootstrapping_with_prefix(self):
104+
ensurepip.bootstrap(prefix="/foo/bar/")
105+
self.run_pip.assert_called_once_with(
106+
[
107+
"install", "--no-cache-dir", "--no-index", "--find-links",
108+
unittest.mock.ANY, "--prefix", "/foo/bar/", "pip",
109+
],
110+
unittest.mock.ANY,
111+
)
112+
113+
def test_root_and_prefix_mutual_exclusive(self):
114+
with self.assertRaises(ValueError):
115+
ensurepip.bootstrap(root="", prefix="")
116+
self.assertFalse(self.run_pip.called)
117+
103118
def test_bootstrapping_with_user(self):
104119
ensurepip.bootstrap(user=True)
105120

Makefile.pre.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2336,7 +2336,7 @@ install: @FRAMEWORKINSTALLFIRST@ @INSTALLTARGETS@ @FRAMEWORKINSTALLLAST@
23362336
install|*) ensurepip="" ;; \
23372337
esac; \
23382338
$(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \
2339-
$$ensurepip --root=$(DESTDIR)/ ; \
2339+
$$ensurepip --prefix=$(prefix) ; \
23402340
fi
23412341

23422342
.PHONY: altinstall
@@ -2347,7 +2347,7 @@ altinstall: commoninstall
23472347
install|*) ensurepip="--altinstall" ;; \
23482348
esac; \
23492349
$(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \
2350-
$$ensurepip --root=$(DESTDIR)/ ; \
2350+
$$ensurepip --prefix=$(prefix) ; \
23512351
fi
23522352

23532353
.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)