Show More
@@ -2355,19 +2355,31 b' class InteractiveShell(SingletonConfigurable):' | |||||
2355 | ec = os.system(cmd) |
|
2355 | ec = os.system(cmd) | |
2356 | else: |
|
2356 | else: | |
2357 | cmd = py3compat.unicode_to_str(cmd) |
|
2357 | cmd = py3compat.unicode_to_str(cmd) | |
2358 | # Call the cmd using the OS shell, instead of the default /bin/sh, if set. |
|
2358 | # For posix the result of the subprocess.call() below is an exit | |
2359 | ec = subprocess.call(cmd, shell=True, executable=os.environ.get('SHELL', None)) |
|
2359 | # code, which by convention is zero for success, positive for | |
2360 | # exit code is positive for program failure, or negative for |
|
2360 | # program failure. Exit codes above 128 are reserved for signals, | |
2361 | # terminating signal number. |
|
2361 | # and the formula for converting a signal to an exit code is usually | |
2362 |
|
2362 | # signal_number+128. To more easily differentiate between exit | ||
2363 | # Interpret ec > 128 as signal |
|
2363 | # codes and signals, ipython uses negative numbers. For instance | |
2364 | # Some shells (csh, fish) don't follow sh/bash conventions for exit codes |
|
2364 | # since control-c is signal 2 but exit code 130, ipython's | |
|
2365 | # _exit_code variable will read -2. Note that some shells like | |||
|
2366 | # csh and fish don't follow sh/bash conventions for exit codes. | |||
|
2367 | executable = os.environ.get('SHELL', None) | |||
|
2368 | try: | |||
|
2369 | # Use env shell instead of default /bin/sh | |||
|
2370 | ec = subprocess.call(cmd, shell=True, executable=executable) | |||
|
2371 | except KeyboardInterrupt: | |||
|
2372 | # intercept control-C; a long traceback is not useful here | |||
|
2373 | self.write_err("\nKeyboardInterrupt\n") | |||
|
2374 | ec = 130 | |||
2365 | if ec > 128: |
|
2375 | if ec > 128: | |
2366 | ec = -(ec - 128) |
|
2376 | ec = -(ec - 128) | |
2367 |
|
2377 | |||
2368 | # We explicitly do NOT return the subprocess status code, because |
|
2378 | # We explicitly do NOT return the subprocess status code, because | |
2369 | # a non-None value would trigger :func:`sys.displayhook` calls. |
|
2379 | # a non-None value would trigger :func:`sys.displayhook` calls. | |
2370 | # Instead, we store the exit_code in user_ns. |
|
2380 | # Instead, we store the exit_code in user_ns. Note the semantics | |
|
2381 | # of _exit_code: for control-c, _exit_code == -signal.SIGNIT, | |||
|
2382 | # but raising SystemExit(_exit_code) will give status 254! | |||
2371 | self.user_ns['_exit_code'] = ec |
|
2383 | self.user_ns['_exit_code'] = ec | |
2372 |
|
2384 | |||
2373 | # use piped system by default, because it is better behaved |
|
2385 | # use piped system by default, because it is better behaved |
@@ -544,6 +544,16 b' class TestSystemRaw(unittest.TestCase, ExitCodeChecks):' | |||||
544 | cmd = u'''python -c "'åäö'" ''' |
|
544 | cmd = u'''python -c "'åäö'" ''' | |
545 | ip.system_raw(cmd) |
|
545 | ip.system_raw(cmd) | |
546 |
|
546 | |||
|
547 | @mock.patch('subprocess.call') | |||
|
548 | def test_control_c(self, call_mock): | |||
|
549 | call_mock.side_effect = KeyboardInterrupt() | |||
|
550 | try: | |||
|
551 | self.system("sleep 1 # wont happen") | |||
|
552 | except KeyboardInterrupt: | |||
|
553 | self.fail("system call should intercept " | |||
|
554 | "keyboard interrupt from subprocess.call") | |||
|
555 | self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGINT) | |||
|
556 | ||||
547 | # TODO: Exit codes are currently ignored on Windows. |
|
557 | # TODO: Exit codes are currently ignored on Windows. | |
548 | class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks): |
|
558 | class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks): | |
549 | system = ip.system_piped |
|
559 | system = ip.system_piped |
General Comments 0
You need to be logged in to leave comments.
Login now