55import sys
66import sysconfig
77import tempfile
8+ from contextlib import suppress
9+ from functools import cache
810from importlib import resources
911
1012
1113__all__ = ["version" , "bootstrap" ]
12- _PACKAGE_NAMES = ('pip' ,)
1314_PIP_VERSION = "23.2.1"
14- _PROJECTS = [
15- ("pip" , _PIP_VERSION , "py3" ),
16- ]
1715
1816# Packages bundled in ensurepip._bundled have wheel_name set.
1917# Packages from WHEEL_PKG_DIR have wheel_path set.
2725_WHEEL_PKG_DIR = sysconfig .get_config_var ('WHEEL_PKG_DIR' )
2826
2927
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+
3235 try :
3336 filenames = os .listdir (path )
3437 except OSError :
@@ -38,41 +41,39 @@ def _find_packages(path):
3841 # of the same package, but don't attempt to implement correct version
3942 # comparison since this case should not happen.
4043 filenames = sorted (filenames )
44+ pip_pkg = None
4145 for filename in filenames :
4246 # filename is like 'pip-21.2.4-py3-none-any.whl'
4347 if not filename .endswith (".whl" ):
4448 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-' ):
5050 continue
5151
5252 # 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 ]
5456 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
5765
5866
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 )
6371
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
7677
7778
7879def _run_pip (args , additional_paths = None ):
@@ -105,7 +106,7 @@ def version():
105106 """
106107 Returns a string specifying the bundled version of pip.
107108 """
108- return _get_packages ()[ 'pip' ] .version
109+ return _get_usable_pip_package () .version
109110
110111
111112def _disable_pip_configuration_settings ():
@@ -167,24 +168,21 @@ def _bootstrap(*, root=None, upgrade=False, user=False,
167168 with tempfile .TemporaryDirectory () as tmpdir :
168169 # Put our bundled wheels into a temporary directory and construct the
169170 # 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 )
188186
189187 # Construct the arguments to be passed to the pip command
190188 args = ["install" , "--no-cache-dir" , "--no-index" , "--find-links" , tmpdir ]
@@ -197,7 +195,7 @@ def _bootstrap(*, root=None, upgrade=False, user=False,
197195 if verbosity :
198196 args += ["-" + "v" * verbosity ]
199197
200- return _run_pip ([* args , * _PACKAGE_NAMES ], additional_paths )
198+ return _run_pip ([* args , "pip" ], [ filename ] )
201199
202200def _uninstall_helper (* , verbosity = 0 ):
203201 """Helper to support a clean default uninstall process on Windows
@@ -227,7 +225,7 @@ def _uninstall_helper(*, verbosity=0):
227225 if verbosity :
228226 args += ["-" + "v" * verbosity ]
229227
230- return _run_pip ([* args , * reversed ( _PACKAGE_NAMES ) ])
228+ return _run_pip ([* args , "pip" ])
231229
232230
233231def _main (argv = None ):
0 commit comments