(root)/
Python-3.12.0/
Lib/
test/
test_ensurepip.py
       1  import contextlib
       2  import os
       3  import os.path
       4  import sys
       5  import tempfile
       6  import test.support
       7  import unittest
       8  import unittest.mock
       9  
      10  import ensurepip
      11  import ensurepip._uninstall
      12  
      13  
      14  class ESC[4;38;5;81mTestPackages(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      15      def touch(self, directory, filename):
      16          fullname = os.path.join(directory, filename)
      17          open(fullname, "wb").close()
      18  
      19      def test_version(self):
      20          # Test version()
      21          with tempfile.TemporaryDirectory() as tmpdir:
      22              self.touch(tmpdir, "pip-1.2.3b1-py2.py3-none-any.whl")
      23              with (unittest.mock.patch.object(ensurepip, '_PACKAGES', None),
      24                    unittest.mock.patch.object(ensurepip, '_WHEEL_PKG_DIR', tmpdir)):
      25                  self.assertEqual(ensurepip.version(), '1.2.3b1')
      26  
      27      def test_get_packages_no_dir(self):
      28          # Test _get_packages() without a wheel package directory
      29          with (unittest.mock.patch.object(ensurepip, '_PACKAGES', None),
      30                unittest.mock.patch.object(ensurepip, '_WHEEL_PKG_DIR', None)):
      31              packages = ensurepip._get_packages()
      32  
      33              # when bundled wheel packages are used, we get _PIP_VERSION
      34              self.assertEqual(ensurepip._PIP_VERSION, ensurepip.version())
      35  
      36          # use bundled wheel packages
      37          self.assertIsNotNone(packages['pip'].wheel_name)
      38  
      39      def test_get_packages_with_dir(self):
      40          # Test _get_packages() with a wheel package directory
      41          pip_filename = "pip-20.2.2-py2.py3-none-any.whl"
      42  
      43          with tempfile.TemporaryDirectory() as tmpdir:
      44              self.touch(tmpdir, pip_filename)
      45              # not used, make sure that it's ignored
      46              self.touch(tmpdir, "wheel-0.34.2-py2.py3-none-any.whl")
      47  
      48              with (unittest.mock.patch.object(ensurepip, '_PACKAGES', None),
      49                    unittest.mock.patch.object(ensurepip, '_WHEEL_PKG_DIR', tmpdir)):
      50                  packages = ensurepip._get_packages()
      51  
      52              self.assertEqual(packages['pip'].version, '20.2.2')
      53              self.assertEqual(packages['pip'].wheel_path,
      54                               os.path.join(tmpdir, pip_filename))
      55  
      56              # wheel package is ignored
      57              self.assertEqual(sorted(packages), ['pip'])
      58  
      59  
      60  class ESC[4;38;5;81mEnsurepipMixin:
      61  
      62      def setUp(self):
      63          run_pip_patch = unittest.mock.patch("ensurepip._run_pip")
      64          self.run_pip = run_pip_patch.start()
      65          self.run_pip.return_value = 0
      66          self.addCleanup(run_pip_patch.stop)
      67  
      68          # Avoid side effects on the actual os module
      69          real_devnull = os.devnull
      70          os_patch = unittest.mock.patch("ensurepip.os")
      71          patched_os = os_patch.start()
      72          # But expose os.listdir() used by _find_packages()
      73          patched_os.listdir = os.listdir
      74          self.addCleanup(os_patch.stop)
      75          patched_os.devnull = real_devnull
      76          patched_os.path = os.path
      77          self.os_environ = patched_os.environ = os.environ.copy()
      78  
      79  
      80  class ESC[4;38;5;81mTestBootstrap(ESC[4;38;5;149mEnsurepipMixin, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      81  
      82      def test_basic_bootstrapping(self):
      83          ensurepip.bootstrap()
      84  
      85          self.run_pip.assert_called_once_with(
      86              [
      87                  "install", "--no-cache-dir", "--no-index", "--find-links",
      88                  unittest.mock.ANY, "pip",
      89              ],
      90              unittest.mock.ANY,
      91          )
      92  
      93          additional_paths = self.run_pip.call_args[0][1]
      94          self.assertEqual(len(additional_paths), 1)
      95  
      96      def test_bootstrapping_with_root(self):
      97          ensurepip.bootstrap(root="/foo/bar/")
      98  
      99          self.run_pip.assert_called_once_with(
     100              [
     101                  "install", "--no-cache-dir", "--no-index", "--find-links",
     102                  unittest.mock.ANY, "--root", "/foo/bar/",
     103                  "pip",
     104              ],
     105              unittest.mock.ANY,
     106          )
     107  
     108      def test_bootstrapping_with_user(self):
     109          ensurepip.bootstrap(user=True)
     110  
     111          self.run_pip.assert_called_once_with(
     112              [
     113                  "install", "--no-cache-dir", "--no-index", "--find-links",
     114                  unittest.mock.ANY, "--user", "pip",
     115              ],
     116              unittest.mock.ANY,
     117          )
     118  
     119      def test_bootstrapping_with_upgrade(self):
     120          ensurepip.bootstrap(upgrade=True)
     121  
     122          self.run_pip.assert_called_once_with(
     123              [
     124                  "install", "--no-cache-dir", "--no-index", "--find-links",
     125                  unittest.mock.ANY, "--upgrade", "pip",
     126              ],
     127              unittest.mock.ANY,
     128          )
     129  
     130      def test_bootstrapping_with_verbosity_1(self):
     131          ensurepip.bootstrap(verbosity=1)
     132  
     133          self.run_pip.assert_called_once_with(
     134              [
     135                  "install", "--no-cache-dir", "--no-index", "--find-links",
     136                  unittest.mock.ANY, "-v", "pip",
     137              ],
     138              unittest.mock.ANY,
     139          )
     140  
     141      def test_bootstrapping_with_verbosity_2(self):
     142          ensurepip.bootstrap(verbosity=2)
     143  
     144          self.run_pip.assert_called_once_with(
     145              [
     146                  "install", "--no-cache-dir", "--no-index", "--find-links",
     147                  unittest.mock.ANY, "-vv", "pip",
     148              ],
     149              unittest.mock.ANY,
     150          )
     151  
     152      def test_bootstrapping_with_verbosity_3(self):
     153          ensurepip.bootstrap(verbosity=3)
     154  
     155          self.run_pip.assert_called_once_with(
     156              [
     157                  "install", "--no-cache-dir", "--no-index", "--find-links",
     158                  unittest.mock.ANY, "-vvv", "pip",
     159              ],
     160              unittest.mock.ANY,
     161          )
     162  
     163      def test_bootstrapping_with_regular_install(self):
     164          ensurepip.bootstrap()
     165          self.assertEqual(self.os_environ["ENSUREPIP_OPTIONS"], "install")
     166  
     167      def test_bootstrapping_with_alt_install(self):
     168          ensurepip.bootstrap(altinstall=True)
     169          self.assertEqual(self.os_environ["ENSUREPIP_OPTIONS"], "altinstall")
     170  
     171      def test_bootstrapping_with_default_pip(self):
     172          ensurepip.bootstrap(default_pip=True)
     173          self.assertNotIn("ENSUREPIP_OPTIONS", self.os_environ)
     174  
     175      def test_altinstall_default_pip_conflict(self):
     176          with self.assertRaises(ValueError):
     177              ensurepip.bootstrap(altinstall=True, default_pip=True)
     178          self.assertFalse(self.run_pip.called)
     179  
     180      def test_pip_environment_variables_removed(self):
     181          # ensurepip deliberately ignores all pip environment variables
     182          # See http://bugs.python.org/issue19734 for details
     183          self.os_environ["PIP_THIS_SHOULD_GO_AWAY"] = "test fodder"
     184          ensurepip.bootstrap()
     185          self.assertNotIn("PIP_THIS_SHOULD_GO_AWAY", self.os_environ)
     186  
     187      def test_pip_config_file_disabled(self):
     188          # ensurepip deliberately ignores the pip config file
     189          # See http://bugs.python.org/issue20053 for details
     190          ensurepip.bootstrap()
     191          self.assertEqual(self.os_environ["PIP_CONFIG_FILE"], os.devnull)
     192  
     193  @contextlib.contextmanager
     194  def fake_pip(version=ensurepip.version()):
     195      if version is None:
     196          pip = None
     197      else:
     198          class ESC[4;38;5;81mFakePip():
     199              __version__ = version
     200          pip = FakePip()
     201      sentinel = object()
     202      orig_pip = sys.modules.get("pip", sentinel)
     203      sys.modules["pip"] = pip
     204      try:
     205          yield pip
     206      finally:
     207          if orig_pip is sentinel:
     208              del sys.modules["pip"]
     209          else:
     210              sys.modules["pip"] = orig_pip
     211  
     212  class ESC[4;38;5;81mTestUninstall(ESC[4;38;5;149mEnsurepipMixin, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     213  
     214      def test_uninstall_skipped_when_not_installed(self):
     215          with fake_pip(None):
     216              ensurepip._uninstall_helper()
     217          self.assertFalse(self.run_pip.called)
     218  
     219      def test_uninstall_skipped_with_warning_for_wrong_version(self):
     220          with fake_pip("not a valid version"):
     221              with test.support.captured_stderr() as stderr:
     222                  ensurepip._uninstall_helper()
     223          warning = stderr.getvalue().strip()
     224          self.assertIn("only uninstall a matching version", warning)
     225          self.assertFalse(self.run_pip.called)
     226  
     227  
     228      def test_uninstall(self):
     229          with fake_pip():
     230              ensurepip._uninstall_helper()
     231  
     232          self.run_pip.assert_called_once_with(
     233              [
     234                  "uninstall", "-y", "--disable-pip-version-check", "pip",
     235              ]
     236          )
     237  
     238      def test_uninstall_with_verbosity_1(self):
     239          with fake_pip():
     240              ensurepip._uninstall_helper(verbosity=1)
     241  
     242          self.run_pip.assert_called_once_with(
     243              [
     244                  "uninstall", "-y", "--disable-pip-version-check", "-v", "pip",
     245              ]
     246          )
     247  
     248      def test_uninstall_with_verbosity_2(self):
     249          with fake_pip():
     250              ensurepip._uninstall_helper(verbosity=2)
     251  
     252          self.run_pip.assert_called_once_with(
     253              [
     254                  "uninstall", "-y", "--disable-pip-version-check", "-vv", "pip",
     255              ]
     256          )
     257  
     258      def test_uninstall_with_verbosity_3(self):
     259          with fake_pip():
     260              ensurepip._uninstall_helper(verbosity=3)
     261  
     262          self.run_pip.assert_called_once_with(
     263              [
     264                  "uninstall", "-y", "--disable-pip-version-check", "-vvv",
     265                  "pip"
     266              ]
     267          )
     268  
     269      def test_pip_environment_variables_removed(self):
     270          # ensurepip deliberately ignores all pip environment variables
     271          # See http://bugs.python.org/issue19734 for details
     272          self.os_environ["PIP_THIS_SHOULD_GO_AWAY"] = "test fodder"
     273          with fake_pip():
     274              ensurepip._uninstall_helper()
     275          self.assertNotIn("PIP_THIS_SHOULD_GO_AWAY", self.os_environ)
     276  
     277      def test_pip_config_file_disabled(self):
     278          # ensurepip deliberately ignores the pip config file
     279          # See http://bugs.python.org/issue20053 for details
     280          with fake_pip():
     281              ensurepip._uninstall_helper()
     282          self.assertEqual(self.os_environ["PIP_CONFIG_FILE"], os.devnull)
     283  
     284  
     285  # Basic testing of the main functions and their argument parsing
     286  
     287  EXPECTED_VERSION_OUTPUT = "pip " + ensurepip.version()
     288  
     289  class ESC[4;38;5;81mTestBootstrappingMainFunction(ESC[4;38;5;149mEnsurepipMixin, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     290  
     291      def test_bootstrap_version(self):
     292          with test.support.captured_stdout() as stdout:
     293              with self.assertRaises(SystemExit):
     294                  ensurepip._main(["--version"])
     295          result = stdout.getvalue().strip()
     296          self.assertEqual(result, EXPECTED_VERSION_OUTPUT)
     297          self.assertFalse(self.run_pip.called)
     298  
     299      def test_basic_bootstrapping(self):
     300          exit_code = ensurepip._main([])
     301  
     302          self.run_pip.assert_called_once_with(
     303              [
     304                  "install", "--no-cache-dir", "--no-index", "--find-links",
     305                  unittest.mock.ANY, "pip",
     306              ],
     307              unittest.mock.ANY,
     308          )
     309  
     310          additional_paths = self.run_pip.call_args[0][1]
     311          self.assertEqual(len(additional_paths), 1)
     312          self.assertEqual(exit_code, 0)
     313  
     314      def test_bootstrapping_error_code(self):
     315          self.run_pip.return_value = 2
     316          exit_code = ensurepip._main([])
     317          self.assertEqual(exit_code, 2)
     318  
     319  
     320  class ESC[4;38;5;81mTestUninstallationMainFunction(ESC[4;38;5;149mEnsurepipMixin, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     321  
     322      def test_uninstall_version(self):
     323          with test.support.captured_stdout() as stdout:
     324              with self.assertRaises(SystemExit):
     325                  ensurepip._uninstall._main(["--version"])
     326          result = stdout.getvalue().strip()
     327          self.assertEqual(result, EXPECTED_VERSION_OUTPUT)
     328          self.assertFalse(self.run_pip.called)
     329  
     330      def test_basic_uninstall(self):
     331          with fake_pip():
     332              exit_code = ensurepip._uninstall._main([])
     333  
     334          self.run_pip.assert_called_once_with(
     335              [
     336                  "uninstall", "-y", "--disable-pip-version-check", "pip",
     337              ]
     338          )
     339  
     340          self.assertEqual(exit_code, 0)
     341  
     342      def test_uninstall_error_code(self):
     343          with fake_pip():
     344              self.run_pip.return_value = 2
     345              exit_code = ensurepip._uninstall._main([])
     346          self.assertEqual(exit_code, 2)
     347  
     348  
     349  if __name__ == "__main__":
     350      unittest.main()