LEFT | RIGHT |
1 # Tests invocation of the interpreter with various command line arguments | 1 # Tests invocation of the interpreter with various command line arguments |
2 # Most tests are executed with environment variables ignored | 2 # Most tests are executed with environment variables ignored |
3 # See test_cmd_line_script.py for testing of script execution | 3 # See test_cmd_line_script.py for testing of script execution |
4 | 4 |
5 import test.support, unittest | 5 import test.support, unittest |
6 import os | 6 import os |
| 7 import shutil |
7 import sys | 8 import sys |
8 import subprocess | 9 import subprocess |
9 import tempfile | 10 import tempfile |
10 from test.script_helper import (spawn_python, kill_python, assert_python_ok, | 11 from test.script_helper import (spawn_python, kill_python, assert_python_ok, |
11 assert_python_failure) | 12 assert_python_failure) |
12 | 13 |
13 | 14 |
14 # XXX (ncoghlan): Move to script_helper and make consistent with run_python | 15 # XXX (ncoghlan): Move to script_helper and make consistent with run_python |
15 def _kill_python_and_exit_code(p): | 16 def _kill_python_and_exit_code(p): |
16 data = kill_python(p) | 17 data = kill_python(p) |
(...skipping 17 matching lines...) Expand all Loading... |
34 | 35 |
35 def test_site_flag(self): | 36 def test_site_flag(self): |
36 self.verify_valid_flag('-S') | 37 self.verify_valid_flag('-S') |
37 | 38 |
38 def test_usage(self): | 39 def test_usage(self): |
39 rc, out, err = assert_python_ok('-h') | 40 rc, out, err = assert_python_ok('-h') |
40 self.assertIn(b'usage', out) | 41 self.assertIn(b'usage', out) |
41 | 42 |
42 def test_version(self): | 43 def test_version(self): |
43 version = ('Python %d.%d' % sys.version_info[:2]).encode("ascii") | 44 version = ('Python %d.%d' % sys.version_info[:2]).encode("ascii") |
44 rc, out, err = assert_python_ok('-V') | 45 for switch in '-V', '--version': |
45 self.assertTrue(err.startswith(version)) | 46 rc, out, err = assert_python_ok(switch) |
| 47 self.assertFalse(err.startswith(version)) |
| 48 self.assertTrue(out.startswith(version)) |
46 | 49 |
47 def test_verbose(self): | 50 def test_verbose(self): |
48 # -v causes imports to write to stderr. If the write to | 51 # -v causes imports to write to stderr. If the write to |
49 # stderr itself causes an import to happen (for the output | 52 # stderr itself causes an import to happen (for the output |
50 # codec), a recursion loop can occur. | 53 # codec), a recursion loop can occur. |
51 rc, out, err = assert_python_ok('-v') | 54 rc, out, err = assert_python_ok('-v') |
52 self.assertNotIn(b'stack overflow', err) | 55 self.assertNotIn(b'stack overflow', err) |
53 rc, out, err = assert_python_ok('-vv') | 56 rc, out, err = assert_python_ok('-vv') |
54 self.assertNotIn(b'stack overflow', err) | 57 self.assertNotIn(b'stack overflow', err) |
55 | 58 |
56 def test_xoptions(self): | 59 def test_xoptions(self): |
57 rc, out, err = assert_python_ok('-c', 'import sys; print(sys._xoptions)'
) | 60 def get_xoptions(*args): |
58 opts = eval(out.splitlines()[0]) | 61 # use subprocess module directly because test.script_helper adds |
| 62 # "-X faulthandler" to the command line |
| 63 args = (sys.executable, '-E') + args |
| 64 args += ('-c', 'import sys; print(sys._xoptions)') |
| 65 out = subprocess.check_output(args) |
| 66 opts = eval(out.splitlines()[0]) |
| 67 return opts |
| 68 |
| 69 opts = get_xoptions() |
59 self.assertEqual(opts, {}) | 70 self.assertEqual(opts, {}) |
60 rc, out, err = assert_python_ok( | 71 |
61 '-Xa', '-Xb=c,d=e', '-c', 'import sys; print(sys._xoptions)') | 72 opts = get_xoptions('-Xa', '-Xb=c,d=e') |
62 opts = eval(out.splitlines()[0]) | |
63 self.assertEqual(opts, {'a': True, 'b': 'c,d=e'}) | 73 self.assertEqual(opts, {'a': True, 'b': 'c,d=e'}) |
| 74 |
| 75 def test_showrefcount(self): |
| 76 def run_python(*args): |
| 77 # this is similar to assert_python_ok but doesn't strip |
| 78 # the refcount from stderr. It can be replaced once |
| 79 # assert_python_ok stops doing that. |
| 80 cmd = [sys.executable] |
| 81 cmd.extend(args) |
| 82 PIPE = subprocess.PIPE |
| 83 p = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE) |
| 84 out, err = p.communicate() |
| 85 p.stdout.close() |
| 86 p.stderr.close() |
| 87 rc = p.returncode |
| 88 self.assertEqual(rc, 0) |
| 89 return rc, out, err |
| 90 code = 'import sys; print(sys._xoptions)' |
| 91 # normally the refcount is hidden |
| 92 rc, out, err = run_python('-c', code) |
| 93 self.assertEqual(out.rstrip(), b'{}') |
| 94 self.assertEqual(err, b'') |
| 95 # "-X showrefcount" shows the refcount, but only in debug builds |
| 96 rc, out, err = run_python('-X', 'showrefcount', '-c', code) |
| 97 self.assertEqual(out.rstrip(), b"{'showrefcount': True}") |
| 98 if hasattr(sys, 'gettotalrefcount'): # debug build |
| 99 self.assertRegex(err, br'^\[\d+ refs, \d+ blocks\]') |
| 100 else: |
| 101 self.assertEqual(err, b'') |
64 | 102 |
65 def test_run_module(self): | 103 def test_run_module(self): |
66 # Test expected operation of the '-m' switch | 104 # Test expected operation of the '-m' switch |
67 # Switch needs an argument | 105 # Switch needs an argument |
68 assert_python_failure('-m') | 106 assert_python_failure('-m') |
69 # Check we get an error for a nonexistent module | 107 # Check we get an error for a nonexistent module |
70 assert_python_failure('-m', 'fnord43520xyz') | 108 assert_python_failure('-m', 'fnord43520xyz') |
71 # Check the runpy module also gives an error for | 109 # Check the runpy module also gives an error for |
72 # a nonexistent module | 110 # a nonexistent module |
73 assert_python_failure('-m', 'runpy', 'fnord43520xyz'), | 111 assert_python_failure('-m', 'runpy', 'fnord43520xyz') |
74 # All good if module is located and run successfully | 112 # All good if module is located and run successfully |
75 assert_python_ok('-m', 'timeit', '-n', '1'), | 113 assert_python_ok('-m', 'timeit', '-n', '1') |
76 | 114 |
77 def test_run_module_bug1764407(self): | 115 def test_run_module_bug1764407(self): |
78 # -m and -i need to play well together | 116 # -m and -i need to play well together |
79 # Runs the timeit module and checks the __main__ | 117 # Runs the timeit module and checks the __main__ |
80 # namespace has been populated appropriately | 118 # namespace has been populated appropriately |
81 p = spawn_python('-i', '-m', 'timeit', '-n', '1') | 119 p = spawn_python('-i', '-m', 'timeit', '-n', '1') |
82 p.stdin.write(b'Timer\n') | 120 p.stdin.write(b'Timer\n') |
83 p.stdin.write(b'exit()\n') | 121 p.stdin.write(b'exit()\n') |
84 data = kill_python(p) | 122 data = kill_python(p) |
85 self.assertNotEqual(data.find(b'1 loop'), -1) | 123 self.assertNotEqual(data.find(b'1 loop'), -1) |
86 self.assertNotEqual(data.find(b'__main__.Timer'), -1) | 124 self.assertNotEqual(data.find(b'__main__.Timer'), -1) |
87 | 125 |
88 def test_run_code(self): | 126 def test_run_code(self): |
89 # Test expected operation of the '-c' switch | 127 # Test expected operation of the '-c' switch |
90 # Switch needs an argument | 128 # Switch needs an argument |
91 assert_python_failure('-c') | 129 assert_python_failure('-c') |
92 # Check we get an error for an uncaught exception | 130 # Check we get an error for an uncaught exception |
93 assert_python_failure('-c', 'raise Exception') | 131 assert_python_failure('-c', 'raise Exception') |
94 # All good if execution is successful | 132 # All good if execution is successful |
95 assert_python_ok('-c', 'pass') | 133 assert_python_ok('-c', 'pass') |
96 | 134 |
97 @unittest.skipUnless(test.support.FS_NONASCII, 'need support.FS_NONASCII') | 135 @unittest.skipUnless(test.support.FS_NONASCII, 'need support.FS_NONASCII') |
98 def test_non_ascii(self): | 136 def test_non_ascii(self): |
99 # Test handling of non-ascii data | 137 # Test handling of non-ascii data |
100 if test.support.verbose: | |
101 import locale | |
102 print('locale encoding = %s, filesystem encoding = %s' | |
103 % (locale.getpreferredencoding(), sys.getfilesystemencoding())
) | |
104 command = ("assert(ord(%r) == %s)" | 138 command = ("assert(ord(%r) == %s)" |
105 % (test.support.FS_NONASCII, ord(test.support.FS_NONASCII))) | 139 % (test.support.FS_NONASCII, ord(test.support.FS_NONASCII))) |
106 assert_python_ok('-c', command) | 140 assert_python_ok('-c', command) |
107 | 141 |
108 # On Windows, pass bytes to subprocess doesn't test how Python decodes the | 142 # On Windows, pass bytes to subprocess doesn't test how Python decodes the |
109 # command line, but how subprocess does decode bytes to unicode. Python | 143 # command line, but how subprocess does decode bytes to unicode. Python |
110 # doesn't decode the command line because Windows provides directly the | 144 # doesn't decode the command line because Windows provides directly the |
111 # arguments as unicode (using wmain() instead of main()). | 145 # arguments as unicode (using wmain() instead of main()). |
112 @unittest.skipIf(sys.platform == 'win32', | 146 @unittest.skipIf(sys.platform == 'win32', |
113 'Windows has a native unicode API') | 147 'Windows has a native unicode API') |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 import sys | 245 import sys |
212 path = ":".join(sys.path) | 246 path = ":".join(sys.path) |
213 path = path.encode("ascii", "backslashreplace") | 247 path = path.encode("ascii", "backslashreplace") |
214 sys.stdout.buffer.write(path)""" | 248 sys.stdout.buffer.write(path)""" |
215 rc, out, err = assert_python_ok('-S', '-c', code, | 249 rc, out, err = assert_python_ok('-S', '-c', code, |
216 PYTHONPATH=path) | 250 PYTHONPATH=path) |
217 self.assertIn(path1.encode('ascii'), out) | 251 self.assertIn(path1.encode('ascii'), out) |
218 self.assertIn(path2.encode('ascii'), out) | 252 self.assertIn(path2.encode('ascii'), out) |
219 | 253 |
220 def test_empty_PYTHONPATH_issue16309(self): | 254 def test_empty_PYTHONPATH_issue16309(self): |
221 """On Posix, it is documented that setting PATH to the | 255 # On Posix, it is documented that setting PATH to the |
222 empty string is equivalent to not setting PATH at all, | 256 # empty string is equivalent to not setting PATH at all, |
223 which is an exception to the rule that in a string like | 257 # which is an exception to the rule that in a string like |
224 "/bin::/usr/bin" the empty string in the middle gets | 258 # "/bin::/usr/bin" the empty string in the middle gets |
225 interpreted as '.'""" | 259 # interpreted as '.' |
226 code = """if 1: | 260 code = """if 1: |
227 import sys | 261 import sys |
228 path = ":".join(sys.path) | 262 path = ":".join(sys.path) |
229 path = path.encode("ascii", "backslashreplace") | 263 path = path.encode("ascii", "backslashreplace") |
230 sys.stdout.buffer.write(path)""" | 264 sys.stdout.buffer.write(path)""" |
231 rc1, out1, err1 = assert_python_ok('-c', code, PYTHONPATH="") | 265 rc1, out1, err1 = assert_python_ok('-c', code, PYTHONPATH="") |
232 rc2, out2, err2 = assert_python_ok('-c', code) | 266 rc2, out2, err2 = assert_python_ok('-c', code, __isolated=False) |
233 # regarding to Posix specification, outputs should be equal | 267 # regarding to Posix specification, outputs should be equal |
234 # for empty and unset PYTHONPATH | 268 # for empty and unset PYTHONPATH |
235 self.assertEquals(out1, out2) | 269 self.assertEqual(out1, out2) |
236 | 270 |
237 def test_displayhook_unencodable(self): | 271 def test_displayhook_unencodable(self): |
238 for encoding in ('ascii', 'latin-1', 'utf-8'): | 272 for encoding in ('ascii', 'latin-1', 'utf-8'): |
239 env = os.environ.copy() | 273 env = os.environ.copy() |
240 env['PYTHONIOENCODING'] = encoding | 274 env['PYTHONIOENCODING'] = encoding |
241 p = subprocess.Popen( | 275 p = subprocess.Popen( |
242 [sys.executable, '-i'], | 276 [sys.executable, '-i'], |
243 stdin=subprocess.PIPE, | 277 stdin=subprocess.PIPE, |
244 stdout=subprocess.PIPE, | 278 stdout=subprocess.PIPE, |
245 stderr=subprocess.STDOUT, | 279 stderr=subprocess.STDOUT, |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 # Issue #15001: PyRun_SimpleFileExFlags() did crash because it kept a | 414 # Issue #15001: PyRun_SimpleFileExFlags() did crash because it kept a |
381 # borrowed reference to the dict of __main__ module and later modify | 415 # borrowed reference to the dict of __main__ module and later modify |
382 # the dict whereas the module was destroyed | 416 # the dict whereas the module was destroyed |
383 filename = test.support.TESTFN | 417 filename = test.support.TESTFN |
384 self.addCleanup(test.support.unlink, filename) | 418 self.addCleanup(test.support.unlink, filename) |
385 with open(filename, "w") as script: | 419 with open(filename, "w") as script: |
386 print("import sys", file=script) | 420 print("import sys", file=script) |
387 print("del sys.modules['__main__']", file=script) | 421 print("del sys.modules['__main__']", file=script) |
388 assert_python_ok(filename) | 422 assert_python_ok(filename) |
389 | 423 |
390 | |
391 def test_unknown_options(self): | 424 def test_unknown_options(self): |
392 rc, out, err = assert_python_failure('-z', __cleanenv=True) | 425 rc, out, err = assert_python_failure('-E', '-z') |
393 self.assertIn(b'Unknown option', err) | 426 self.assertIn(b'Unknown option: -z', err) |
394 self.assertEqual(err.splitlines().count(b'Unknown option: -z'), 1) | 427 self.assertEqual(err.splitlines().count(b'Unknown option: -z'), 1) |
395 self.assertEqual(b'', out) | 428 self.assertEqual(b'', out) |
| 429 # Add "without='-E'" to prevent _assert_python to append -E |
| 430 # to env_vars and change the output of stderr |
| 431 rc, out, err = assert_python_failure('-z', without='-E') |
| 432 self.assertIn(b'Unknown option: -z', err) |
| 433 self.assertEqual(err.splitlines().count(b'Unknown option: -z'), 1) |
| 434 self.assertEqual(b'', out) |
| 435 rc, out, err = assert_python_failure('-a', '-z', without='-E') |
| 436 self.assertIn(b'Unknown option: -a', err) |
| 437 # only the first unknown option is reported |
| 438 self.assertNotIn(b'Unknown option: -z', err) |
| 439 self.assertEqual(err.splitlines().count(b'Unknown option: -a'), 1) |
| 440 self.assertEqual(b'', out) |
| 441 |
| 442 |
| 443 def test_isolatedmode(self): |
| 444 self.verify_valid_flag('-I') |
| 445 self.verify_valid_flag('-IEs') |
| 446 rc, out, err = assert_python_ok('-I', '-c', |
| 447 'from sys import flags as f; ' |
| 448 'print(f.no_user_site, f.ignore_environment, f.isolated)', |
| 449 # dummyvar to prevent extranous -E |
| 450 dummyvar="") |
| 451 self.assertEqual(out.strip(), b'1 1 1') |
| 452 with test.support.temp_cwd() as tmpdir: |
| 453 fake = os.path.join(tmpdir, "uuid.py") |
| 454 main = os.path.join(tmpdir, "main.py") |
| 455 with open(fake, "w") as f: |
| 456 f.write("raise RuntimeError('isolated mode test')\n") |
| 457 with open(main, "w") as f: |
| 458 f.write("import uuid\n") |
| 459 f.write("print('ok')\n") |
| 460 self.assertRaises(subprocess.CalledProcessError, |
| 461 subprocess.check_output, |
| 462 [sys.executable, main], cwd=tmpdir, |
| 463 stderr=subprocess.DEVNULL) |
| 464 out = subprocess.check_output([sys.executable, "-I", main], |
| 465 cwd=tmpdir) |
| 466 self.assertEqual(out.strip(), b"ok") |
396 | 467 |
397 def test_main(): | 468 def test_main(): |
398 test.support.run_unittest(CmdLineTest) | 469 test.support.run_unittest(CmdLineTest) |
399 test.support.reap_children() | 470 test.support.reap_children() |
400 | 471 |
401 if __name__ == "__main__": | 472 if __name__ == "__main__": |
402 test_main() | 473 test_main() |
LEFT | RIGHT |