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