bpo-31351: Set return code in ensurepip when pip fails (GH-3626)
Previously ensurepip would always report success, even if the pip installation failed.
This commit is contained in:
parent
a96c96f5da
commit
9adda0cdf8
|
@ -78,6 +78,9 @@ options:
|
|||
|
||||
Providing both of the script selection options will trigger an exception.
|
||||
|
||||
.. versionchanged:: 3.7.0
|
||||
The exit status is non-zero if the command fails.
|
||||
|
||||
|
||||
Module API
|
||||
----------
|
||||
|
|
|
@ -25,7 +25,7 @@ def _run_pip(args, additional_paths=None):
|
|||
|
||||
# Install the bundled software
|
||||
import pip
|
||||
pip.main(args)
|
||||
return pip.main(args)
|
||||
|
||||
|
||||
def version():
|
||||
|
@ -53,6 +53,21 @@ def bootstrap(*, root=None, upgrade=False, user=False,
|
|||
Bootstrap pip into the current Python installation (or the given root
|
||||
directory).
|
||||
|
||||
Note that calling this function will alter both sys.path and os.environ.
|
||||
"""
|
||||
# Discard the return value
|
||||
_bootstrap(root=root, upgrade=upgrade, user=user,
|
||||
altinstall=altinstall, default_pip=default_pip,
|
||||
verbosity=verbosity)
|
||||
|
||||
|
||||
def _bootstrap(*, root=None, upgrade=False, user=False,
|
||||
altinstall=False, default_pip=False,
|
||||
verbosity=0):
|
||||
"""
|
||||
Bootstrap pip into the current Python installation (or the given root
|
||||
directory). Returns pip command status code.
|
||||
|
||||
Note that calling this function will alter both sys.path and os.environ.
|
||||
"""
|
||||
if altinstall and default_pip:
|
||||
|
@ -99,7 +114,7 @@ def bootstrap(*, root=None, upgrade=False, user=False,
|
|||
if verbosity:
|
||||
args += ["-" + "v" * verbosity]
|
||||
|
||||
_run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
|
||||
return _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
|
||||
|
||||
def _uninstall_helper(*, verbosity=0):
|
||||
"""Helper to support a clean default uninstall process on Windows
|
||||
|
@ -126,7 +141,7 @@ def _uninstall_helper(*, verbosity=0):
|
|||
if verbosity:
|
||||
args += ["-" + "v" * verbosity]
|
||||
|
||||
_run_pip(args + [p[0] for p in reversed(_PROJECTS)])
|
||||
return _run_pip(args + [p[0] for p in reversed(_PROJECTS)])
|
||||
|
||||
|
||||
def _main(argv=None):
|
||||
|
@ -180,7 +195,7 @@ def _main(argv=None):
|
|||
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
bootstrap(
|
||||
return _bootstrap(
|
||||
root=args.root,
|
||||
upgrade=args.upgrade,
|
||||
user=args.user,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import ensurepip
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
ensurepip._main()
|
||||
sys.exit(ensurepip._main())
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import argparse
|
||||
import ensurepip
|
||||
import sys
|
||||
|
||||
|
||||
def _main(argv=None):
|
||||
|
@ -23,8 +24,8 @@ def _main(argv=None):
|
|||
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
ensurepip._uninstall_helper(verbosity=args.verbosity)
|
||||
return ensurepip._uninstall_helper(verbosity=args.verbosity)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
_main()
|
||||
sys.exit(_main())
|
||||
|
|
|
@ -20,6 +20,7 @@ class EnsurepipMixin:
|
|||
def setUp(self):
|
||||
run_pip_patch = unittest.mock.patch("ensurepip._run_pip")
|
||||
self.run_pip = run_pip_patch.start()
|
||||
self.run_pip.return_value = 0
|
||||
self.addCleanup(run_pip_patch.stop)
|
||||
|
||||
# Avoid side effects on the actual os module
|
||||
|
@ -255,7 +256,7 @@ class TestBootstrappingMainFunction(EnsurepipMixin, unittest.TestCase):
|
|||
self.assertFalse(self.run_pip.called)
|
||||
|
||||
def test_basic_bootstrapping(self):
|
||||
ensurepip._main([])
|
||||
exit_code = ensurepip._main([])
|
||||
|
||||
self.run_pip.assert_called_once_with(
|
||||
[
|
||||
|
@ -267,6 +268,13 @@ class TestBootstrappingMainFunction(EnsurepipMixin, unittest.TestCase):
|
|||
|
||||
additional_paths = self.run_pip.call_args[0][1]
|
||||
self.assertEqual(len(additional_paths), 2)
|
||||
self.assertEqual(exit_code, 0)
|
||||
|
||||
def test_bootstrapping_error_code(self):
|
||||
self.run_pip.return_value = 2
|
||||
exit_code = ensurepip._main([])
|
||||
self.assertEqual(exit_code, 2)
|
||||
|
||||
|
||||
class TestUninstallationMainFunction(EnsurepipMixin, unittest.TestCase):
|
||||
|
||||
|
@ -280,7 +288,7 @@ class TestUninstallationMainFunction(EnsurepipMixin, unittest.TestCase):
|
|||
|
||||
def test_basic_uninstall(self):
|
||||
with fake_pip():
|
||||
ensurepip._uninstall._main([])
|
||||
exit_code = ensurepip._uninstall._main([])
|
||||
|
||||
self.run_pip.assert_called_once_with(
|
||||
[
|
||||
|
@ -289,6 +297,13 @@ class TestUninstallationMainFunction(EnsurepipMixin, unittest.TestCase):
|
|||
]
|
||||
)
|
||||
|
||||
self.assertEqual(exit_code, 0)
|
||||
|
||||
def test_uninstall_error_code(self):
|
||||
with fake_pip():
|
||||
self.run_pip.return_value = 2
|
||||
exit_code = ensurepip._uninstall._main([])
|
||||
self.assertEqual(exit_code, 2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
python -m ensurepip now exits with non-zero exit code if pip bootstrapping
|
||||
has failed.
|
Loading…
Reference in New Issue