this repo has no description
1#!/usr/bin/env python3
2# Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
3import os
4import subprocess
5import sys
6import unittest
7import zipfile
8from tempfile import TemporaryDirectory
9
10
11def with_pty(command):
12 return [sys.executable, '-c', 'import pty, sys; pty.spawn(sys.argv[1:])'] + command
13
14
15class OptionsTest(unittest.TestCase):
16 def test_I_option_sets_isolated_no_user_site_ignore_environment_flags(self):
17 result = subprocess.run(
18 [sys.executable, "-I", "-c", "import sys;print(sys.flags)"],
19 check=True,
20 capture_output=True,
21 )
22 self.assertIn(b"isolated=1", result.stdout)
23 self.assertIn(b"ignore_environment=1", result.stdout)
24 self.assertIn(b"no_user_site=1", result.stdout)
25
26 def test_O_option_increments_optimize_flag(self):
27 result = subprocess.run(
28 [sys.executable, "-OO", "-OOO", "-c", "import sys;print(sys.flags)"],
29 check=True,
30 capture_output=True,
31 )
32 self.assertIn(b"optimize=5", result.stdout)
33
34 def test_B_option_sets_dont_write_bytecode_flag(self):
35 result = subprocess.run(
36 [sys.executable, "-B", "-c", "import sys;print(sys.flags)"],
37 check=True,
38 capture_output=True,
39 )
40 self.assertIn(b"dont_write_bytecode=1", result.stdout)
41
42 def test_PYTHONHASHSEED_sets_fixed_seed(self):
43 env = dict(os.environ)
44 env["PYTHONHASHSEED"] = "0"
45 code = "print(hash('abcdefghijkl'));import sys;print(sys.flags)"
46 result0 = subprocess.run(
47 [sys.executable, "-c", code], check=True, capture_output=True, env=env
48 )
49 result1 = subprocess.run(
50 [sys.executable, "-c", code], check=True, capture_output=True, env=env
51 )
52 self.assertEqual(result0.stdout, result1.stdout)
53 self.assertIn(b"hash_randomization=0", result0.stdout)
54
55 def test_PYTHONHASHSEED_sets_random_seed(self):
56 env = dict(os.environ)
57 env["PYTHONHASHSEED"] = "random"
58 code = "print(hash('abcdefghijkl'));import sys;print(sys.flags)"
59 result0 = subprocess.run(
60 [sys.executable, "-c", code], check=True, capture_output=True, env=env
61 )
62 result1 = subprocess.run(
63 [sys.executable, "-c", code], check=True, capture_output=True, env=env
64 )
65 self.assertNotEqual(result0.stdout, result1.stdout)
66 self.assertIn(b"hash_randomization=1", result0.stdout)
67
68 def test_PYTHONHASHSEED_unset_sets_random_seed(self):
69 code = "print(hash('abcdefghijkl'));import sys;print(sys.flags)"
70 result0 = subprocess.run(
71 [sys.executable, "-c", code], check=True, capture_output=True
72 )
73 result1 = subprocess.run(
74 [sys.executable, "-c", code], check=True, capture_output=True
75 )
76 self.assertNotEqual(result0.stdout, result1.stdout)
77 self.assertIn(b"hash_randomization=1", result0.stdout)
78
79 def test_PYTHONPATH_sets_sys_path(self):
80 with TemporaryDirectory() as tempdir:
81 path0 = os.path.abspath(os.path.join(tempdir, "foo"))
82 path1 = os.path.abspath(os.path.join(tempdir, "bar"))
83 env = dict(os.environ)
84 env["PYTHONPATH"] = f"{path0}:{path1}"
85 code = "import sys;print('sys.path: ' + str(sys.path))"
86 result = subprocess.run(
87 [sys.executable, "-c", code],
88 check=True,
89 capture_output=True,
90 env=env,
91 encoding="utf-8",
92 )
93 self.assertIn(f"sys.path: ['', '{path0}', '{path1}'", result.stdout)
94
95 def test_PYTHONPYCACHEPREFIX_sets_sys_pycache_prefix(self):
96 with TemporaryDirectory() as tempdir:
97 path = os.path.abspath(os.path.join(tempdir, "foo"))
98 env = dict(os.environ)
99 env["PYTHONPYCACHEPREFIX"] = path
100 code = "import sys;print(f'pycache_prefix: {sys.pycache_prefix}')"
101 result = subprocess.run(
102 [sys.executable, "-c", code],
103 check=True,
104 capture_output=True,
105 env=env,
106 encoding="utf-8",
107 )
108 self.assertIn(f"pycache_prefix: {path}", result.stdout)
109
110 def test_PYTHONWARNINGS_adds_warnoptions(self):
111 env = dict(os.environ)
112 env["PYTHONWARNINGS"] = "foo,bar"
113 code = "import sys;print('warnoptions: ' + str(sys.warnoptions))"
114 result = subprocess.run(
115 [sys.executable, "-W", "baz", "-W", "bam", "-c", code],
116 check=True,
117 capture_output=True,
118 env=env,
119 )
120 self.assertIn(b"warnoptions: ['foo', 'bar', 'baz', 'bam']", result.stdout)
121
122 def test_S_option_sets_no_site_flag(self):
123 result = subprocess.run(
124 [sys.executable, "-S", "-c", "import sys;print(sys.flags)"],
125 check=True,
126 capture_output=True,
127 )
128 self.assertIn(b"no_site=1", result.stdout)
129
130 def test_E_option_sets_ignore_environment_flag(self):
131 result = subprocess.run(
132 [sys.executable, "-E", "-c", "import sys;print(sys.flags)"],
133 check=True,
134 capture_output=True,
135 )
136 self.assertIn(b"ignore_environment=1", result.stdout)
137
138 def test_V_option_prints_version(self):
139 result = subprocess.run(
140 [sys.executable, "-V"], check=True, capture_output=True, encoding="utf-8"
141 )
142 version = sys.version_info
143 self.assertIn(
144 f"Python {version.major}.{version.minor}.{version.micro}", result.stdout
145 )
146
147 def test_W_option_adds_warnoptions(self):
148 env = dict(os.environ)
149 code = "import sys;print('warnoptions: ' + str(sys.warnoptions))"
150 result = subprocess.run(
151 [sys.executable, "-W", "foo", "-W", "ba,r", "-c", code],
152 check=True,
153 capture_output=True,
154 env=env,
155 )
156 self.assertIn(b"warnoptions: ['foo', 'ba,r']", result.stdout)
157
158 def test_c_option_runs_python_code(self):
159 result = subprocess.run(
160 [sys.executable, "-c", "print('test_c_op' + 'tion ok')"],
161 check=True,
162 capture_output=True,
163 )
164 self.assertIn(b"test_c_option ok", result.stdout)
165 self.assertNotIn(b">>>", result.stderr)
166
167 def test_c_option_flushes_stderr_on_finalize(self):
168 result = subprocess.run(
169 [sys.executable, "-c", "import sys; sys.stderr.write('1;2;3')"],
170 check=True,
171 capture_output=True,
172 )
173 self.assertIn(b"1;2;3", result.stderr)
174
175 def test_c_option_flushes_stdout_on_finalize(self):
176 result = subprocess.run(
177 [sys.executable, "-c", "import sys; sys.stdout.write('1;2;3')"],
178 check=True,
179 capture_output=True,
180 )
181 self.assertIn(b"1;2;3", result.stdout)
182
183 def test_c_option_flushes_stdout_afer_sys_exit_call_on_finalize(self):
184 result = subprocess.run(
185 [sys.executable, "-c", "import sys; sys.stdout.write('1;2;3'); sys.exit()"],
186 check=True,
187 capture_output=True,
188 )
189 self.assertIn(b"1;2;3", result.stdout)
190
191 def test_t_option_noop(self):
192 result = subprocess.run(
193 [sys.executable, "-t", "-c", "0"], check=True, capture_output=True
194 )
195 self.assertIn(b"", result.stdout)
196
197 def test_i_option_sets_inspect_interactive_flags(self):
198 result = subprocess.run(
199 [sys.executable, "-i", "-c", "import sys;print(sys.flags);sys.ps1='TTT:'"],
200 check=True,
201 capture_output=True,
202 stdin=subprocess.DEVNULL,
203 )
204 self.assertIn(b"inspect=1", result.stdout)
205 self.assertIn(b"interactive=1", result.stdout)
206 self.assertIn(b"TTT:", result.stderr)
207
208 def test_m_option_imports_module(self):
209 result = subprocess.run(
210 [sys.executable, "-m", "this"], check=True, capture_output=True
211 )
212 self.assertIn(b"The Zen of Python", result.stdout)
213 self.assertNotIn(b">>>", result.stderr)
214
215 def test_no_option_sets_default_flags(self):
216 result = subprocess.run(
217 [sys.executable, "-c", "import sys;print(sys.flags)"],
218 check=True,
219 capture_output=True,
220 )
221 self.assertIn(
222 b"sys.flags(debug=0, inspect=0, interactive=0, optimize=0, dont_write_bytecode=0, no_user_site=0, no_site=0, ignore_environment=0, verbose=0, bytes_warning=0, quiet=0, hash_randomization=1, isolated=0, dev_mode=False, utf8_mode",
223 result.stdout,
224 )
225
226 def test_no_arguments_works(self):
227 result = subprocess.run([sys.executable], stdin=subprocess.DEVNULL)
228 self.assertEqual(result.returncode, 0)
229
230 def test_s_option_sets_no_user_site_flag(self):
231 result = subprocess.run(
232 [sys.executable, "-s", "-c", "import sys;print(sys.flags)"],
233 check=True,
234 capture_output=True,
235 )
236 self.assertIn(b"no_user_site=1", result.stdout)
237
238 def test_v_option_increments_verbose_flag(self):
239 result = subprocess.run(
240 [sys.executable, "-vvv", "-v", "-c", "import sys;print(sys.flags)"],
241 check=True,
242 capture_output=True,
243 )
244 self.assertIn(b"verbose=4", result.stdout)
245
246 def test_version_option_prints_version(self):
247 result = subprocess.run(
248 [sys.executable, "--version"],
249 check=True,
250 capture_output=True,
251 encoding="utf-8",
252 )
253 version = sys.version_info
254 self.assertIn(
255 f"Python {version.major}.{version.minor}.{version.micro}", result.stdout
256 )
257
258 def test_q_option_sets_quiet_flag(self):
259 result = subprocess.run(
260 [sys.executable, "-q", "-c", "import sys;print(sys.flags)"],
261 check=True,
262 capture_output=True,
263 )
264 self.assertIn(b"quiet=1", result.stdout)
265
266 def test_no_u_option_in_pty_sets_buffered_stdio(self):
267 result = subprocess.run(
268 with_pty([sys.executable, "-c", "import sys;print(sys.stdout.line_buffering)"]),
269 check=True,
270 capture_output=True,
271 )
272 self.assertIn(b"True", result.stdout)
273
274 def test_no_u_option_no_pty_sets_unbuffered_stdio(self):
275 result = subprocess.run(
276 [sys.executable, "-c", "import sys;print(sys.stdout.line_buffering)"],
277 check=True,
278 capture_output=True,
279 )
280 self.assertIn(b"False", result.stdout)
281
282 def test_u_option_in_pty_sets_unbuffered_stdio(self):
283 result = subprocess.run(
284 with_pty([sys.executable, "-u", "-c", "import sys;print(sys.stdout.line_buffering)"]),
285 check=True,
286 capture_output=True,
287 )
288 self.assertIn(b"False", result.stdout)
289
290 def test_u_option_no_pty_sets_unbuffered_stdio(self):
291 result = subprocess.run(
292 [sys.executable, "-u", "-c", "import sys;print(sys.stdout.line_buffering)"],
293 check=True,
294 capture_output=True,
295 )
296 self.assertIn(b"False", result.stdout)
297
298 def test_u_option_in_pty_sets_unbuffered_stdin(self):
299 result = subprocess.run(
300 with_pty([sys.executable, "-u", "-c", "import sys;print(sys.stdin.line_buffering)"]),
301 check=True,
302 capture_output=True,
303 )
304 self.assertIn(b"False", result.stdout)
305
306 def test_u_option_sets_unbuffered_stdin(self):
307 result = subprocess.run(
308 [sys.executable, "-u", "-c", "import sys;print(sys.stdin.line_buffering)"],
309 check=True,
310 capture_output=True,
311 )
312 self.assertIn(b"False", result.stdout)
313
314
315class RunTest(unittest.TestCase):
316 def test_builtins_of_dunder_main_is_module(self):
317 from types import ModuleType
318
319 main = sys.modules["__main__"]
320 self.assertIsInstance(main.__builtins__, ModuleType)
321
322 def test_with_directory_executes_code(self):
323 with TemporaryDirectory() as tempdir:
324 tempfile = os.path.join(tempdir, "__main__.py")
325 tempfile = os.path.abspath(tempfile)
326 with open(tempfile, "w") as fp:
327 fp.write("print('test directory executed')\n")
328 result = subprocess.run(
329 [sys.executable, tempdir],
330 check=True,
331 capture_output=True,
332 encoding="utf-8",
333 )
334 self.assertEqual(result.returncode, 0)
335 self.assertIn("test directory executed", result.stdout)
336
337 def test_with_directory_reports_cant_find_dunder_main(self):
338 with TemporaryDirectory() as tempdir:
339 tempfile = os.path.join(tempdir, "sample.py")
340 tempfile = os.path.abspath(tempfile)
341 with open(tempfile, "w") as fp:
342 fp.write("print('test file executed')\n")
343 result = subprocess.run([sys.executable, tempdir], capture_output=True)
344 self.assertIn(b"can't find '__main__' module in ", result.stderr)
345 self.assertEqual(1, result.returncode)
346
347 def test_with_fifo_executes_code(self):
348 with TemporaryDirectory() as tempdir:
349 fifoname = f"{tempdir}/fifo"
350 os.mkfifo(fifoname)
351 proc = subprocess.Popen(
352 [sys.executable, fifoname],
353 stdout=subprocess.PIPE,
354 stderr=subprocess.PIPE,
355 )
356 with open(fifoname, "w") as fp:
357 fp.write(f"# l{'o' * 10000}ng comment\n")
358 fp.write("print('testing 1,2,3')\n")
359 stdout, stderr = proc.communicate()
360 self.assertEqual(proc.returncode, 0)
361 self.assertEqual(stderr, b"")
362 self.assertEqual(stdout, b"testing 1,2,3\n")
363
364 def test_with_file_executes_code(self):
365 with TemporaryDirectory() as tempdir:
366 tempfile = os.path.join(tempdir, "foo.py")
367 tempfile = os.path.abspath(tempfile)
368 with open(tempfile, "w") as fp:
369 fp.write("print('test fi' + 'le executed')\n")
370 fp.write("import sys\n")
371 fp.write("print('argv: ' + str(sys.argv))\n")
372 result = subprocess.run(
373 [sys.executable, tempfile, "arg0", "arg1 with spaces"],
374 check=True,
375 capture_output=True,
376 encoding="utf-8",
377 )
378 self.assertEqual(result.returncode, 0)
379 self.assertIn("test file executed", result.stdout)
380 self.assertIn(
381 f"argv: ['{tempfile}', 'arg0', 'arg1 with spaces']", result.stdout
382 )
383
384 def test_with_file_invalid_utf8_raises_syntax_error(self):
385 with TemporaryDirectory() as tempdir:
386 tempfile = os.path.join(tempdir, "bad_utf8.py")
387 with open(tempfile, "wb") as fp:
388 fp.write(b"print('Bad UTF8: \xf8\xa1\xa1\xa1\xa1'\n")
389 result = subprocess.run(
390 [sys.executable, tempfile],
391 capture_output=True,
392 encoding="utf-8",
393 )
394 self.assertIn("SyntaxError:", result.stderr)
395 self.assertEqual(result.returncode, 1)
396
397 def test_with_zipfile_executes_code(self):
398 with TemporaryDirectory() as tempdir:
399 tempzipfile = os.path.join(tempdir, "test.zip")
400 tempzipfile = os.path.abspath(tempzipfile)
401 with zipfile.ZipFile(tempzipfile, "w") as myzip:
402 myzip.writestr("__main__.py", "print('test zip file executed')\n")
403 result = subprocess.run(
404 [sys.executable, tempzipfile],
405 check=True,
406 capture_output=True,
407 encoding="utf-8",
408 )
409 self.assertIn("test zip file executed", result.stdout)
410
411 def test_with_zipfile_reports_cant_find_dunder_main(self):
412 with TemporaryDirectory() as tempdir:
413 tempzipfile = os.path.join(tempdir, "test.zip")
414 tempzipfile = os.path.abspath(tempzipfile)
415 with zipfile.ZipFile(tempzipfile, "w") as myzip:
416 myzip.writestr("test.py", "print('test zip file executed')\n")
417 result = subprocess.run(
418 [sys.executable, tempzipfile], capture_output=True, encoding="utf-8"
419 )
420 self.assertIn("can't find '__main__' module in", result.stderr)
421 self.assertEqual(1, result.returncode)
422
423
424if __name__ == "__main__":
425 unittest.main()