Skip to content

Disconnect SignalBlocker after exiting loop. #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 7, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions pytestqt/_tests/test_wait_signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,8 @@ def check(self, timeout, *delays):
return StopWatch()


@pytest.mark.parametrize('multiple, raising',
[(True, True), (True, False), (False, True),
(False, False)])
@pytest.mark.parametrize('multiple', [True, False])
@pytest.mark.parametrize('raising', [True, False])
def test_wait_signals_handles_exceptions(qtbot, multiple, raising):
"""
Make sure waitSignal handles exceptions correctly.
Expand All @@ -239,3 +238,30 @@ class TestException(Exception):
with pytest.raises(TestException):
with func(arg, timeout=10, raising=raising):
raise TestException


@pytest.mark.parametrize('multiple', [True, False])
@pytest.mark.parametrize('do_timeout', [True, False])
def test_wait_twice(qtbot, single_shot, multiple, do_timeout):
"""
https://github.com/pytest-dev/pytest-qt/issues/69
"""
signaller = Signaller()

if multiple:
func = qtbot.waitSignals
arg = [signaller.signal]
else:
func = qtbot.waitSignal
arg = signaller.signal

if do_timeout:
with func(arg, timeout=100):
single_shot(signaller.signal, 200)
with func(arg, timeout=100):
single_shot(signaller.signal, 200)
else:
with func(arg):
signaller.signal.emit()
with func(arg):
signaller.signal.emit()
33 changes: 31 additions & 2 deletions pytestqt/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,12 @@ def __init__(self, timeout=1000, raising=False):
self.timeout = timeout
self.signal_triggered = False
self.raising = raising
if timeout is None:
self._timer = None
else:
self._timer = QtCore.QTimer()
self._timer.setSingleShot(True)
self._timer.setInterval(timeout)

def wait(self):
"""
Expand All @@ -367,13 +373,26 @@ def wait(self):
return
if self.timeout is None and not self._signals:
raise ValueError("No signals or timeout specified.")
if self.timeout is not None:
QtCore.QTimer.singleShot(self.timeout, self._loop.quit)
if self._timer is not None:
self._timer.timeout.connect(self._quit_loop_by_timeout)
self._timer.start()
self._loop.exec_()
if not self.signal_triggered and self.raising:
raise SignalTimeoutError("Didn't get signal after %sms." %
self.timeout)

def _quit_loop_by_timeout(self):
self._loop.quit()
self._cleanup()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't cleanup always be called? If so, I think you should call it as soon after self._loop.exec_() finishes (in line 377).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True - I first only had it in _quit_loop_by_signal and then noticed it's also needed on timeouts, that's why I didn't think of putting it there.


def _cleanup(self):
if self._timer is not None:
try:
self._timer.timeout.disconnect(self._quit_loop_by_timeout)
except (TypeError, RuntimeError):
# already disconnected by Qt?
pass

def __enter__(self):
return self

Expand Down Expand Up @@ -426,6 +445,16 @@ def _quit_loop_by_signal(self):
"""
self.signal_triggered = True
self._loop.quit()
self._cleanup()

def _cleanup(self):
super(SignalBlocker, self)._cleanup()
for signal in self._signals:
try:
signal.disconnect(self._quit_loop_by_signal)
except (TypeError, RuntimeError):
# already disconnected by Qt?
pass


class MultiSignalBlocker(_AbstractSignalBlocker):
Expand Down