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