Home | History | Annotate | Download | only in test
      1 import unittest
      2 import unittest.mock
      3 import test.support
      4 import os
      5 import os.path
      6 import contextlib
      7 import sys
      8 
      9 import ensurepip
     10 import ensurepip._uninstall
     11 
     12 
     13 class TestEnsurePipVersion(unittest.TestCase):
     14 
     15     def test_returns_version(self):
     16         self.assertEqual(ensurepip._PIP_VERSION, ensurepip.version())
     17 
     18 class EnsurepipMixin:
     19 
     20     def setUp(self):
     21         run_pip_patch = unittest.mock.patch("ensurepip._run_pip")
     22         self.run_pip = run_pip_patch.start()
     23         self.addCleanup(run_pip_patch.stop)
     24 
     25         # Avoid side effects on the actual os module
     26         real_devnull = os.devnull
     27         os_patch = unittest.mock.patch("ensurepip.os")
     28         patched_os = os_patch.start()
     29         self.addCleanup(os_patch.stop)
     30         patched_os.devnull = real_devnull
     31         patched_os.path = os.path
     32         self.os_environ = patched_os.environ = os.environ.copy()
     33 
     34 
     35 class TestBootstrap(EnsurepipMixin, unittest.TestCase):
     36 
     37     def test_basic_bootstrapping(self):
     38         ensurepip.bootstrap()
     39 
     40         self.run_pip.assert_called_once_with(
     41             [
     42                 "install", "--no-index", "--find-links",
     43                 unittest.mock.ANY, "setuptools", "pip",
     44             ],
     45             unittest.mock.ANY,
     46         )
     47 
     48         additional_paths = self.run_pip.call_args[0][1]
     49         self.assertEqual(len(additional_paths), 2)
     50 
     51     def test_bootstrapping_with_root(self):
     52         ensurepip.bootstrap(root="/foo/bar/")
     53 
     54         self.run_pip.assert_called_once_with(
     55             [
     56                 "install", "--no-index", "--find-links",
     57                 unittest.mock.ANY, "--root", "/foo/bar/",
     58                 "setuptools", "pip",
     59             ],
     60             unittest.mock.ANY,
     61         )
     62 
     63     def test_bootstrapping_with_user(self):
     64         ensurepip.bootstrap(user=True)
     65 
     66         self.run_pip.assert_called_once_with(
     67             [
     68                 "install", "--no-index", "--find-links",
     69                 unittest.mock.ANY, "--user", "setuptools", "pip",
     70             ],
     71             unittest.mock.ANY,
     72         )
     73 
     74     def test_bootstrapping_with_upgrade(self):
     75         ensurepip.bootstrap(upgrade=True)
     76 
     77         self.run_pip.assert_called_once_with(
     78             [
     79                 "install", "--no-index", "--find-links",
     80                 unittest.mock.ANY, "--upgrade", "setuptools", "pip",
     81             ],
     82             unittest.mock.ANY,
     83         )
     84 
     85     def test_bootstrapping_with_verbosity_1(self):
     86         ensurepip.bootstrap(verbosity=1)
     87 
     88         self.run_pip.assert_called_once_with(
     89             [
     90                 "install", "--no-index", "--find-links",
     91                 unittest.mock.ANY, "-v", "setuptools", "pip",
     92             ],
     93             unittest.mock.ANY,
     94         )
     95 
     96     def test_bootstrapping_with_verbosity_2(self):
     97         ensurepip.bootstrap(verbosity=2)
     98 
     99         self.run_pip.assert_called_once_with(
    100             [
    101                 "install", "--no-index", "--find-links",
    102                 unittest.mock.ANY, "-vv", "setuptools", "pip",
    103             ],
    104             unittest.mock.ANY,
    105         )
    106 
    107     def test_bootstrapping_with_verbosity_3(self):
    108         ensurepip.bootstrap(verbosity=3)
    109 
    110         self.run_pip.assert_called_once_with(
    111             [
    112                 "install", "--no-index", "--find-links",
    113                 unittest.mock.ANY, "-vvv", "setuptools", "pip",
    114             ],
    115             unittest.mock.ANY,
    116         )
    117 
    118     def test_bootstrapping_with_regular_install(self):
    119         ensurepip.bootstrap()
    120         self.assertEqual(self.os_environ["ENSUREPIP_OPTIONS"], "install")
    121 
    122     def test_bootstrapping_with_alt_install(self):
    123         ensurepip.bootstrap(altinstall=True)
    124         self.assertEqual(self.os_environ["ENSUREPIP_OPTIONS"], "altinstall")
    125 
    126     def test_bootstrapping_with_default_pip(self):
    127         ensurepip.bootstrap(default_pip=True)
    128         self.assertNotIn("ENSUREPIP_OPTIONS", self.os_environ)
    129 
    130     def test_altinstall_default_pip_conflict(self):
    131         with self.assertRaises(ValueError):
    132             ensurepip.bootstrap(altinstall=True, default_pip=True)
    133         self.assertFalse(self.run_pip.called)
    134 
    135     def test_pip_environment_variables_removed(self):
    136         # ensurepip deliberately ignores all pip environment variables
    137         # See http://bugs.python.org/issue19734 for details
    138         self.os_environ["PIP_THIS_SHOULD_GO_AWAY"] = "test fodder"
    139         ensurepip.bootstrap()
    140         self.assertNotIn("PIP_THIS_SHOULD_GO_AWAY", self.os_environ)
    141 
    142     def test_pip_config_file_disabled(self):
    143         # ensurepip deliberately ignores the pip config file
    144         # See http://bugs.python.org/issue20053 for details
    145         ensurepip.bootstrap()
    146         self.assertEqual(self.os_environ["PIP_CONFIG_FILE"], os.devnull)
    147 
    148 @contextlib.contextmanager
    149 def fake_pip(version=ensurepip._PIP_VERSION):
    150     if version is None:
    151         pip = None
    152     else:
    153         class FakePip():
    154             __version__ = version
    155         pip = FakePip()
    156     sentinel = object()
    157     orig_pip = sys.modules.get("pip", sentinel)
    158     sys.modules["pip"] = pip
    159     try:
    160         yield pip
    161     finally:
    162         if orig_pip is sentinel:
    163             del sys.modules["pip"]
    164         else:
    165             sys.modules["pip"] = orig_pip
    166 
    167 class TestUninstall(EnsurepipMixin, unittest.TestCase):
    168 
    169     def test_uninstall_skipped_when_not_installed(self):
    170         with fake_pip(None):
    171             ensurepip._uninstall_helper()
    172         self.assertFalse(self.run_pip.called)
    173 
    174     def test_uninstall_skipped_with_warning_for_wrong_version(self):
    175         with fake_pip("not a valid version"):
    176             with test.support.captured_stderr() as stderr:
    177                 ensurepip._uninstall_helper()
    178         warning = stderr.getvalue().strip()
    179         self.assertIn("only uninstall a matching version", warning)
    180         self.assertFalse(self.run_pip.called)
    181 
    182 
    183     def test_uninstall(self):
    184         with fake_pip():
    185             ensurepip._uninstall_helper()
    186 
    187         self.run_pip.assert_called_once_with(
    188             [
    189                 "uninstall", "-y", "--disable-pip-version-check", "pip",
    190                 "setuptools",
    191             ]
    192         )
    193 
    194     def test_uninstall_with_verbosity_1(self):
    195         with fake_pip():
    196             ensurepip._uninstall_helper(verbosity=1)
    197 
    198         self.run_pip.assert_called_once_with(
    199             [
    200                 "uninstall", "-y", "--disable-pip-version-check", "-v", "pip",
    201                 "setuptools",
    202             ]
    203         )
    204 
    205     def test_uninstall_with_verbosity_2(self):
    206         with fake_pip():
    207             ensurepip._uninstall_helper(verbosity=2)
    208 
    209         self.run_pip.assert_called_once_with(
    210             [
    211                 "uninstall", "-y", "--disable-pip-version-check", "-vv", "pip",
    212                 "setuptools",
    213             ]
    214         )
    215 
    216     def test_uninstall_with_verbosity_3(self):
    217         with fake_pip():
    218             ensurepip._uninstall_helper(verbosity=3)
    219 
    220         self.run_pip.assert_called_once_with(
    221             [
    222                 "uninstall", "-y", "--disable-pip-version-check", "-vvv",
    223                 "pip", "setuptools",
    224             ]
    225         )
    226 
    227     def test_pip_environment_variables_removed(self):
    228         # ensurepip deliberately ignores all pip environment variables
    229         # See http://bugs.python.org/issue19734 for details
    230         self.os_environ["PIP_THIS_SHOULD_GO_AWAY"] = "test fodder"
    231         with fake_pip():
    232             ensurepip._uninstall_helper()
    233         self.assertNotIn("PIP_THIS_SHOULD_GO_AWAY", self.os_environ)
    234 
    235     def test_pip_config_file_disabled(self):
    236         # ensurepip deliberately ignores the pip config file
    237         # See http://bugs.python.org/issue20053 for details
    238         with fake_pip():
    239             ensurepip._uninstall_helper()
    240         self.assertEqual(self.os_environ["PIP_CONFIG_FILE"], os.devnull)
    241 
    242 
    243 # Basic testing of the main functions and their argument parsing
    244 
    245 EXPECTED_VERSION_OUTPUT = "pip " + ensurepip._PIP_VERSION
    246 
    247 class TestBootstrappingMainFunction(EnsurepipMixin, unittest.TestCase):
    248 
    249     def test_bootstrap_version(self):
    250         with test.support.captured_stdout() as stdout:
    251             with self.assertRaises(SystemExit):
    252                 ensurepip._main(["--version"])
    253         result = stdout.getvalue().strip()
    254         self.assertEqual(result, EXPECTED_VERSION_OUTPUT)
    255         self.assertFalse(self.run_pip.called)
    256 
    257     def test_basic_bootstrapping(self):
    258         ensurepip._main([])
    259 
    260         self.run_pip.assert_called_once_with(
    261             [
    262                 "install", "--no-index", "--find-links",
    263                 unittest.mock.ANY, "setuptools", "pip",
    264             ],
    265             unittest.mock.ANY,
    266         )
    267 
    268         additional_paths = self.run_pip.call_args[0][1]
    269         self.assertEqual(len(additional_paths), 2)
    270 
    271 class TestUninstallationMainFunction(EnsurepipMixin, unittest.TestCase):
    272 
    273     def test_uninstall_version(self):
    274         with test.support.captured_stdout() as stdout:
    275             with self.assertRaises(SystemExit):
    276                 ensurepip._uninstall._main(["--version"])
    277         result = stdout.getvalue().strip()
    278         self.assertEqual(result, EXPECTED_VERSION_OUTPUT)
    279         self.assertFalse(self.run_pip.called)
    280 
    281     def test_basic_uninstall(self):
    282         with fake_pip():
    283             ensurepip._uninstall._main([])
    284 
    285         self.run_pip.assert_called_once_with(
    286             [
    287                 "uninstall", "-y", "--disable-pip-version-check", "pip",
    288                 "setuptools",
    289             ]
    290         )
    291 
    292 
    293 
    294 if __name__ == "__main__":
    295     unittest.main()
    296