Show More
@@ -29,6 +29,7 import runpy | |||||
29 | import sys |
|
29 | import sys | |
30 | import tempfile |
|
30 | import tempfile | |
31 | import types |
|
31 | import types | |
|
32 | import subprocess | |||
32 | from io import open as io_open |
|
33 | from io import open as io_open | |
33 |
|
34 | |||
34 | from IPython.config.configurable import SingletonConfigurable |
|
35 | from IPython.config.configurable import SingletonConfigurable | |
@@ -2232,7 +2233,8 class InteractiveShell(SingletonConfigurable): | |||||
2232 | self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1)) |
|
2233 | self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1)) | |
2233 |
|
2234 | |||
2234 | def system_raw(self, cmd): |
|
2235 | def system_raw(self, cmd): | |
2235 | """Call the given cmd in a subprocess using os.system |
|
2236 | """Call the given cmd in a subprocess using os.system on Windows or | |
|
2237 | subprocess.call using the system shell on other platforms. | |||
2236 |
|
2238 | |||
2237 | Parameters |
|
2239 | Parameters | |
2238 | ---------- |
|
2240 | ---------- | |
@@ -2250,11 +2252,10 class InteractiveShell(SingletonConfigurable): | |||||
2250 | ec = os.system(cmd) |
|
2252 | ec = os.system(cmd) | |
2251 | else: |
|
2253 | else: | |
2252 | cmd = py3compat.unicode_to_str(cmd) |
|
2254 | cmd = py3compat.unicode_to_str(cmd) | |
2253 | ec = os.system(cmd) |
|
2255 | # Call the cmd using the OS shell, instead of the default /bin/sh, if set. | |
2254 | # The high byte is the exit code, the low byte is a signal number |
|
2256 | ec = subprocess.call(cmd, shell=True, executable=os.environ.get('SHELL', None)) | |
2255 | # that we discard for now. See the docs for os.wait() |
|
2257 | # exit code is positive for program failure, or negative for | |
2256 | if ec > 255: |
|
2258 | # terminating signal number. | |
2257 | ec >>= 8 |
|
|||
2258 |
|
2259 | |||
2259 | # We explicitly do NOT return the subprocess status code, because |
|
2260 | # We explicitly do NOT return the subprocess status code, because | |
2260 | # a non-None value would trigger :func:`sys.displayhook` calls. |
|
2261 | # a non-None value would trigger :func:`sys.displayhook` calls. |
@@ -22,6 +22,7 Authors | |||||
22 | # stdlib |
|
22 | # stdlib | |
23 | import ast |
|
23 | import ast | |
24 | import os |
|
24 | import os | |
|
25 | import signal | |||
25 | import shutil |
|
26 | import shutil | |
26 | import sys |
|
27 | import sys | |
27 | import tempfile |
|
28 | import tempfile | |
@@ -33,7 +34,7 from StringIO import StringIO | |||||
33 | import nose.tools as nt |
|
34 | import nose.tools as nt | |
34 |
|
35 | |||
35 | # Our own |
|
36 | # Our own | |
36 | from IPython.testing.decorators import skipif, onlyif_unicode_paths |
|
37 | from IPython.testing.decorators import skipif, skip_win32, onlyif_unicode_paths | |
37 | from IPython.testing import tools as tt |
|
38 | from IPython.testing import tools as tt | |
38 | from IPython.utils import io |
|
39 | from IPython.utils import io | |
39 |
|
40 | |||
@@ -414,19 +415,48 class TestSafeExecfileNonAsciiPath(unittest.TestCase): | |||||
414 | """ |
|
415 | """ | |
415 | ip.safe_execfile(self.fname, {}, raise_exceptions=True) |
|
416 | ip.safe_execfile(self.fname, {}, raise_exceptions=True) | |
416 |
|
417 | |||
|
418 | class ExitCodeChecks(tt.TempFileMixin): | |||
|
419 | def test_exit_code_ok(self): | |||
|
420 | self.system('exit 0') | |||
|
421 | self.assertEqual(ip.user_ns['_exit_code'], 0) | |||
|
422 | ||||
|
423 | def test_exit_code_error(self): | |||
|
424 | self.system('exit 1') | |||
|
425 | self.assertEqual(ip.user_ns['_exit_code'], 1) | |||
|
426 | ||||
|
427 | @skipif(not hasattr(signal, 'SIGALRM')) | |||
|
428 | def test_exit_code_signal(self): | |||
|
429 | self.mktmp("import signal, time\n" | |||
|
430 | "signal.setitimer(signal.ITIMER_REAL, 0.1)\n" | |||
|
431 | "time.sleep(1)\n") | |||
|
432 | self.system("%s %s" % (sys.executable, self.fname)) | |||
|
433 | self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM) | |||
|
434 | ||||
|
435 | class TestSystemRaw(unittest.TestCase, ExitCodeChecks): | |||
|
436 | system = ip.system_raw | |||
417 |
|
437 | |||
418 | class TestSystemRaw(unittest.TestCase): |
|
|||
419 | @onlyif_unicode_paths |
|
438 | @onlyif_unicode_paths | |
420 | def test_1(self): |
|
439 | def test_1(self): | |
421 | """Test system_raw with non-ascii cmd |
|
440 | """Test system_raw with non-ascii cmd | |
422 | """ |
|
441 | """ | |
423 |
cmd = u |
|
442 | cmd = u'''python -c "'åäö'" ''' | |
424 | ip.system_raw(cmd) |
|
443 | ip.system_raw(cmd) | |
425 |
|
444 | |||
426 | def test_exit_code(self): |
|
445 | # TODO: Exit codes are currently ignored on Windows. | |
427 | """Test that the exit code is parsed correctly.""" |
|
446 | class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks): | |
428 | ip.system_raw('exit 1') |
|
447 | system = ip.system_piped | |
429 | self.assertEqual(ip.user_ns['_exit_code'], 1) |
|
448 | ||
|
449 | @skip_win32 | |||
|
450 | def test_exit_code_ok(self): | |||
|
451 | ExitCodeChecks.test_exit_code_ok(self) | |||
|
452 | ||||
|
453 | @skip_win32 | |||
|
454 | def test_exit_code_error(self): | |||
|
455 | ExitCodeChecks.test_exit_code_error(self) | |||
|
456 | ||||
|
457 | @skip_win32 | |||
|
458 | def test_exit_code_signal(self): | |||
|
459 | ExitCodeChecks.test_exit_code_signal(self) | |||
430 |
|
460 | |||
431 | class TestModules(unittest.TestCase, tt.TempFileMixin): |
|
461 | class TestModules(unittest.TestCase, tt.TempFileMixin): | |
432 | def test_extraneous_loads(self): |
|
462 | def test_extraneous_loads(self): |
@@ -184,6 +184,12 class ProcessHandler(object): | |||||
184 | child.terminate(force=True) |
|
184 | child.terminate(force=True) | |
185 | # add isalive check, to ensure exitstatus is set: |
|
185 | # add isalive check, to ensure exitstatus is set: | |
186 | child.isalive() |
|
186 | child.isalive() | |
|
187 | ||||
|
188 | # We follow the subprocess pattern, returning either the exit status | |||
|
189 | # as a positive number, or the terminating signal as a negative | |||
|
190 | # number. sh returns 128+n for signals | |||
|
191 | if child.exitstatus > 128: | |||
|
192 | return -(child.exitstatus - 128) | |||
187 | return child.exitstatus |
|
193 | return child.exitstatus | |
188 |
|
194 | |||
189 |
|
195 |
General Comments 0
You need to be logged in to leave comments.
Login now