1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
From: Stefano Rivera <stefanor@debian.org>
Date: Sat, 7 Oct 2017 09:38:58 +0200
Subject: Debian: Let ensurepip use the system wheels
Not the ones from the python source.
Origin: Debian cpython packaging
Last-Update: 2017-05-21
---
lib-python/3/ensurepip/__init__.py | 76 +++++++++++++++++++++++++++-----------
1 file changed, 55 insertions(+), 21 deletions(-)
diff --git a/lib-python/3/ensurepip/__init__.py b/lib-python/3/ensurepip/__init__.py
index 981534c..1854a04 100644
--- a/lib-python/3/ensurepip/__init__.py
+++ b/lib-python/3/ensurepip/__init__.py
@@ -1,3 +1,4 @@
+import glob
import os
import os.path
import sys
@@ -6,16 +7,12 @@ import tempfile
import subprocess
from importlib import resources
-from . import _bundled
-
-
__all__ = ["version", "bootstrap"]
-_SETUPTOOLS_VERSION = "58.1.0"
-_PIP_VERSION = "22.0.4"
+_PACKAGE_NAMES = ('setuptools', 'pip')
_PROJECTS = [
- ("setuptools", _SETUPTOOLS_VERSION, "py3"),
- ("pip", _PIP_VERSION, "py3"),
+ "setuptools",
+ "pip",
]
@@ -43,7 +40,19 @@ def version():
"""
Returns a string specifying the bundled version of pip.
"""
- return _PIP_VERSION
+ wheel_names = glob.glob('/usr/share/python-wheels/pip-*[.-]py3-*.whl')
+ if not wheel_names:
+ return None
+ wheel_names.sort(key=_wheel_version, reverse=True)
+ return os.path.basename(wheel_names[0]).split('-')[1]
+
+
+def _wheel_version(name):
+ """Return a tuple of a .whl's version, for sorting"""
+ name = os.path.basename(name)
+ package, version, tags = name.split('-', 2)
+ return [int(part) for part in version.split('.') if part.isdigit()]
+
def _disable_pip_configuration_settings():
# We deliberately ignore all pip environment variables
@@ -101,20 +110,44 @@ def _bootstrap(*, root=None, upgrade=False, user=False,
# omit pip and easy_install
os.environ["ENSUREPIP_OPTIONS"] = "install"
+ # Debian: The bundled wheels are useless to us because we must use ones
+ # crafted from source code in the archive. As we build the virtual
+ # environment, copy the wheels from the system location into the virtual
+ # environment, and place those wheels on sys.path.
+ def copy_wheels(wheels, destdir, paths):
+ for project in wheels:
+ wheel_names = glob.glob(
+ '/usr/share/python-wheels/{}-*[.-]py3-*.whl'.format(project))
+ if len(wheel_names) == 0:
+ raise RuntimeError('missing dependency wheel %s' % project)
+ wheel_names.sort(key=_wheel_version, reverse=True)
+ wheel_name = os.path.basename(wheel_names[0])
+ path = os.path.join('/usr/share/python-wheels', wheel_name)
+ with open(path, 'rb') as fp:
+ whl = fp.read()
+ dest = os.path.join(destdir, wheel_name)
+ with open(dest, 'wb') as fp:
+ fp.write(whl)
+ paths.append(dest)
+
with tempfile.TemporaryDirectory() as tmpdir:
+ # This directory is a "well known directory" which Debian has patched
+ # pip to look in when attempting to locate wheels to use to satisfy
+ # the dependencies that pip normally bundles but Debian has debundled.
+ # This is critically important and if this directory changes then both
+ # python-pip and python-virtualenv needs updated to match.
+ venv_wheel_dir = os.path.join(sys.prefix, 'share', 'python-wheels')
+ os.makedirs(venv_wheel_dir, exist_ok=True)
+ dependencies = [
+ os.path.basename(whl).split('-')[0]
+ for whl in glob.glob('/usr/share/python-wheels/*.whl')
+ ]
+ copy_wheels(dependencies, venv_wheel_dir, sys.path)
+
# Put our bundled wheels into a temporary directory and construct the
# additional paths that need added to sys.path
additional_paths = []
- for project, version, py_tag in _PROJECTS:
- wheel_name = "{}-{}-{}-none-any.whl".format(project, version, py_tag)
- whl = resources.read_binary(
- _bundled,
- wheel_name,
- )
- with open(os.path.join(tmpdir, wheel_name), "wb") as fp:
- fp.write(whl)
-
- additional_paths.append(os.path.join(tmpdir, wheel_name))
+ copy_wheels(_PROJECTS, tmpdir, additional_paths)
# Construct the arguments to be passed to the pip command
args = ["install", "--no-cache-dir", "--no-index", "--find-links", tmpdir]
@@ -127,7 +160,7 @@ def _bootstrap(*, root=None, upgrade=False, user=False,
if verbosity:
args += ["-" + "v" * verbosity]
- return _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
+ return _run_pip(args + _PROJECTS, additional_paths)
def _uninstall_helper(*, verbosity=0):
"""Helper to support a clean default uninstall process on Windows
@@ -141,7 +174,8 @@ def _uninstall_helper(*, verbosity=0):
return
# If the pip version doesn't match the bundled one, leave it alone
- if pip.__version__ != _PIP_VERSION:
+ # Disabled for Debian, always using the version from the python3-pip package.
+ if False: # pip.__version__ != _PIP_VERSION:
msg = ("ensurepip will only uninstall a matching version "
"({!r} installed, {!r} bundled)")
print(msg.format(pip.__version__, _PIP_VERSION), file=sys.stderr)
@@ -154,7 +188,7 @@ def _uninstall_helper(*, verbosity=0):
if verbosity:
args += ["-" + "v" * verbosity]
- return _run_pip(args + [p[0] for p in reversed(_PROJECTS)])
+ return _run_pip(args + list(reversed(_PROJECTS)))
def _main(argv=None):
|