1 # tests command line execution of scripts 2 3 import contextlib 4 import importlib 5 import importlib.machinery 6 import zipimport 7 import unittest 8 import sys 9 import os 10 import os.path 11 import py_compile 12 import subprocess 13 import io 14 15 import textwrap 16 from test import support 17 from test.support.script_helper import ( 18 make_pkg, make_script, make_zip_pkg, make_zip_script, 19 assert_python_ok, assert_python_failure, spawn_python, kill_python) 20 21 verbose = support.verbose 22 23 example_args = ['test1', 'test2', 'test3'] 24 25 test_source = """\ 26 # Script may be run with optimisation enabled, so don't rely on assert 27 # statements being executed 28 def assertEqual(lhs, rhs): 29 if lhs != rhs: 30 raise AssertionError('%r != %r' % (lhs, rhs)) 31 def assertIdentical(lhs, rhs): 32 if lhs is not rhs: 33 raise AssertionError('%r is not %r' % (lhs, rhs)) 34 # Check basic code execution 35 result = ['Top level assignment'] 36 def f(): 37 result.append('Lower level reference') 38 f() 39 assertEqual(result, ['Top level assignment', 'Lower level reference']) 40 # Check population of magic variables 41 assertEqual(__name__, '__main__') 42 from importlib.machinery import BuiltinImporter 43 _loader = __loader__ if __loader__ is BuiltinImporter else type(__loader__) 44 print('__loader__==%a' % _loader) 45 print('__file__==%a' % __file__) 46 print('__cached__==%a' % __cached__) 47 print('__package__==%r' % __package__) 48 # Check PEP 451 details 49 import os.path 50 if __package__ is not None: 51 print('__main__ was located through the import system') 52 assertIdentical(__spec__.loader, __loader__) 53 expected_spec_name = os.path.splitext(os.path.basename(__file__))[0] 54 if __package__: 55 expected_spec_name = __package__ + "." + expected_spec_name 56 assertEqual(__spec__.name, expected_spec_name) 57 assertEqual(__spec__.parent, __package__) 58 assertIdentical(__spec__.submodule_search_locations, None) 59 assertEqual(__spec__.origin, __file__) 60 if __spec__.cached is not None: 61 assertEqual(__spec__.cached, __cached__) 62 # Check the sys module 63 import sys 64 assertIdentical(globals(), sys.modules[__name__].__dict__) 65 if __spec__ is not None: 66 # XXX: We're not currently making __main__ available under its real name 67 pass # assertIdentical(globals(), sys.modules[__spec__.name].__dict__) 68 from test import test_cmd_line_script 69 example_args_list = test_cmd_line_script.example_args 70 assertEqual(sys.argv[1:], example_args_list) 71 print('sys.argv[0]==%a' % sys.argv[0]) 72 print('sys.path[0]==%a' % sys.path[0]) 73 # Check the working directory 74 import os 75 print('cwd==%a' % os.getcwd()) 76 """ 77 78 def _make_test_script(script_dir, script_basename, source=test_source): 79 to_return = make_script(script_dir, script_basename, source) 80 importlib.invalidate_caches() 81 return to_return 82 83 def _make_test_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename, 84 source=test_source, depth=1): 85 to_return = make_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename, 86 source, depth) 87 importlib.invalidate_caches() 88 return to_return 89 90 # There's no easy way to pass the script directory in to get 91 # -m to work (avoiding that is the whole point of making 92 # directories and zipfiles executable!) 93 # So we fake it for testing purposes with a custom launch script 94 launch_source = """\ 95 import sys, os.path, runpy 96 sys.path.insert(0, %s) 97 runpy._run_module_as_main(%r) 98 """ 99 100 def _make_launch_script(script_dir, script_basename, module_name, path=None): 101 if path is None: 102 path = "os.path.dirname(__file__)" 103 else: 104 path = repr(path) 105 source = launch_source % (path, module_name) 106 to_return = make_script(script_dir, script_basename, source) 107 importlib.invalidate_caches() 108 return to_return 109 110 class CmdLineTest(unittest.TestCase): 111 def _check_output(self, script_name, exit_code, data, 112 expected_file, expected_argv0, 113 expected_path0, expected_package, 114 expected_loader): 115 if verbose > 1: 116 print("Output from test script %r:" % script_name) 117 print(repr(data)) 118 self.assertEqual(exit_code, 0) 119 printed_loader = '__loader__==%a' % expected_loader 120 printed_file = '__file__==%a' % expected_file 121 printed_package = '__package__==%r' % expected_package 122 printed_argv0 = 'sys.argv[0]==%a' % expected_argv0 123 printed_path0 = 'sys.path[0]==%a' % expected_path0 124 printed_cwd = 'cwd==%a' % os.getcwd() 125 if verbose > 1: 126 print('Expected output:') 127 print(printed_file) 128 print(printed_package) 129 print(printed_argv0) 130 print(printed_cwd) 131 self.assertIn(printed_loader.encode('utf-8'), data) 132 self.assertIn(printed_file.encode('utf-8'), data) 133 self.assertIn(printed_package.encode('utf-8'), data) 134 self.assertIn(printed_argv0.encode('utf-8'), data) 135 self.assertIn(printed_path0.encode('utf-8'), data) 136 self.assertIn(printed_cwd.encode('utf-8'), data) 137 138 def _check_script(self, script_name, expected_file, 139 expected_argv0, expected_path0, 140 expected_package, expected_loader, 141 *cmd_line_switches): 142 run_args = [*support.optim_args_from_interpreter_flags(), 143 *cmd_line_switches, script_name, *example_args] 144 rc, out, err = assert_python_ok(*run_args, __isolated=False) 145 self._check_output(script_name, rc, out + err, expected_file, 146 expected_argv0, expected_path0, 147 expected_package, expected_loader) 148 149 def _check_import_error(self, script_name, expected_msg, 150 *cmd_line_switches): 151 run_args = cmd_line_switches + (script_name,) 152 rc, out, err = assert_python_failure(*run_args) 153 if verbose > 1: 154 print('Output from test script %r:' % script_name) 155 print(repr(err)) 156 print('Expected output: %r' % expected_msg) 157 self.assertIn(expected_msg.encode('utf-8'), err) 158 159 def test_dash_c_loader(self): 160 rc, out, err = assert_python_ok("-c", "print(__loader__)") 161 expected = repr(importlib.machinery.BuiltinImporter).encode("utf-8") 162 self.assertIn(expected, out) 163 164 def test_stdin_loader(self): 165 # Unfortunately, there's no way to automatically test the fully 166 # interactive REPL, since that code path only gets executed when 167 # stdin is an interactive tty. 168 p = spawn_python() 169 try: 170 p.stdin.write(b"print(__loader__)\n") 171 p.stdin.flush() 172 finally: 173 out = kill_python(p) 174 expected = repr(importlib.machinery.BuiltinImporter).encode("utf-8") 175 self.assertIn(expected, out) 176 177 @contextlib.contextmanager 178 def interactive_python(self, separate_stderr=False): 179 if separate_stderr: 180 p = spawn_python('-i', bufsize=1, stderr=subprocess.PIPE) 181 stderr = p.stderr 182 else: 183 p = spawn_python('-i', bufsize=1, stderr=subprocess.STDOUT) 184 stderr = p.stdout 185 try: 186 # Drain stderr until prompt 187 while True: 188 data = stderr.read(4) 189 if data == b">>> ": 190 break 191 stderr.readline() 192 yield p 193 finally: 194 kill_python(p) 195 stderr.close() 196 197 def check_repl_stdout_flush(self, separate_stderr=False): 198 with self.interactive_python(separate_stderr) as p: 199 p.stdin.write(b"print('foo')\n") 200 p.stdin.flush() 201 self.assertEqual(b'foo', p.stdout.readline().strip()) 202 203 def check_repl_stderr_flush(self, separate_stderr=False): 204 with self.interactive_python(separate_stderr) as p: 205 p.stdin.write(b"1/0\n") 206 p.stdin.flush() 207 stderr = p.stderr if separate_stderr else p.stdout 208 self.assertIn(b'Traceback ', stderr.readline()) 209 self.assertIn(b'File "<stdin>"', stderr.readline()) 210 self.assertIn(b'ZeroDivisionError', stderr.readline()) 211 212 def test_repl_stdout_flush(self): 213 self.check_repl_stdout_flush() 214 215 def test_repl_stdout_flush_separate_stderr(self): 216 self.check_repl_stdout_flush(True) 217 218 def test_repl_stderr_flush(self): 219 self.check_repl_stderr_flush() 220 221 def test_repl_stderr_flush_separate_stderr(self): 222 self.check_repl_stderr_flush(True) 223 224 def test_basic_script(self): 225 with support.temp_dir() as script_dir: 226 script_name = _make_test_script(script_dir, 'script') 227 self._check_script(script_name, script_name, script_name, 228 script_dir, None, 229 importlib.machinery.SourceFileLoader) 230 231 def test_script_compiled(self): 232 with support.temp_dir() as script_dir: 233 script_name = _make_test_script(script_dir, 'script') 234 py_compile.compile(script_name, doraise=True) 235 os.remove(script_name) 236 pyc_file = support.make_legacy_pyc(script_name) 237 self._check_script(pyc_file, pyc_file, 238 pyc_file, script_dir, None, 239 importlib.machinery.SourcelessFileLoader) 240 241 def test_directory(self): 242 with support.temp_dir() as script_dir: 243 script_name = _make_test_script(script_dir, '__main__') 244 self._check_script(script_dir, script_name, script_dir, 245 script_dir, '', 246 importlib.machinery.SourceFileLoader) 247 248 def test_directory_compiled(self): 249 with support.temp_dir() as script_dir: 250 script_name = _make_test_script(script_dir, '__main__') 251 py_compile.compile(script_name, doraise=True) 252 os.remove(script_name) 253 pyc_file = support.make_legacy_pyc(script_name) 254 self._check_script(script_dir, pyc_file, script_dir, 255 script_dir, '', 256 importlib.machinery.SourcelessFileLoader) 257 258 def test_directory_error(self): 259 with support.temp_dir() as script_dir: 260 msg = "can't find '__main__' module in %r" % script_dir 261 self._check_import_error(script_dir, msg) 262 263 def test_zipfile(self): 264 with support.temp_dir() as script_dir: 265 script_name = _make_test_script(script_dir, '__main__') 266 zip_name, run_name = make_zip_script(script_dir, 'test_zip', script_name) 267 self._check_script(zip_name, run_name, zip_name, zip_name, '', 268 zipimport.zipimporter) 269 270 def test_zipfile_compiled(self): 271 with support.temp_dir() as script_dir: 272 script_name = _make_test_script(script_dir, '__main__') 273 compiled_name = py_compile.compile(script_name, doraise=True) 274 zip_name, run_name = make_zip_script(script_dir, 'test_zip', compiled_name) 275 self._check_script(zip_name, run_name, zip_name, zip_name, '', 276 zipimport.zipimporter) 277 278 def test_zipfile_error(self): 279 with support.temp_dir() as script_dir: 280 script_name = _make_test_script(script_dir, 'not_main') 281 zip_name, run_name = make_zip_script(script_dir, 'test_zip', script_name) 282 msg = "can't find '__main__' module in %r" % zip_name 283 self._check_import_error(zip_name, msg) 284 285 def test_module_in_package(self): 286 with support.temp_dir() as script_dir: 287 pkg_dir = os.path.join(script_dir, 'test_pkg') 288 make_pkg(pkg_dir) 289 script_name = _make_test_script(pkg_dir, 'script') 290 launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.script') 291 self._check_script(launch_name, script_name, script_name, 292 script_dir, 'test_pkg', 293 importlib.machinery.SourceFileLoader) 294 295 def test_module_in_package_in_zipfile(self): 296 with support.temp_dir() as script_dir: 297 zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script') 298 launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.script', zip_name) 299 self._check_script(launch_name, run_name, run_name, 300 zip_name, 'test_pkg', zipimport.zipimporter) 301 302 def test_module_in_subpackage_in_zipfile(self): 303 with support.temp_dir() as script_dir: 304 zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script', depth=2) 305 launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.test_pkg.script', zip_name) 306 self._check_script(launch_name, run_name, run_name, 307 zip_name, 'test_pkg.test_pkg', 308 zipimport.zipimporter) 309 310 def test_package(self): 311 with support.temp_dir() as script_dir: 312 pkg_dir = os.path.join(script_dir, 'test_pkg') 313 make_pkg(pkg_dir) 314 script_name = _make_test_script(pkg_dir, '__main__') 315 launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg') 316 self._check_script(launch_name, script_name, 317 script_name, script_dir, 'test_pkg', 318 importlib.machinery.SourceFileLoader) 319 320 def test_package_compiled(self): 321 with support.temp_dir() as script_dir: 322 pkg_dir = os.path.join(script_dir, 'test_pkg') 323 make_pkg(pkg_dir) 324 script_name = _make_test_script(pkg_dir, '__main__') 325 compiled_name = py_compile.compile(script_name, doraise=True) 326 os.remove(script_name) 327 pyc_file = support.make_legacy_pyc(script_name) 328 launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg') 329 self._check_script(launch_name, pyc_file, 330 pyc_file, script_dir, 'test_pkg', 331 importlib.machinery.SourcelessFileLoader) 332 333 def test_package_error(self): 334 with support.temp_dir() as script_dir: 335 pkg_dir = os.path.join(script_dir, 'test_pkg') 336 make_pkg(pkg_dir) 337 msg = ("'test_pkg' is a package and cannot " 338 "be directly executed") 339 launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg') 340 self._check_import_error(launch_name, msg) 341 342 def test_package_recursion(self): 343 with support.temp_dir() as script_dir: 344 pkg_dir = os.path.join(script_dir, 'test_pkg') 345 make_pkg(pkg_dir) 346 main_dir = os.path.join(pkg_dir, '__main__') 347 make_pkg(main_dir) 348 msg = ("Cannot use package as __main__ module; " 349 "'test_pkg' is a package and cannot " 350 "be directly executed") 351 launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg') 352 self._check_import_error(launch_name, msg) 353 354 def test_issue8202(self): 355 # Make sure package __init__ modules see "-m" in sys.argv0 while 356 # searching for the module to execute 357 with support.temp_dir() as script_dir: 358 with support.change_cwd(path=script_dir): 359 pkg_dir = os.path.join(script_dir, 'test_pkg') 360 make_pkg(pkg_dir, "import sys; print('init_argv0==%r' % sys.argv[0])") 361 script_name = _make_test_script(pkg_dir, 'script') 362 rc, out, err = assert_python_ok('-m', 'test_pkg.script', *example_args, __isolated=False) 363 if verbose > 1: 364 print(repr(out)) 365 expected = "init_argv0==%r" % '-m' 366 self.assertIn(expected.encode('utf-8'), out) 367 self._check_output(script_name, rc, out, 368 script_name, script_name, '', 'test_pkg', 369 importlib.machinery.SourceFileLoader) 370 371 def test_issue8202_dash_c_file_ignored(self): 372 # Make sure a "-c" file in the current directory 373 # does not alter the value of sys.path[0] 374 with support.temp_dir() as script_dir: 375 with support.change_cwd(path=script_dir): 376 with open("-c", "w") as f: 377 f.write("data") 378 rc, out, err = assert_python_ok('-c', 379 'import sys; print("sys.path[0]==%r" % sys.path[0])', 380 __isolated=False) 381 if verbose > 1: 382 print(repr(out)) 383 expected = "sys.path[0]==%r" % '' 384 self.assertIn(expected.encode('utf-8'), out) 385 386 def test_issue8202_dash_m_file_ignored(self): 387 # Make sure a "-m" file in the current directory 388 # does not alter the value of sys.path[0] 389 with support.temp_dir() as script_dir: 390 script_name = _make_test_script(script_dir, 'other') 391 with support.change_cwd(path=script_dir): 392 with open("-m", "w") as f: 393 f.write("data") 394 rc, out, err = assert_python_ok('-m', 'other', *example_args, 395 __isolated=False) 396 self._check_output(script_name, rc, out, 397 script_name, script_name, '', '', 398 importlib.machinery.SourceFileLoader) 399 400 @contextlib.contextmanager 401 def setup_test_pkg(self, *args): 402 with support.temp_dir() as script_dir, \ 403 support.change_cwd(path=script_dir): 404 pkg_dir = os.path.join(script_dir, 'test_pkg') 405 make_pkg(pkg_dir, *args) 406 yield pkg_dir 407 408 def check_dash_m_failure(self, *args): 409 rc, out, err = assert_python_failure('-m', *args, __isolated=False) 410 if verbose > 1: 411 print(repr(out)) 412 self.assertEqual(rc, 1) 413 return err 414 415 def test_dash_m_error_code_is_one(self): 416 # If a module is invoked with the -m command line flag 417 # and results in an error that the return code to the 418 # shell is '1' 419 with self.setup_test_pkg() as pkg_dir: 420 script_name = _make_test_script(pkg_dir, 'other', 421 "if __name__ == '__main__': raise ValueError") 422 err = self.check_dash_m_failure('test_pkg.other', *example_args) 423 self.assertIn(b'ValueError', err) 424 425 def test_dash_m_errors(self): 426 # Exercise error reporting for various invalid package executions 427 tests = ( 428 ('builtins', br'No code object available'), 429 ('builtins.x', br'Error while finding module specification.*' 430 br'AttributeError'), 431 ('builtins.x.y', br'Error while finding module specification.*' 432 br'ModuleNotFoundError.*No module named.*not a package'), 433 ('os.path', br'loader.*cannot handle'), 434 ('importlib', br'No module named.*' 435 br'is a package and cannot be directly executed'), 436 ('importlib.nonexistant', br'No module named'), 437 ('.unittest', br'Relative module names not supported'), 438 ) 439 for name, regex in tests: 440 with self.subTest(name): 441 rc, _, err = assert_python_failure('-m', name) 442 self.assertEqual(rc, 1) 443 self.assertRegex(err, regex) 444 self.assertNotIn(b'Traceback', err) 445 446 def test_dash_m_bad_pyc(self): 447 with support.temp_dir() as script_dir, \ 448 support.change_cwd(path=script_dir): 449 os.mkdir('test_pkg') 450 # Create invalid *.pyc as empty file 451 with open('test_pkg/__init__.pyc', 'wb'): 452 pass 453 err = self.check_dash_m_failure('test_pkg') 454 self.assertRegex(err, 455 br'Error while finding module specification.*' 456 br'ImportError.*bad magic number') 457 self.assertNotIn(b'is a package', err) 458 self.assertNotIn(b'Traceback', err) 459 460 def test_dash_m_init_traceback(self): 461 # These were wrapped in an ImportError and tracebacks were 462 # suppressed; see Issue 14285 463 exceptions = (ImportError, AttributeError, TypeError, ValueError) 464 for exception in exceptions: 465 exception = exception.__name__ 466 init = "raise {0}('Exception in __init__.py')".format(exception) 467 with self.subTest(exception), \ 468 self.setup_test_pkg(init) as pkg_dir: 469 err = self.check_dash_m_failure('test_pkg') 470 self.assertIn(exception.encode('ascii'), err) 471 self.assertIn(b'Exception in __init__.py', err) 472 self.assertIn(b'Traceback', err) 473 474 def test_dash_m_main_traceback(self): 475 # Ensure that an ImportError's traceback is reported 476 with self.setup_test_pkg() as pkg_dir: 477 main = "raise ImportError('Exception in __main__ module')" 478 _make_test_script(pkg_dir, '__main__', main) 479 err = self.check_dash_m_failure('test_pkg') 480 self.assertIn(b'ImportError', err) 481 self.assertIn(b'Exception in __main__ module', err) 482 self.assertIn(b'Traceback', err) 483 484 def test_pep_409_verbiage(self): 485 # Make sure PEP 409 syntax properly suppresses 486 # the context of an exception 487 script = textwrap.dedent("""\ 488 try: 489 raise ValueError 490 except: 491 raise NameError from None 492 """) 493 with support.temp_dir() as script_dir: 494 script_name = _make_test_script(script_dir, 'script', script) 495 exitcode, stdout, stderr = assert_python_failure(script_name) 496 text = stderr.decode('ascii').split('\n') 497 self.assertEqual(len(text), 4) 498 self.assertTrue(text[0].startswith('Traceback')) 499 self.assertTrue(text[1].startswith(' File ')) 500 self.assertTrue(text[3].startswith('NameError')) 501 502 def test_non_ascii(self): 503 # Mac OS X denies the creation of a file with an invalid UTF-8 name. 504 # Windows allows creating a name with an arbitrary bytes name, but 505 # Python cannot a undecodable bytes argument to a subprocess. 506 if (support.TESTFN_UNDECODABLE 507 and sys.platform not in ('win32', 'darwin')): 508 name = os.fsdecode(support.TESTFN_UNDECODABLE) 509 elif support.TESTFN_NONASCII: 510 name = support.TESTFN_NONASCII 511 else: 512 self.skipTest("need support.TESTFN_NONASCII") 513 514 # Issue #16218 515 source = 'print(ascii(__file__))\n' 516 script_name = _make_test_script(os.curdir, name, source) 517 self.addCleanup(support.unlink, script_name) 518 rc, stdout, stderr = assert_python_ok(script_name) 519 self.assertEqual( 520 ascii(script_name), 521 stdout.rstrip().decode('ascii'), 522 'stdout=%r stderr=%r' % (stdout, stderr)) 523 self.assertEqual(0, rc) 524 525 def test_issue20500_exit_with_exception_value(self): 526 script = textwrap.dedent("""\ 527 import sys 528 error = None 529 try: 530 raise ValueError('some text') 531 except ValueError as err: 532 error = err 533 534 if error: 535 sys.exit(error) 536 """) 537 with support.temp_dir() as script_dir: 538 script_name = _make_test_script(script_dir, 'script', script) 539 exitcode, stdout, stderr = assert_python_failure(script_name) 540 text = stderr.decode('ascii') 541 self.assertEqual(text, "some text") 542 543 def test_syntaxerror_unindented_caret_position(self): 544 script = "1 + 1 = 2\n" 545 with support.temp_dir() as script_dir: 546 script_name = _make_test_script(script_dir, 'script', script) 547 exitcode, stdout, stderr = assert_python_failure(script_name) 548 text = io.TextIOWrapper(io.BytesIO(stderr), 'ascii').read() 549 # Confirm that the caret is located under the first 1 character 550 self.assertIn("\n 1 + 1 = 2\n ^", text) 551 552 def test_syntaxerror_indented_caret_position(self): 553 script = textwrap.dedent("""\ 554 if True: 555 1 + 1 = 2 556 """) 557 with support.temp_dir() as script_dir: 558 script_name = _make_test_script(script_dir, 'script', script) 559 exitcode, stdout, stderr = assert_python_failure(script_name) 560 text = io.TextIOWrapper(io.BytesIO(stderr), 'ascii').read() 561 # Confirm that the caret is located under the first 1 character 562 self.assertIn("\n 1 + 1 = 2\n ^", text) 563 564 # Try the same with a form feed at the start of the indented line 565 script = ( 566 "if True:\n" 567 "\f 1 + 1 = 2\n" 568 ) 569 script_name = _make_test_script(script_dir, "script", script) 570 exitcode, stdout, stderr = assert_python_failure(script_name) 571 text = io.TextIOWrapper(io.BytesIO(stderr), "ascii").read() 572 self.assertNotIn("\f", text) 573 self.assertIn("\n 1 + 1 = 2\n ^", text) 574 575 def test_consistent_sys_path_for_direct_execution(self): 576 # This test case ensures that the following all give the same 577 # sys.path configuration: 578 # 579 # ./python -s script_dir/__main__.py 580 # ./python -s script_dir 581 # ./python -I script_dir 582 script = textwrap.dedent("""\ 583 import sys 584 for entry in sys.path: 585 print(entry) 586 """) 587 # Always show full path diffs on errors 588 self.maxDiff = None 589 with support.temp_dir() as work_dir, support.temp_dir() as script_dir: 590 script_name = _make_test_script(script_dir, '__main__', script) 591 # Reference output comes from directly executing __main__.py 592 # We omit PYTHONPATH and user site to align with isolated mode 593 p = spawn_python("-Es", script_name, cwd=work_dir) 594 out_by_name = kill_python(p).decode().splitlines() 595 self.assertEqual(out_by_name[0], script_dir) 596 self.assertNotIn(work_dir, out_by_name) 597 # Directory execution should give the same output 598 p = spawn_python("-Es", script_dir, cwd=work_dir) 599 out_by_dir = kill_python(p).decode().splitlines() 600 self.assertEqual(out_by_dir, out_by_name) 601 # As should directory execution in isolated mode 602 p = spawn_python("-I", script_dir, cwd=work_dir) 603 out_by_dir_isolated = kill_python(p).decode().splitlines() 604 self.assertEqual(out_by_dir_isolated, out_by_dir, out_by_name) 605 606 def test_consistent_sys_path_for_module_execution(self): 607 # This test case ensures that the following both give the same 608 # sys.path configuration: 609 # ./python -sm script_pkg.__main__ 610 # ./python -sm script_pkg 611 # 612 # And that this fails as unable to find the package: 613 # ./python -Im script_pkg 614 script = textwrap.dedent("""\ 615 import sys 616 for entry in sys.path: 617 print(entry) 618 """) 619 # Always show full path diffs on errors 620 self.maxDiff = None 621 with support.temp_dir() as work_dir: 622 script_dir = os.path.join(work_dir, "script_pkg") 623 os.mkdir(script_dir) 624 script_name = _make_test_script(script_dir, '__main__', script) 625 # Reference output comes from `-m script_pkg.__main__` 626 # We omit PYTHONPATH and user site to better align with the 627 # direct execution test cases 628 p = spawn_python("-sm", "script_pkg.__main__", cwd=work_dir) 629 out_by_module = kill_python(p).decode().splitlines() 630 self.assertEqual(out_by_module[0], '') 631 self.assertNotIn(script_dir, out_by_module) 632 # Package execution should give the same output 633 p = spawn_python("-sm", "script_pkg", cwd=work_dir) 634 out_by_package = kill_python(p).decode().splitlines() 635 self.assertEqual(out_by_package, out_by_module) 636 # Isolated mode should fail with an import error 637 exitcode, stdout, stderr = assert_python_failure( 638 "-Im", "script_pkg", cwd=work_dir 639 ) 640 traceback_lines = stderr.decode().splitlines() 641 self.assertIn("No module named script_pkg", traceback_lines[-1]) 642 643 def test_main(): 644 support.run_unittest(CmdLineTest) 645 support.reap_children() 646 647 if __name__ == '__main__': 648 test_main() 649