diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index c2b7847..fc530af 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -2206,6 +2206,10 @@ class InteractiveShell(SingletonConfigurable): else: cmd = py3compat.unicode_to_str(cmd) ec = os.system(cmd) + # The high byte is the exit code, the low byte is a signal number + # that we discard for now. See the docs for os.wait() + if ec > 255: + ec >>= 8 # We explicitly do NOT return the subprocess status code, because # a non-None value would trigger :func:`sys.displayhook` calls. diff --git a/IPython/core/tests/test_interactiveshell.py b/IPython/core/tests/test_interactiveshell.py index 8031ad6..a595429 100644 --- a/IPython/core/tests/test_interactiveshell.py +++ b/IPython/core/tests/test_interactiveshell.py @@ -402,6 +402,11 @@ class TestSystemRaw(unittest.TestCase): cmd = ur'''python -c "'åäö'" ''' ip.system_raw(cmd) + def test_exit_code(self): + """Test that the exit code is parsed correctly.""" + ip.system_raw('exit 1') + self.assertEqual(ip.user_ns['_exit_code'], 1) + class TestModules(unittest.TestCase, tt.TempFileMixin): def test_extraneous_loads(self): """Test we're not loading modules on startup that we shouldn't.