diff options
author | Igor Filatov <iafilatov@users.noreply.github.com> | 2017-09-25 04:03:24 +0300 |
---|---|---|
committer | Nick Coghlan <ncoghlan@gmail.com> | 2017-09-25 11:03:24 +1000 |
commit | cf7197ae43767c4346864e5b41246f628edd9b51 (patch) | |
tree | 31b2ad79968e1509a5b09ced5fc344346700640d | |
parent | da86874a3d8f882d6aedd882b2e27f59b59d6798 (diff) | |
download | cpython-git-cf7197ae43767c4346864e5b41246f628edd9b51.tar.gz |
[2.7] bpo-31351: Set return code in ensurepip when pip fails (GH-3734)
Previously ensurepip would always report success, even if the
pip installation failed.
(cherry picked from commit 9adda0cdf89432386b7a04444a6199b580d287a1)
-rw-r--r-- | Doc/library/ensurepip.rst | 3 | ||||
-rw-r--r-- | Lib/ensurepip/__init__.py | 24 | ||||
-rw-r--r-- | Lib/ensurepip/__main__.py | 3 | ||||
-rw-r--r-- | Lib/ensurepip/_uninstall.py | 5 | ||||
-rw-r--r-- | Lib/test/test_ensurepip.py | 19 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2017-09-17-15-24-25.bpo-31351.yQdKv-.rst | 2 |
6 files changed, 46 insertions, 10 deletions
diff --git a/Doc/library/ensurepip.rst b/Doc/library/ensurepip.rst index a6358e44b1..b6f7120947 100644 --- a/Doc/library/ensurepip.rst +++ b/Doc/library/ensurepip.rst @@ -76,6 +76,9 @@ options: * ``--no-default-pip``: if a non-default installation is request, the ``pip`` script will *not* be installed. +.. versionchanged:: 2.7.15 + The exit status is non-zero if the command fails. + Module API ---------- diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py index c2abed84ef..ea2a5e6348 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -29,7 +29,7 @@ def _run_pip(args, additional_paths=None): # Install the bundled software import pip - pip.main(args) + return pip.main(args) def version(): @@ -60,6 +60,21 @@ def bootstrap(root=None, upgrade=False, user=False, 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=True, + 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: raise ValueError("Cannot use altinstall and default_pip together") @@ -105,11 +120,10 @@ 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) finally: shutil.rmtree(tmpdir, ignore_errors=True) - def _uninstall_helper(verbosity=0): """Helper to support a clean default uninstall process on Windows @@ -135,7 +149,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): @@ -196,7 +210,7 @@ def _main(argv=None): args = parser.parse_args(argv) - bootstrap( + return _bootstrap( root=args.root, upgrade=args.upgrade, user=args.user, diff --git a/Lib/ensurepip/__main__.py b/Lib/ensurepip/__main__.py index 77527d7a35..03eef0dd94 100644 --- a/Lib/ensurepip/__main__.py +++ b/Lib/ensurepip/__main__.py @@ -1,4 +1,5 @@ import ensurepip +import sys if __name__ == "__main__": - ensurepip._main() + sys.exit(ensurepip._main()) diff --git a/Lib/ensurepip/_uninstall.py b/Lib/ensurepip/_uninstall.py index 750365ec4d..b257904328 100644 --- a/Lib/ensurepip/_uninstall.py +++ b/Lib/ensurepip/_uninstall.py @@ -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()) diff --git a/Lib/test/test_ensurepip.py b/Lib/test/test_ensurepip.py index 3316fcfaa1..cb9d10a104 100644 --- a/Lib/test/test_ensurepip.py +++ b/Lib/test/test_ensurepip.py @@ -21,6 +21,7 @@ class EnsurepipMixin: def setUp(self): run_pip_patch = 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 @@ -258,7 +259,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( [ @@ -270,6 +271,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): @@ -284,7 +292,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( [ @@ -293,6 +301,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__": test.test_support.run_unittest(__name__) diff --git a/Misc/NEWS.d/next/Library/2017-09-17-15-24-25.bpo-31351.yQdKv-.rst b/Misc/NEWS.d/next/Library/2017-09-17-15-24-25.bpo-31351.yQdKv-.rst new file mode 100644 index 0000000000..20f2c1bdc1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-09-17-15-24-25.bpo-31351.yQdKv-.rst @@ -0,0 +1,2 @@ +python -m ensurepip now exits with non-zero exit code if pip bootstrapping +has failed. |