Report stdout/stderr of failed subprocesses.
This commit is contained in:
parent
d3dc90cb2a
commit
5c769d8000
@ -84,6 +84,8 @@ Changed
|
|||||||
- `general -> log-javascript-console` got changed from a boolean to an option
|
- `general -> log-javascript-console` got changed from a boolean to an option
|
||||||
taking a loglevel (`none`, `info`, `debug`).
|
taking a loglevel (`none`, `info`, `debug`).
|
||||||
- `:tab-move +/-` now wraps around if `tabs -> wrap` is `true`.
|
- `:tab-move +/-` now wraps around if `tabs -> wrap` is `true`.
|
||||||
|
- When a subprocess (like launched by `:spawn`) fails, its stdout/stderr is now
|
||||||
|
logged to the console.
|
||||||
|
|
||||||
Deprecated
|
Deprecated
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
@ -109,9 +109,18 @@ class GUIProcess(QObject):
|
|||||||
self._what.capitalize()))
|
self._what.capitalize()))
|
||||||
else:
|
else:
|
||||||
assert status == QProcess.NormalExit
|
assert status == QProcess.NormalExit
|
||||||
|
# We call this 'status' here as it makes more sense to the user -
|
||||||
|
# it's actually 'code'.
|
||||||
message.error(self._win_id, "{} exited with status {}.".format(
|
message.error(self._win_id, "{} exited with status {}.".format(
|
||||||
self._what.capitalize(), code))
|
self._what.capitalize(), code))
|
||||||
|
|
||||||
|
stderr = bytes(self._proc.readAllStandardError()).decode('utf-8')
|
||||||
|
stdout = bytes(self._proc.readAllStandardOutput()).decode('utf-8')
|
||||||
|
if stdout:
|
||||||
|
log.procs.error("Process stdout:\n" + stdout.strip())
|
||||||
|
if stderr:
|
||||||
|
log.procs.error("Process stderr:\n" + stderr.strip())
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def on_started(self):
|
def on_started(self):
|
||||||
"""Called when the process started successfully."""
|
"""Called when the process started successfully."""
|
||||||
|
@ -93,6 +93,8 @@ def test_start_env(monkeypatch, qtbot, py_proc):
|
|||||||
argv = py_proc("""
|
argv = py_proc("""
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
env = dict(os.environ)
|
env = dict(os.environ)
|
||||||
print(json.dumps(env))
|
print(json.dumps(env))
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
@ -201,3 +203,33 @@ def test_exit_unsuccessful(qtbot, proc, guiprocess_message_mock, py_proc):
|
|||||||
|
|
||||||
msg = guiprocess_message_mock.getmsg(guiprocess_message_mock.Level.error)
|
msg = guiprocess_message_mock.getmsg(guiprocess_message_mock.Level.error)
|
||||||
assert msg.text == "Testprocess exited with status 1."
|
assert msg.text == "Testprocess exited with status 1."
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.not_frozen
|
||||||
|
@pytest.mark.parametrize('stream', ['stdout', 'stderr'])
|
||||||
|
def test_exit_unsuccessful_output(qtbot, proc, caplog, py_proc, stream):
|
||||||
|
"""When a process fails, its output should be logged."""
|
||||||
|
with caplog.atLevel(logging.ERROR):
|
||||||
|
with qtbot.waitSignal(proc.finished, raising=True, timeout=10000):
|
||||||
|
proc.start(*py_proc("""
|
||||||
|
import sys
|
||||||
|
print("test", file=sys.{})
|
||||||
|
sys.exit(1)
|
||||||
|
""".format(stream)))
|
||||||
|
assert len(caplog.records) == 2
|
||||||
|
assert caplog.records[1].msg == 'Process {}:\ntest'.format(stream)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('stream', ['stdout', 'stderr'])
|
||||||
|
def test_exit_successful_output(qtbot, proc, py_proc, stream):
|
||||||
|
"""When a process suceeds, no output should be logged.
|
||||||
|
|
||||||
|
The test doesn't actually check the log as it'd fail because of the error
|
||||||
|
logging.
|
||||||
|
"""
|
||||||
|
with qtbot.waitSignal(proc.finished, raising=True, timeout=10000):
|
||||||
|
proc.start(*py_proc("""
|
||||||
|
import sys
|
||||||
|
print("test", file=sys.{})
|
||||||
|
sys.exit(0)
|
||||||
|
""".format(stream)))
|
||||||
|
Loading…
Reference in New Issue
Block a user