blob: 759168ec97e1f216d7fd2928dc9b947ead143237 [file] [log] [blame]
Nick Coghland0cf0632013-11-11 22:11:55 +10001import unittest
2import unittest.mock
Nick Coghland0cf0632013-11-11 22:11:55 +10003import test.support
Nick Coghland3e83e22013-11-13 22:24:58 +10004import os
5import os.path
Nick Coghlanfdf3a622013-11-30 17:15:09 +10006import contextlib
7import sys
Nick Coghland0cf0632013-11-11 22:11:55 +10008
Nick Coghlanf71cae02013-12-23 18:20:34 +10009import ensurepip
10import ensurepip._uninstall
Nick Coghland0cf0632013-11-11 22:11:55 +100011
Nick Coghlanae2ee962013-12-23 23:07:07 +100012# pip currently requires ssl support, so we ensure we handle
13# it being missing (http://bugs.python.org/issue19744)
14ensurepip_no_ssl = test.support.import_fresh_module("ensurepip",
15 blocked=["ssl"])
16try:
17 import ssl
18except ImportError:
19 def requires_usable_pip(f):
20 deco = unittest.skip(ensurepip._MISSING_SSL_MESSAGE)
21 return deco(f)
22else:
23 def requires_usable_pip(f):
24 return f
25
Nick Coghland0cf0632013-11-11 22:11:55 +100026class TestEnsurePipVersion(unittest.TestCase):
27
28 def test_returns_version(self):
29 self.assertEqual(ensurepip._PIP_VERSION, ensurepip.version())
30
Nick Coghlanf71cae02013-12-23 18:20:34 +100031class EnsurepipMixin:
Nick Coghland0cf0632013-11-11 22:11:55 +100032
33 def setUp(self):
34 run_pip_patch = unittest.mock.patch("ensurepip._run_pip")
35 self.run_pip = run_pip_patch.start()
36 self.addCleanup(run_pip_patch.stop)
37
Nick Coghland3e83e22013-11-13 22:24:58 +100038 # Avoid side effects on the actual os module
Nick Coghlan6edd82a2014-02-04 23:02:36 +100039 real_devnull = os.devnull
Nick Coghland3e83e22013-11-13 22:24:58 +100040 os_patch = unittest.mock.patch("ensurepip.os")
41 patched_os = os_patch.start()
42 self.addCleanup(os_patch.stop)
Nick Coghlan6edd82a2014-02-04 23:02:36 +100043 patched_os.devnull = real_devnull
Nick Coghland3e83e22013-11-13 22:24:58 +100044 patched_os.path = os.path
45 self.os_environ = patched_os.environ = os.environ.copy()
Nick Coghland0cf0632013-11-11 22:11:55 +100046
Nick Coghlanae2ee962013-12-23 23:07:07 +100047
Nick Coghlanf71cae02013-12-23 18:20:34 +100048class TestBootstrap(EnsurepipMixin, unittest.TestCase):
49
Nick Coghlanae2ee962013-12-23 23:07:07 +100050 @requires_usable_pip
Nick Coghland0cf0632013-11-11 22:11:55 +100051 def test_basic_bootstrapping(self):
52 ensurepip.bootstrap()
53
54 self.run_pip.assert_called_once_with(
55 [
56 "install", "--no-index", "--find-links",
Donald Stufftf7f58f82014-01-02 09:33:35 -050057 unittest.mock.ANY, "setuptools", "pip",
Nick Coghland0cf0632013-11-11 22:11:55 +100058 ],
59 unittest.mock.ANY,
60 )
61
62 additional_paths = self.run_pip.call_args[0][1]
63 self.assertEqual(len(additional_paths), 2)
64
Nick Coghlanae2ee962013-12-23 23:07:07 +100065 @requires_usable_pip
Nick Coghland0cf0632013-11-11 22:11:55 +100066 def test_bootstrapping_with_root(self):
67 ensurepip.bootstrap(root="/foo/bar/")
68
69 self.run_pip.assert_called_once_with(
70 [
71 "install", "--no-index", "--find-links",
Donald Stufftf7f58f82014-01-02 09:33:35 -050072 unittest.mock.ANY, "--root", "/foo/bar/",
Nick Coghland0cf0632013-11-11 22:11:55 +100073 "setuptools", "pip",
74 ],
75 unittest.mock.ANY,
76 )
77
Nick Coghlanae2ee962013-12-23 23:07:07 +100078 @requires_usable_pip
Nick Coghland0cf0632013-11-11 22:11:55 +100079 def test_bootstrapping_with_user(self):
80 ensurepip.bootstrap(user=True)
81
82 self.run_pip.assert_called_once_with(
83 [
84 "install", "--no-index", "--find-links",
Donald Stufftf7f58f82014-01-02 09:33:35 -050085 unittest.mock.ANY, "--user", "setuptools", "pip",
Nick Coghland0cf0632013-11-11 22:11:55 +100086 ],
87 unittest.mock.ANY,
88 )
89
Nick Coghlanae2ee962013-12-23 23:07:07 +100090 @requires_usable_pip
Nick Coghland0cf0632013-11-11 22:11:55 +100091 def test_bootstrapping_with_upgrade(self):
92 ensurepip.bootstrap(upgrade=True)
93
94 self.run_pip.assert_called_once_with(
95 [
96 "install", "--no-index", "--find-links",
Donald Stufftf7f58f82014-01-02 09:33:35 -050097 unittest.mock.ANY, "--upgrade", "setuptools", "pip",
Nick Coghland0cf0632013-11-11 22:11:55 +100098 ],
99 unittest.mock.ANY,
100 )
101
Nick Coghlanae2ee962013-12-23 23:07:07 +1000102 @requires_usable_pip
Nick Coghland0cf0632013-11-11 22:11:55 +1000103 def test_bootstrapping_with_verbosity_1(self):
104 ensurepip.bootstrap(verbosity=1)
105
106 self.run_pip.assert_called_once_with(
107 [
108 "install", "--no-index", "--find-links",
Donald Stufftf7f58f82014-01-02 09:33:35 -0500109 unittest.mock.ANY, "-v", "setuptools", "pip",
Nick Coghland0cf0632013-11-11 22:11:55 +1000110 ],
111 unittest.mock.ANY,
112 )
113
Nick Coghlanae2ee962013-12-23 23:07:07 +1000114 @requires_usable_pip
Nick Coghland0cf0632013-11-11 22:11:55 +1000115 def test_bootstrapping_with_verbosity_2(self):
116 ensurepip.bootstrap(verbosity=2)
117
118 self.run_pip.assert_called_once_with(
119 [
120 "install", "--no-index", "--find-links",
Donald Stufftf7f58f82014-01-02 09:33:35 -0500121 unittest.mock.ANY, "-vv", "setuptools", "pip",
Nick Coghland0cf0632013-11-11 22:11:55 +1000122 ],
123 unittest.mock.ANY,
124 )
125
Nick Coghlanae2ee962013-12-23 23:07:07 +1000126 @requires_usable_pip
Nick Coghland0cf0632013-11-11 22:11:55 +1000127 def test_bootstrapping_with_verbosity_3(self):
128 ensurepip.bootstrap(verbosity=3)
129
130 self.run_pip.assert_called_once_with(
131 [
132 "install", "--no-index", "--find-links",
Donald Stufftf7f58f82014-01-02 09:33:35 -0500133 unittest.mock.ANY, "-vvv", "setuptools", "pip",
Nick Coghland0cf0632013-11-11 22:11:55 +1000134 ],
135 unittest.mock.ANY,
136 )
137
Nick Coghlanae2ee962013-12-23 23:07:07 +1000138 @requires_usable_pip
Nick Coghland0cf0632013-11-11 22:11:55 +1000139 def test_bootstrapping_with_regular_install(self):
140 ensurepip.bootstrap()
141 self.assertEqual(self.os_environ["ENSUREPIP_OPTIONS"], "install")
142
Nick Coghlanae2ee962013-12-23 23:07:07 +1000143 @requires_usable_pip
Nick Coghland0cf0632013-11-11 22:11:55 +1000144 def test_bootstrapping_with_alt_install(self):
145 ensurepip.bootstrap(altinstall=True)
146 self.assertEqual(self.os_environ["ENSUREPIP_OPTIONS"], "altinstall")
147
Nick Coghlanae2ee962013-12-23 23:07:07 +1000148 @requires_usable_pip
Nick Coghland0cf0632013-11-11 22:11:55 +1000149 def test_bootstrapping_with_default_pip(self):
150 ensurepip.bootstrap(default_pip=True)
151 self.assertNotIn("ENSUREPIP_OPTIONS", self.os_environ)
152
153 def test_altinstall_default_pip_conflict(self):
154 with self.assertRaises(ValueError):
155 ensurepip.bootstrap(altinstall=True, default_pip=True)
Benjamin Petersonc844b002014-04-16 16:06:39 -0400156 self.assertFalse(self.run_pip.called)
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000157
Nick Coghlanae2ee962013-12-23 23:07:07 +1000158 @requires_usable_pip
Nick Coghlan6256fcb2013-12-23 16:16:07 +1000159 def test_pip_environment_variables_removed(self):
160 # ensurepip deliberately ignores all pip environment variables
161 # See http://bugs.python.org/issue19734 for details
162 self.os_environ["PIP_THIS_SHOULD_GO_AWAY"] = "test fodder"
163 ensurepip.bootstrap()
164 self.assertNotIn("PIP_THIS_SHOULD_GO_AWAY", self.os_environ)
165
Nick Coghlan6edd82a2014-02-04 23:02:36 +1000166 @requires_usable_pip
167 def test_pip_config_file_disabled(self):
168 # ensurepip deliberately ignores the pip config file
169 # See http://bugs.python.org/issue20053 for details
170 ensurepip.bootstrap()
171 self.assertEqual(self.os_environ["PIP_CONFIG_FILE"], os.devnull)
Nick Coghlan6256fcb2013-12-23 16:16:07 +1000172
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000173@contextlib.contextmanager
174def fake_pip(version=ensurepip._PIP_VERSION):
175 if version is None:
176 pip = None
177 else:
178 class FakePip():
179 __version__ = version
180 pip = FakePip()
181 sentinel = object()
182 orig_pip = sys.modules.get("pip", sentinel)
183 sys.modules["pip"] = pip
184 try:
185 yield pip
186 finally:
187 if orig_pip is sentinel:
188 del sys.modules["pip"]
189 else:
190 sys.modules["pip"] = orig_pip
191
Nick Coghlanf71cae02013-12-23 18:20:34 +1000192class TestUninstall(EnsurepipMixin, unittest.TestCase):
Nick Coghlaned9af522013-12-23 17:39:12 +1000193
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000194 def test_uninstall_skipped_when_not_installed(self):
195 with fake_pip(None):
Nick Coghlanf71cae02013-12-23 18:20:34 +1000196 ensurepip._uninstall_helper()
Benjamin Petersonc844b002014-04-16 16:06:39 -0400197 self.assertFalse(self.run_pip.called)
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000198
Nick Coghlana46cf122014-02-28 23:35:05 +1000199 def test_uninstall_skipped_with_warning_for_wrong_version(self):
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000200 with fake_pip("not a valid version"):
Nick Coghlana46cf122014-02-28 23:35:05 +1000201 with test.support.captured_stderr() as stderr:
Nick Coghlanf71cae02013-12-23 18:20:34 +1000202 ensurepip._uninstall_helper()
Nick Coghlana46cf122014-02-28 23:35:05 +1000203 warning = stderr.getvalue().strip()
204 self.assertIn("only uninstall a matching version", warning)
Benjamin Petersonc844b002014-04-16 16:06:39 -0400205 self.assertFalse(self.run_pip.called)
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000206
207
Nick Coghlanae2ee962013-12-23 23:07:07 +1000208 @requires_usable_pip
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000209 def test_uninstall(self):
210 with fake_pip():
Nick Coghlanf71cae02013-12-23 18:20:34 +1000211 ensurepip._uninstall_helper()
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000212
213 self.run_pip.assert_called_once_with(
214 ["uninstall", "-y", "pip", "setuptools"]
215 )
216
Nick Coghlanae2ee962013-12-23 23:07:07 +1000217 @requires_usable_pip
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000218 def test_uninstall_with_verbosity_1(self):
219 with fake_pip():
Nick Coghlanf71cae02013-12-23 18:20:34 +1000220 ensurepip._uninstall_helper(verbosity=1)
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000221
222 self.run_pip.assert_called_once_with(
223 ["uninstall", "-y", "-v", "pip", "setuptools"]
224 )
225
Nick Coghlanae2ee962013-12-23 23:07:07 +1000226 @requires_usable_pip
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000227 def test_uninstall_with_verbosity_2(self):
228 with fake_pip():
Nick Coghlanf71cae02013-12-23 18:20:34 +1000229 ensurepip._uninstall_helper(verbosity=2)
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000230
231 self.run_pip.assert_called_once_with(
232 ["uninstall", "-y", "-vv", "pip", "setuptools"]
233 )
234
Nick Coghlanae2ee962013-12-23 23:07:07 +1000235 @requires_usable_pip
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000236 def test_uninstall_with_verbosity_3(self):
237 with fake_pip():
Nick Coghlanf71cae02013-12-23 18:20:34 +1000238 ensurepip._uninstall_helper(verbosity=3)
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000239
240 self.run_pip.assert_called_once_with(
241 ["uninstall", "-y", "-vvv", "pip", "setuptools"]
242 )
243
Nick Coghlanae2ee962013-12-23 23:07:07 +1000244 @requires_usable_pip
Nick Coghlaned9af522013-12-23 17:39:12 +1000245 def test_pip_environment_variables_removed(self):
246 # ensurepip deliberately ignores all pip environment variables
247 # See http://bugs.python.org/issue19734 for details
248 self.os_environ["PIP_THIS_SHOULD_GO_AWAY"] = "test fodder"
249 with fake_pip():
Nick Coghlanf71cae02013-12-23 18:20:34 +1000250 ensurepip._uninstall_helper()
Nick Coghlaned9af522013-12-23 17:39:12 +1000251 self.assertNotIn("PIP_THIS_SHOULD_GO_AWAY", self.os_environ)
Nick Coghlanfdf3a622013-11-30 17:15:09 +1000252
Nick Coghlan6edd82a2014-02-04 23:02:36 +1000253 @requires_usable_pip
254 def test_pip_config_file_disabled(self):
255 # ensurepip deliberately ignores the pip config file
256 # See http://bugs.python.org/issue20053 for details
257 with fake_pip():
258 ensurepip._uninstall_helper()
259 self.assertEqual(self.os_environ["PIP_CONFIG_FILE"], os.devnull)
260
Nick Coghland0cf0632013-11-11 22:11:55 +1000261
Nick Coghlanae2ee962013-12-23 23:07:07 +1000262class TestMissingSSL(EnsurepipMixin, unittest.TestCase):
263
264 def setUp(self):
265 sys.modules["ensurepip"] = ensurepip_no_ssl
266 @self.addCleanup
267 def restore_module():
268 sys.modules["ensurepip"] = ensurepip
269 super().setUp()
270
271 def test_bootstrap_requires_ssl(self):
272 self.os_environ["PIP_THIS_SHOULD_STAY"] = "test fodder"
273 with self.assertRaisesRegex(RuntimeError, "requires SSL/TLS"):
274 ensurepip_no_ssl.bootstrap()
Benjamin Petersonc844b002014-04-16 16:06:39 -0400275 self.assertFalse(self.run_pip.called)
Nick Coghlanae2ee962013-12-23 23:07:07 +1000276 self.assertIn("PIP_THIS_SHOULD_STAY", self.os_environ)
277
278 def test_uninstall_requires_ssl(self):
279 self.os_environ["PIP_THIS_SHOULD_STAY"] = "test fodder"
280 with self.assertRaisesRegex(RuntimeError, "requires SSL/TLS"):
281 with fake_pip():
282 ensurepip_no_ssl._uninstall_helper()
Benjamin Petersonc844b002014-04-16 16:06:39 -0400283 self.assertFalse(self.run_pip.called)
Nick Coghlanae2ee962013-12-23 23:07:07 +1000284 self.assertIn("PIP_THIS_SHOULD_STAY", self.os_environ)
285
Nick Coghlanc00fa632014-02-15 09:14:54 +1000286 def test_main_exits_early_with_warning(self):
287 with test.support.captured_stderr() as stderr:
288 ensurepip_no_ssl._main(["--version"])
289 warning = stderr.getvalue().strip()
290 self.assertTrue(warning.endswith("requires SSL/TLS"), warning)
Benjamin Petersonc844b002014-04-16 16:06:39 -0400291 self.assertFalse(self.run_pip.called)
Nick Coghlanc00fa632014-02-15 09:14:54 +1000292
Nick Coghlanf71cae02013-12-23 18:20:34 +1000293# Basic testing of the main functions and their argument parsing
294
295EXPECTED_VERSION_OUTPUT = "pip " + ensurepip._PIP_VERSION
296
297class TestBootstrappingMainFunction(EnsurepipMixin, unittest.TestCase):
298
Nick Coghlanc00fa632014-02-15 09:14:54 +1000299 @requires_usable_pip
Nick Coghlanf71cae02013-12-23 18:20:34 +1000300 def test_bootstrap_version(self):
301 with test.support.captured_stdout() as stdout:
302 with self.assertRaises(SystemExit):
303 ensurepip._main(["--version"])
304 result = stdout.getvalue().strip()
305 self.assertEqual(result, EXPECTED_VERSION_OUTPUT)
Benjamin Petersonc844b002014-04-16 16:06:39 -0400306 self.assertFalse(self.run_pip.called)
Nick Coghlanf71cae02013-12-23 18:20:34 +1000307
Nick Coghlanae2ee962013-12-23 23:07:07 +1000308 @requires_usable_pip
Nick Coghlanf71cae02013-12-23 18:20:34 +1000309 def test_basic_bootstrapping(self):
310 ensurepip._main([])
311
312 self.run_pip.assert_called_once_with(
313 [
314 "install", "--no-index", "--find-links",
Donald Stufftf7f58f82014-01-02 09:33:35 -0500315 unittest.mock.ANY, "setuptools", "pip",
Nick Coghlanf71cae02013-12-23 18:20:34 +1000316 ],
317 unittest.mock.ANY,
318 )
319
320 additional_paths = self.run_pip.call_args[0][1]
321 self.assertEqual(len(additional_paths), 2)
322
323class TestUninstallationMainFunction(EnsurepipMixin, unittest.TestCase):
324
325 def test_uninstall_version(self):
326 with test.support.captured_stdout() as stdout:
327 with self.assertRaises(SystemExit):
328 ensurepip._uninstall._main(["--version"])
329 result = stdout.getvalue().strip()
330 self.assertEqual(result, EXPECTED_VERSION_OUTPUT)
Benjamin Petersonc844b002014-04-16 16:06:39 -0400331 self.assertFalse(self.run_pip.called)
Nick Coghlanf71cae02013-12-23 18:20:34 +1000332
Nick Coghlanae2ee962013-12-23 23:07:07 +1000333 @requires_usable_pip
Nick Coghlanf71cae02013-12-23 18:20:34 +1000334 def test_basic_uninstall(self):
335 with fake_pip():
336 ensurepip._uninstall._main([])
337
338 self.run_pip.assert_called_once_with(
339 ["uninstall", "-y", "pip", "setuptools"]
340 )
341
342
Nick Coghland0cf0632013-11-11 22:11:55 +1000343
344if __name__ == "__main__":
345 test.support.run_unittest(__name__)