5
5
import sys
6
6
import sysconfig
7
7
import tempfile
8
+ from contextlib import suppress
9
+ from functools import cache
8
10
from importlib import resources
9
11
10
12
11
13
__all__ = ["version" , "bootstrap" ]
12
- _PACKAGE_NAMES = ('pip' ,)
13
14
_PIP_VERSION = "23.2.1"
14
- _PROJECTS = [
15
- ("pip" , _PIP_VERSION , "py3" ),
16
- ]
17
15
18
16
# Packages bundled in ensurepip._bundled have wheel_name set.
19
17
# Packages from WHEEL_PKG_DIR have wheel_path set.
27
25
_WHEEL_PKG_DIR = sysconfig .get_config_var ('WHEEL_PKG_DIR' )
28
26
29
27
30
- def _find_packages (path ):
31
- packages = {}
28
+ def _find_packages (path : str | None ) -> _Package :
29
+ if path is None :
30
+ raise LookupError (
31
+ 'The compile-time `WHEEL_PKG_DIR` is unset so there is '
32
+ 'no place for looking up the wheels.' ,
33
+ )
34
+
32
35
try :
33
36
filenames = os .listdir (path )
34
37
except OSError :
@@ -38,41 +41,39 @@ def _find_packages(path):
38
41
# of the same package, but don't attempt to implement correct version
39
42
# comparison since this case should not happen.
40
43
filenames = sorted (filenames )
44
+ pip_pkg = None
41
45
for filename in filenames :
42
46
# filename is like 'pip-21.2.4-py3-none-any.whl'
43
47
if not filename .endswith (".whl" ):
44
48
continue
45
- for name in _PACKAGE_NAMES :
46
- prefix = name + '-'
47
- if filename .startswith (prefix ):
48
- break
49
- else :
49
+ if not filename .startswith ('pip-' ):
50
50
continue
51
51
52
52
# Extract '21.2.4' from 'pip-21.2.4-py3-none-any.whl'
53
- version = filename .removeprefix (prefix ).partition ('-' )[0 ]
53
+ discovered_pip_pkg_version = filename .removeprefix (
54
+ 'pip-' ,
55
+ ).partition ('-' )[0 ]
54
56
wheel_path = os .path .join (path , filename )
55
- packages [name ] = _Package (version , None , wheel_path )
56
- return packages
57
+ pip_pkg = _Package (discovered_pip_pkg_version , None , wheel_path )
58
+
59
+ if pip_pkg is None :
60
+ raise LookupError (
61
+ '`WHEEL_PKG_DIR` does not contain any wheel files for `pip`.' ,
62
+ )
63
+
64
+ return pip_pkg
57
65
58
66
59
- def _get_packages ():
60
- global _PACKAGES , _WHEEL_PKG_DIR
61
- if _PACKAGES is not None :
62
- return _PACKAGES
67
+ @ cache
68
+ def _get_usable_pip_package () -> _Package :
69
+ wheel_name = f"pip- { _PIP_VERSION } -py3-none-any.whl"
70
+ pip_pkg = _Package ( _PIP_VERSION , wheel_name , None )
63
71
64
- packages = {}
65
- for name , version , py_tag in _PROJECTS :
66
- wheel_name = f"{ name } -{ version } -{ py_tag } -none-any.whl"
67
- packages [name ] = _Package (version , wheel_name , None )
68
- if _WHEEL_PKG_DIR :
69
- dir_packages = _find_packages (_WHEEL_PKG_DIR )
70
- # only used the wheel package directory if all packages are found there
71
- if all (name in dir_packages for name in _PACKAGE_NAMES ):
72
- packages = dir_packages
73
- _PACKAGES = packages
74
- return packages
75
- _PACKAGES = None
72
+ with suppress (LookupError ):
73
+ # only use the wheel package directory if all packages are found there
74
+ pip_pkg = _find_packages (_WHEEL_PKG_DIR )
75
+
76
+ return pip_pkg
76
77
77
78
78
79
def _run_pip (args , additional_paths = None ):
@@ -105,7 +106,7 @@ def version():
105
106
"""
106
107
Returns a string specifying the bundled version of pip.
107
108
"""
108
- return _get_packages ()[ 'pip' ] .version
109
+ return _get_usable_pip_package () .version
109
110
110
111
111
112
def _disable_pip_configuration_settings ():
@@ -167,24 +168,21 @@ def _bootstrap(*, root=None, upgrade=False, user=False,
167
168
with tempfile .TemporaryDirectory () as tmpdir :
168
169
# Put our bundled wheels into a temporary directory and construct the
169
170
# additional paths that need added to sys.path
170
- additional_paths = []
171
- for name , package in _get_packages ().items ():
172
- if package .wheel_name :
173
- # Use bundled wheel package
174
- wheel_name = package .wheel_name
175
- wheel_path = resources .files ("ensurepip" ) / "_bundled" / wheel_name
176
- whl = wheel_path .read_bytes ()
177
- else :
178
- # Use the wheel package directory
179
- with open (package .wheel_path , "rb" ) as fp :
180
- whl = fp .read ()
181
- wheel_name = os .path .basename (package .wheel_path )
182
-
183
- filename = os .path .join (tmpdir , wheel_name )
184
- with open (filename , "wb" ) as fp :
185
- fp .write (whl )
186
-
187
- additional_paths .append (filename )
171
+ package = _get_usable_pip_package ()
172
+ if package .wheel_name :
173
+ # Use bundled wheel package
174
+ wheel_name = package .wheel_name
175
+ wheel_path = resources .files ("ensurepip" ) / "_bundled" / wheel_name
176
+ whl = wheel_path .read_bytes ()
177
+ else :
178
+ # Use the wheel package directory
179
+ with open (package .wheel_path , "rb" ) as fp :
180
+ whl = fp .read ()
181
+ wheel_name = os .path .basename (package .wheel_path )
182
+
183
+ filename = os .path .join (tmpdir , wheel_name )
184
+ with open (filename , "wb" ) as fp :
185
+ fp .write (whl )
188
186
189
187
# Construct the arguments to be passed to the pip command
190
188
args = ["install" , "--no-cache-dir" , "--no-index" , "--find-links" , tmpdir ]
@@ -197,7 +195,7 @@ def _bootstrap(*, root=None, upgrade=False, user=False,
197
195
if verbosity :
198
196
args += ["-" + "v" * verbosity ]
199
197
200
- return _run_pip ([* args , * _PACKAGE_NAMES ], additional_paths )
198
+ return _run_pip ([* args , "pip" ], [ filename ] )
201
199
202
200
def _uninstall_helper (* , verbosity = 0 ):
203
201
"""Helper to support a clean default uninstall process on Windows
@@ -227,7 +225,7 @@ def _uninstall_helper(*, verbosity=0):
227
225
if verbosity :
228
226
args += ["-" + "v" * verbosity ]
229
227
230
- return _run_pip ([* args , * reversed ( _PACKAGE_NAMES ) ])
228
+ return _run_pip ([* args , "pip" ])
231
229
232
230
233
231
def _main (argv = None ):
0 commit comments