From ad401e035f2f5b33c4bab0782c2bfd346aba5840 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 11 Jun 2015 19:10:01 +0200 Subject: [PATCH] Proxy QProcess signals. --- qutebrowser/commands/userscripts.py | 4 +-- qutebrowser/misc/editor.py | 4 +-- qutebrowser/misc/guiprocess.py | 39 ++++++++++++++++++++--------- tests/misc/test_editor.py | 22 ++++++++-------- 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/qutebrowser/commands/userscripts.py b/qutebrowser/commands/userscripts.py index 08117f2fd..ffd71bbbb 100644 --- a/qutebrowser/commands/userscripts.py +++ b/qutebrowser/commands/userscripts.py @@ -101,8 +101,8 @@ class _BaseUserscriptRunner(QObject): self._proc = guiprocess.GUIProcess(self._win_id, 'userscript', additional_env=self._env, parent=self) - self._proc.proc.error.connect(self.on_proc_error) - self._proc.proc.finished.connect(self.on_proc_finished) + self._proc.error.connect(self.on_proc_error) + self._proc.finished.connect(self.on_proc_finished) self._proc.start(cmd, args) def _cleanup(self): diff --git a/qutebrowser/misc/editor.py b/qutebrowser/misc/editor.py index 8294e377c..b5a9e5995 100644 --- a/qutebrowser/misc/editor.py +++ b/qutebrowser/misc/editor.py @@ -116,8 +116,8 @@ class ExternalEditor(QObject): return self._proc = guiprocess.GUIProcess(self._win_id, what='editor', parent=self) - self._proc.proc.finished.connect(self.on_proc_closed) - self._proc.proc.error.connect(self.on_proc_error) + self._proc.finished.connect(self.on_proc_closed) + self._proc.error.connect(self.on_proc_error) editor = config.get('general', 'editor') executable = editor[0] args = [self._filename if arg == '{}' else arg for arg in editor[1:]] diff --git a/qutebrowser/misc/guiprocess.py b/qutebrowser/misc/guiprocess.py index 1506c1da6..04b9f27d9 100644 --- a/qutebrowser/misc/guiprocess.py +++ b/qutebrowser/misc/guiprocess.py @@ -21,7 +21,8 @@ import shlex -from PyQt5.QtCore import pyqtSlot, QProcess, QIODevice, QProcessEnvironment +from PyQt5.QtCore import (pyqtSlot, pyqtSignal, QObject, QProcess, + QProcessEnvironment) from qutebrowser.utils import message, log @@ -39,23 +40,31 @@ ERROR_STRINGS = { } -class GUIProcess: +class GUIProcess(QObject): """An external process which shows notifications in the GUI. Args: - proc: The underlying QProcess. cmd: The command which was started. args: A list of arguments which gets passed. started: Whether the underlying process is started. + _proc: The underlying QProcess. _win_id: The window ID this process is used in. _what: What kind of thing is spawned (process/editor/userscript/...). Used in messages. _verbose: Whether to show more messages. + + Signals: + error/finished/started signals proxied from QProcess. """ + error = pyqtSignal(QProcess.ProcessError) + finished = pyqtSignal(int, QProcess.ExitStatus) + started = pyqtSignal() + def __init__(self, win_id, what, *, verbose=False, additional_env=None, parent=None): + super().__init__(parent) self._win_id = win_id self._what = what self._verbose = verbose @@ -63,16 +72,19 @@ class GUIProcess: self.cmd = None self.args = None - self.proc = QProcess(parent) - self.proc.error.connect(self.on_error) - self.proc.finished.connect(self.on_finished) - self.proc.started.connect(self.on_started) + self._proc = QProcess(self) + self._proc.error.connect(self.on_error) + self._proc.error.connect(self.error) + self._proc.finished.connect(self.on_finished) + self._proc.finished.connect(self.finished) + self._proc.started.connect(self.on_started) + self._proc.started.connect(self.started) if additional_env is not None: procenv = QProcessEnvironment.systemEnvironment() for k, v in additional_env.items(): procenv.insert(k, v) - self.proc.setProcessEnvironment(procenv) + self._proc.setProcessEnvironment(procenv) @pyqtSlot(QProcess.ProcessError) def on_error(self, error): @@ -117,21 +129,24 @@ class GUIProcess: fake_cmdline = ' '.join(shlex.quote(e) for e in [cmd] + list(args)) message.info(self._win_id, 'Executing: ' + fake_cmdline) - def start(self, cmd, args, mode=QIODevice.ReadWrite): + def start(self, cmd, args, mode=None): """Convenience wrapper around QProcess::start.""" log.procs.debug("Starting process.") self._pre_start(cmd, args) - self.proc.start(cmd, args, mode) + if mode is None: + self._proc.start(cmd, args) + else: + self._proc.start(cmd, args, mode) def start_detached(self, cmd, args, cwd=None): """Convenience wrapper around QProcess::startDetached.""" log.procs.debug("Starting detached.") self._pre_start(cmd, args) - ok = self.proc.startDetached(cmd, args, cwd) + ok = self._proc.startDetached(cmd, args, cwd) if ok: log.procs.debug("Process started.") self.started = True else: message.error(self._win_id, "Error while spawning {}: {}.".format( - self._what, self.proc.error()), immediately=True) + self._what, self._proc.error()), immediately=True) diff --git a/tests/misc/test_editor.py b/tests/misc/test_editor.py index 25925f7e1..10142b525 100644 --- a/tests/misc/test_editor.py +++ b/tests/misc/test_editor.py @@ -60,7 +60,7 @@ class TestArg: stubbed_config.data = { 'general': {'editor': ['bin'], 'editor-encoding': 'utf-8'}} self.editor.edit("") - self.editor._proc.proc.start.assert_called_with("bin", []) + self.editor._proc._proc.start.assert_called_with("bin", []) def test_start_args(self, stubbed_config): """Test starting editor with static arguments.""" @@ -68,7 +68,7 @@ class TestArg: 'general': {'editor': ['bin', 'foo', 'bar'], 'editor-encoding': 'utf-8'}} self.editor.edit("") - self.editor._proc.proc.start.assert_called_with("bin", ["foo", "bar"]) + self.editor._proc._proc.start.assert_called_with("bin", ["foo", "bar"]) def test_placeholder(self, stubbed_config): """Test starting editor with placeholder argument.""" @@ -77,7 +77,7 @@ class TestArg: 'editor-encoding': 'utf-8'}} self.editor.edit("") filename = self.editor._filename - self.editor._proc.proc.start.assert_called_with( + self.editor._proc._proc.start.assert_called_with( "bin", ["foo", filename, "bar"]) def test_in_arg_placeholder(self, stubbed_config): @@ -86,7 +86,7 @@ class TestArg: 'general': {'editor': ['bin', 'foo{}bar'], 'editor-encoding': 'utf-8'}} self.editor.edit("") - self.editor._proc.proc.start.assert_called_with("bin", ["foo{}bar"]) + self.editor._proc._proc.start.assert_called_with("bin", ["foo{}bar"]) class TestFileHandling: @@ -113,7 +113,7 @@ class TestFileHandling: self.editor.edit("") filename = self.editor._filename assert os.path.exists(filename) - self.editor._proc.proc.finished.emit(0, QProcess.NormalExit) + self.editor._proc.finished.emit(0, QProcess.NormalExit) assert not os.path.exists(filename) def test_file_handling_closed_error(self, caplog): @@ -122,7 +122,7 @@ class TestFileHandling: filename = self.editor._filename assert os.path.exists(filename) with caplog.atLevel(logging.ERROR): - self.editor._proc.proc.finished.emit(1, QProcess.NormalExit) + self.editor._proc.finished.emit(1, QProcess.NormalExit) assert len(caplog.records()) == 2 assert not os.path.exists(filename) @@ -132,9 +132,9 @@ class TestFileHandling: filename = self.editor._filename assert os.path.exists(filename) with caplog.atLevel(logging.ERROR): - self.editor._proc.proc.error.emit(QProcess.Crashed) + self.editor._proc.error.emit(QProcess.Crashed) assert len(caplog.records()) == 2 - self.editor._proc.proc.finished.emit(0, QProcess.CrashExit) + self.editor._proc.finished.emit(0, QProcess.CrashExit) assert not os.path.exists(filename) @@ -182,7 +182,7 @@ class TestModifyTests: self.editor.edit("") assert self._read() == "" self._write("Hello") - self.editor._proc.proc.finished.emit(0, QProcess.NormalExit) + self.editor._proc.finished.emit(0, QProcess.NormalExit) self.editor.editing_finished.emit.assert_called_with("Hello") def test_simple_input(self): @@ -190,7 +190,7 @@ class TestModifyTests: self.editor.edit("Hello") assert self._read() == "Hello" self._write("World") - self.editor._proc.proc.finished.emit(0, QProcess.NormalExit) + self.editor._proc.finished.emit(0, QProcess.NormalExit) self.editor.editing_finished.emit.assert_called_with("World") def test_umlaut(self): @@ -198,7 +198,7 @@ class TestModifyTests: self.editor.edit("Hällö Wörld") assert self._read() == "Hällö Wörld" self._write("Überprüfung") - self.editor._proc.proc.finished.emit(0, QProcess.NormalExit) + self.editor._proc.finished.emit(0, QProcess.NormalExit) self.editor.editing_finished.emit.assert_called_with("Überprüfung") def test_unicode(self):