Skip to content

Commit ad507a4

Browse files
committed
Share code between SignalBlocker and MultiSignalBlocker.
1 parent a78eece commit ad507a4

File tree

2 files changed

+42
-56
lines changed

2 files changed

+42
-56
lines changed

pytestqt/_tests/test_wait_signal.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,7 @@ def explicit_wait(qtbot, signal, timeout, multiple):
2525
"""
2626
func = qtbot.waitSignals if multiple else qtbot.waitSignal
2727
blocker = func(signal, timeout)
28-
if multiple:
29-
assert not blocker.signals_triggered
30-
else:
31-
assert not blocker.signal_triggered
28+
assert not blocker.signal_triggered
3229
blocker.wait()
3330
return blocker
3431

@@ -87,7 +84,7 @@ def test_signal_triggered(qtbot, wait_function, emit_delay, timeout,
8784

8885
@pytest.mark.parametrize(
8986
('wait_function', 'emit_delay_1', 'emit_delay_2', 'timeout',
90-
'expected_signals_triggered'),
87+
'expected_signal_triggered'),
9188
[
9289
(explicit_wait, 500, 600, 2000, True),
9390
(explicit_wait, 500, 600, None, True),
@@ -103,7 +100,7 @@ def test_signal_triggered(qtbot, wait_function, emit_delay, timeout,
103100
)
104101
def test_signal_triggered_multiple(qtbot, wait_function, emit_delay_1,
105102
emit_delay_2, timeout,
106-
expected_signals_triggered):
103+
expected_signal_triggered):
107104
"""
108105
Testing for a signal in different conditions, ensuring we are obtaining
109106
the expected results.
@@ -129,7 +126,7 @@ def test_signal_triggered_multiple(qtbot, wait_function, emit_delay_1,
129126
assert not blocker._loop.isRunning()
130127

131128
# ensure that either signal was triggered or timeout occurred
132-
assert blocker.signals_triggered == expected_signals_triggered
129+
assert blocker.signal_triggered == expected_signal_triggered
133130

134131
# Check that we exited by the earliest parameter; timeout = None means
135132
# wait forever, so ensure we waited at most 4 times emit-delay
@@ -160,4 +157,4 @@ def test_explicit_emit_multiple(qtbot):
160157
signaller.signal.emit()
161158
signaller.signal_2.emit()
162159

163-
assert waiting.signals_triggered
160+
assert waiting.signal_triggered

pytestqt/plugin.py

Lines changed: 37 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -319,25 +319,29 @@ def waitSignals(self, signals=None, timeout=1000):
319319
wait_signals = waitSignals # pep-8 alias
320320

321321

322-
class SignalBlocker(object):
322+
class AbstractSignalBlocker(object):
323323

324324
"""
325-
Returned by :meth:`QtBot.waitSignal` method.
325+
Base class for :class:`SignalBlocker` and :class:`MultiSignalBlocker`.
326326
327-
.. automethod:: wait
328-
.. automethod:: connect
327+
Provides :meth:`wait` and a context manager protocol, but no means to add
328+
new signals and to detect when the signals should be considered "done".
329+
This needs to be implemented by subclasses.
330+
331+
Subclasses also need to provide ``self._signals`` which should evaluate to
332+
``False`` if no signals were configured.
329333
330334
:ivar int timeout: maximum time to wait for a signal to be triggered. Can
331335
be changed before :meth:`wait` is called.
332336
333-
:ivar bool signal_triggered: set to ``True`` if a signal was triggered, or
334-
``False`` if timeout was reached instead. Until :meth:`wait` is called,
335-
this is set to ``None``.
337+
:ivar bool signal_triggered: set to ``True`` if a signal (or all signals in
338+
case of :class:MultipleSignalBlocker:) was triggered, or ``False`` if
339+
timeout was reached instead. Until :meth:`wait` is called, this is set
340+
to ``None``.
336341
"""
337342

338343
def __init__(self, timeout=1000):
339344
self._loop = QtCore.QEventLoop()
340-
self._signals = []
341345
self.timeout = timeout
342346
self.signal_triggered = False
343347

@@ -350,12 +354,33 @@ def wait(self):
350354
"""
351355
if self.signal_triggered:
352356
return
353-
if self.timeout is None and len(self._signals) == 0:
357+
if self.timeout is None and not self._signals:
354358
raise ValueError("No signals or timeout specified.")
355359
if self.timeout is not None:
356360
QtCore.QTimer.singleShot(self.timeout, self._loop.quit)
357361
self._loop.exec_()
358362

363+
def __enter__(self):
364+
return self
365+
366+
def __exit__(self, type, value, traceback):
367+
self.wait()
368+
369+
370+
class SignalBlocker(AbstractSignalBlocker):
371+
372+
"""
373+
Returned by :meth:`QtBot.waitSignal` method.
374+
375+
.. automethod:: wait
376+
.. automethod:: connect
377+
378+
"""
379+
380+
def __init__(self, timeout=1000):
381+
super(SignalBlocker, self).__init__(timeout)
382+
self._signals = []
383+
359384
def connect(self, signal):
360385
"""
361386
Connects to the given signal, making :meth:`wait()` return once this signal
@@ -373,49 +398,19 @@ def _quit_loop_by_signal(self):
373398
self.signal_triggered = True
374399
self._loop.quit()
375400

376-
def __enter__(self):
377-
return self
378401

379-
def __exit__(self, type, value, traceback):
380-
self.wait()
381-
382-
383-
class MultiSignalBlocker(object):
402+
class MultiSignalBlocker(AbstractSignalBlocker):
384403

385404
"""
386405
Returned by :meth:`QtBot.waitSignals` method.
387406
388407
.. automethod:: wait
389408
.. automethod:: add_signal
390-
391-
:ivar int timeout: maximum time to wait for a signal to be triggered. Can
392-
be changed before :meth:`wait` is called.
393-
394-
:ivar bool signals_triggered: set to ``True`` if all signals were
395-
triggered, or ``False`` if timeout was reached instead. Until
396-
:meth:`wait` is called, this is set to ``None``.
397409
"""
398410

399411
def __init__(self, timeout=1000):
400-
self._loop = QtCore.QEventLoop()
412+
super(MultiSignalBlocker, self).__init__(timeout)
401413
self._signals = {}
402-
self.timeout = timeout
403-
self.signals_triggered = False
404-
405-
def wait(self):
406-
"""
407-
Waits until either a connected signal is triggered or timeout is reached.
408-
409-
:raise ValueError: if no signals are connected and timeout is None; in
410-
this case it would wait forever.
411-
"""
412-
if self.signals_triggered:
413-
return
414-
if self.timeout is None and not self._signals:
415-
raise ValueError("No signals or timeout specified.")
416-
if self.timeout is not None:
417-
QtCore.QTimer.singleShot(self.timeout, self._loop.quit)
418-
self._loop.exec_()
419414

420415
def add_signal(self, signal):
421416
"""
@@ -436,15 +431,9 @@ def _signal_emitted(self, signal):
436431
"""
437432
self._signals[signal] = True
438433
if all(self._signals.values()):
439-
self.signals_triggered = True
434+
self.signal_triggered = True
440435
self._loop.quit()
441436

442-
def __enter__(self):
443-
return self
444-
445-
def __exit__(self, type, value, traceback):
446-
self.wait()
447-
448437

449438
@contextmanager
450439
def capture_exceptions():

0 commit comments

Comments
 (0)