-
-
Notifications
You must be signed in to change notification settings - Fork 34.3k
Description
Bug description:
Until and in 3.12, ensurepip stored the sysconfig.get_config_var('WHEEL_PKG_DIR') result verbatim as a string in _WHEEL_PKG_DIR, and used os functionality to list wheels in the specified directory.
Since 3.13 (tested on 3.14 but I also reviewed the 3.13 library code), the config value (when not None) is normalized to a pathlib.Path, and the .glob method of that is used instead.
This causes a different behaviour when the returned value (as is the case for my local source builds) is an empty string ('', not None):
>>> import os
>>> os.listdir('')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: ''
>>> from pathlib import Path
>>> Path('')
PosixPath('.')
>>> Path('').glob('*')
<generator object Path.glob at 0x7c06678cc590>Therefore, ensurepip will now bootstrap from the process' CWD, if it contains a suitable pip wheel. And a renamed file that is not a valid pip wheel can theoretically just crash:
$ touch pip-is-not-in-here.whl
$ py3.14 -m ensurepip
Traceback (most recent call last):
File "<string>", line 6, in <module>
runpy.run_module("pip", run_name="__main__", alter_sys=True)
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<frozen runpy>", line 222, in run_module
File "<frozen runpy>", line 142, in _get_module_details
ImportError: No module named pip
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "/opt/python/standard/lib/python3.14/ensurepip/__main__.py", line 5, in <module>
sys.exit(ensurepip._main())
~~~~~~~~~~~~~~~^^
File "/opt/python/standard/lib/python3.14/ensurepip/__init__.py", line 257, in _main
return _bootstrap(
root=args.root,
...<4 lines>...
default_pip=args.default_pip,
)
File "/opt/python/standard/lib/python3.14/ensurepip/__init__.py", line 172, in _bootstrap
return _run_pip([*args, "pip"], [os.fsdecode(tmp_wheel_path)])
File "/opt/python/standard/lib/python3.14/ensurepip/__init__.py", line 87, in _run_pip
return subprocess.run(cmd, check=True).returncode
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
File "/opt/python/standard/lib/python3.14/subprocess.py", line 577, in run
raise CalledProcessError(retcode, process.args,
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['/usr/local/bin/py3.14', '-W', 'ignore::DeprecationWarning', '-c', '\nimport runpy\nimport sys\nsys.path = [\'/tmp/tmpc9p5g7z_/pip-is-not-in-here.whl\'] + sys.path\nsys.argv[1:] = [\'install\', \'--no-cache-dir\', \'--no-index\', \'--find-links\', \'/tmp/tmpc9p5g7z_\', \'pip\']\nrunpy.run_module("pip", run_name="__main__", alter_sys=True)\n']' returned non-zero exit status 1.
Actually this behaviour is useful for me (I want to test bootstrapping some modified versions of pip), but it does seem to represent an un-documented change that could break things for someone else.
(Actually I wonder if it is really os.listdir('') that should have been changed forever ago. After all, a '' entry in sys.path does work!)
CPython versions tested on:
3.14
Operating systems tested on:
No response