Skip to content

Commit 78ecf73

Browse files
committed
Fixed several small issues.
1 parent 77b1cb0 commit 78ecf73

File tree

4 files changed

+77
-61
lines changed

4 files changed

+77
-61
lines changed

docs/signals.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ Getting emitted signals and arguments
211211

212212
To determine which of the expected signals were emitted during a ``wait()`` you can use
213213
``blocker.all_signals_and_args`` which contains a list of
214-
:class:`wait_signal.SignalAndArgs <SignalAndArgs>` ``namedtuple`` objects, indicating the signals (and their arguments)
214+
:class:`wait_signal.SignalAndArgs <SignalAndArgs>` objects, indicating the signals (and their arguments)
215215
in the order they were received.
216216

217217

pytestqt/qtbot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ def waitSignal(self, signal=None, timeout=1000, raising=None, check_params_cb=No
219219
The *check_params_cb* parameter.
220220
221221
:param Signal signal:
222-
A signal to wait for, or a tuple (signal, signal_name_as_str) to improve the error message that is part
222+
A signal to wait for, or a tuple ``(signal, signal_name_as_str)`` to improve the error message that is part
223223
of ``SignalTimeoutError``. Set to ``None`` to just use timeout.
224224
:param int timeout:
225225
How many milliseconds to wait before resuming control flow.

pytestqt/wait_signal.py

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ def wait(self):
4848
self._timer.start()
4949
self._loop.exec_()
5050
if not self.signal_triggered and self.raising:
51-
# raise SignalTimeoutError("Didn't get signal after %sms." % self.timeout)
5251
raise SignalTimeoutError(self._timeout_message)
5352

5453
def _quit_loop_by_timeout(self):
@@ -70,22 +69,21 @@ def get_timeout_error_message(self):
7069

7170
def _extract_pyqt_signal_name(self, potential_pyqt_signal):
7271
signal_name = potential_pyqt_signal.signal # type: str
73-
if type(signal_name) != str:
72+
if not isinstance(signal_name, str):
7473
raise TypeError("Invalid 'signal' attribute in {}. "
7574
"Expected str but got {}".format(signal_name, type(signal_name)))
7675
# strip magic number "2" that PyQt prepends to the signal names
77-
if signal_name.startswith("2"):
78-
signal_name = signal_name.lstrip('2')
76+
signal_name = signal_name.lstrip('2')
7977
return signal_name
8078

8179
def _extract_signal_from_signal_tuple(self, potential_signal_tuple):
82-
if type(potential_signal_tuple) is tuple:
80+
if isinstance(potential_signal_tuple, tuple):
8381
if len(potential_signal_tuple) != 2:
84-
raise AssertionError("Signal tuple must have length of 2 (first element is the signal, "
85-
"the second element is the signal's name).")
82+
raise ValueError("Signal tuple must have length of 2 (first element is the signal, "
83+
"the second element is the signal's name).")
8684
signal_tuple = potential_signal_tuple
8785
signal_name = signal_tuple[1]
88-
if type(signal_name) != str or not signal_name:
86+
if not isinstance(signal_name, str) or not signal_name:
8987
raise TypeError("Invalid type for user-provided signal name, "
9088
"expected str but got {}".format(type(signal_name)))
9189
return signal_name
@@ -125,7 +123,7 @@ def get_callback_name(self, callback):
125123

126124
@staticmethod
127125
def get_signal_from_potential_signal_tuple(signal_tuple):
128-
if type(signal_tuple) is tuple:
126+
if isinstance(signal_tuple, tuple):
129127
return signal_tuple[0]
130128
return signal_tuple
131129

@@ -236,36 +234,36 @@ def get_timeout_error_message(self):
236234
cb_name=self.get_callback_name(self.check_params_callback))
237235
else:
238236
return "Signal {signal_name} not emitted after {timeout} ms".format(signal_name=self.signal_name,
239-
timeout=self.timeout)
237+
timeout=self.timeout)
240238

241239

242-
SignalAndArgs = namedtuple("SignalAndArgs", ["signal_name", "args"])
240+
class SignalAndArgs:
241+
def __init__(self, signal_name, args):
242+
self.signal_name = signal_name
243+
self.args = args
243244

245+
def _get_readable_signal_with_optional_args(self):
246+
args = repr(self.args) if self.args else ""
244247

245-
def _get_readable_signal_with_optional_args(self):
246-
if self.args:
247-
args_as_string = []
248-
for arg in self.args:
249-
if type(arg) is str:
250-
args_as_string.append("'" + str(arg) + "'")
251-
else:
252-
args_as_string.append(str(arg))
253-
args_as_list_string = ", ".join(args_as_string) if len(args_as_string) > 1 else args_as_string[0]
254-
args = "({})".format(args_as_list_string)
255-
else:
256-
args = ""
248+
# remove signal parameter signature, e.g. turn "some_signal(QString,int)" to "some_signal", because we're adding
249+
# the actual parameters anyways
250+
signal_name = self.signal_name
251+
signal_name = signal_name.partition('(')[0]
257252

258-
# remove signal parameter signature, e.g. turn "some_signal(QString,int)" to "some_signal", because we're adding
259-
# the actual parameters anyways
260-
signal_name = self.signal_name
261-
if '(' in signal_name:
262-
signal_name = signal_name[:signal_name.index('(')]
253+
return signal_name + args
263254

264-
return signal_name + args
255+
def __str__(self):
256+
return self._get_readable_signal_with_optional_args()
265257

258+
def __repr__(self):
259+
return self._get_readable_signal_with_optional_args()
260+
261+
def __eq__(self, other):
262+
if isinstance(other, self.__class__):
263+
return self.__dict__ == other.__dict__
264+
else:
265+
return False
266266

267-
SignalAndArgs.__str__ = _get_readable_signal_with_optional_args
268-
SignalAndArgs.__repr__ = _get_readable_signal_with_optional_args
269267

270268
# Returns e.g. "3rd" for 3, or "21st" for 21
271269
get_ordinal_str = lambda n: "%d%s" % (n, {1: "st", 2: "nd", 3: "rd"}.get(n if n < 20 else n % 10, "th"))
@@ -400,8 +398,9 @@ def _check_signal_match(self, unique_signal, *args):
400398
self._signal_expected_index += 1
401399
self._strict_order_violated = False # order has not been violated after all!
402400
else:
403-
self._actual_signal_and_args_at_violation = SignalAndArgs(
404-
signal_name=self._signal_names[unique_signal], args=args)
401+
if self._are_signal_names_available():
402+
self._actual_signal_and_args_at_violation = SignalAndArgs(
403+
signal_name=self._signal_names[unique_signal], args=args)
405404

406405
def _all_signals_emitted(self):
407406
return not self._strict_order_violated and all(self._signals_emitted)

tests/test_wait_signal.py

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import fnmatch
33

44
import pytest
5+
import sys
56

67
from pytestqt.qt_compat import qt_api
78
from pytestqt.wait_signal import SignalEmittedError, SignalTimeoutError, SignalAndArgs
@@ -702,7 +703,7 @@ def get_mixed_signals_with_guaranteed_name(signaller):
702703

703704
class TestAllSignalsAndArgs:
704705
"""
705-
Tests blocker.all_signals_and_args (waitSignals() blocker) is filled with the namedtuple SignalAndArgs for each
706+
Tests blocker.all_signals_and_args (waitSignals() blocker) is a list of SignalAndArgs objects, one for each
706707
received expected signal (irrespective of the order parameter).
707708
"""
708709

@@ -738,7 +739,7 @@ def test_non_empty_on_timeout_no_cb(self, qtbot, signaller):
738739
raising=False) as blocker:
739740
signaller.signal_args.emit('1', 1)
740741
signaller.signal.emit()
741-
assert blocker.signal_triggered is False
742+
assert not blocker.signal_triggered
742743
assert blocker.all_signals_and_args == [
743744
SignalAndArgs(signal_name='signal_args(QString,int)', args=('1', 1)),
744745
SignalAndArgs(signal_name='signal()', args=())
@@ -755,14 +756,17 @@ def test_non_empty_no_cb(self, qtbot, signaller):
755756
signaller.signal.emit()
756757
signaller.signal_args.emit('1', 1)
757758
signaller.signal_args.emit('2', 2)
758-
assert blocker.signal_triggered is True
759+
assert blocker.signal_triggered
759760
assert blocker.all_signals_and_args == [
760761
SignalAndArgs(signal_name='signal()', args=()),
761762
SignalAndArgs(signal_name='signal_args(QString,int)', args=('1', 1)),
762763
SignalAndArgs(signal_name='signal_args(QString,int)', args=('2', 2))
763764
]
764765

765766

767+
PY_2 = sys.version_info[0] == 2
768+
769+
766770
class TestWaitSignalSignalTimeoutErrorMessage:
767771
"""Tests that the messages of SignalTimeoutError are formatted correctly, for waitSignal() calls."""
768772

@@ -801,8 +805,8 @@ def arg_validator(int_param):
801805
signaller.signal_single_arg.emit(1)
802806
signaller.signal_single_arg.emit(2)
803807
ex_msg = TestWaitSignalsSignalTimeoutErrorMessage.get_exception_message(excinfo)
804-
assert ex_msg == "Signal signal_single_arg(int) emitted with parameters [1, 2] within 200 ms, " \
805-
"but did not satisfy the arg_validator callback"
808+
assert ex_msg == ("Signal signal_single_arg(int) emitted with parameters [1, 2] within 200 ms, "
809+
"but did not satisfy the arg_validator callback")
806810

807811
def test_with_multiple_args(self, qtbot, signaller):
808812
"""
@@ -820,11 +824,14 @@ def arg_validator(str_param, int_param):
820824

821825
with pytest.raises(SignalTimeoutError) as excinfo:
822826
with qtbot.waitSignal(signal=signal, timeout=200, check_params_cb=arg_validator, raising=True):
823-
signaller.signal_args.emit('1', 1)
827+
signaller.signal_args.emit("1", 1)
824828
signaller.signal_args.emit('2', 2)
825829
ex_msg = TestWaitSignalsSignalTimeoutErrorMessage.get_exception_message(excinfo)
826-
assert ex_msg == "Signal signal_args(QString,int) emitted with parameters [('1', 1), ('2', 2)] " \
827-
"within 200 ms, but did not satisfy the arg_validator callback"
830+
parameters = "[('1', 1), ('2', 2)]"
831+
if PY_2:
832+
parameters = "[(u'1', 1), (u'2', 2)]"
833+
assert ex_msg == ("Signal signal_args(QString,int) emitted with parameters {} "
834+
"within 200 ms, but did not satisfy the arg_validator callback").format(parameters)
828835

829836

830837
class TestWaitSignalsSignalTimeoutErrorMessage:
@@ -845,8 +852,8 @@ def my_callback(str_param, int_param):
845852
check_params_cbs=[None, None, my_callback], order=order, raising=True):
846853
pass # don't emit any signals
847854
ex_msg = TestWaitSignalsSignalTimeoutErrorMessage.get_exception_message(excinfo)
848-
assert ex_msg == "Emitted signals: None. Missing: " \
849-
"[signal(), signal_args(QString,int), signal_args(QString,int) (callback: my_callback)]"
855+
assert ex_msg == ("Emitted signals: None. Missing: "
856+
"[signal(), signal_args(QString,int), signal_args(QString,int) (callback: my_callback)]")
850857

851858
@pytest.mark.parametrize("order", ["none", "simple", "strict"])
852859
def test_no_signal_emitted_no_callbacks(self, qtbot, signaller, order):
@@ -859,8 +866,8 @@ def test_no_signal_emitted_no_callbacks(self, qtbot, signaller, order):
859866
check_params_cbs=None, order=order, raising=True):
860867
pass # don't emit any signals
861868
ex_msg = TestWaitSignalsSignalTimeoutErrorMessage.get_exception_message(excinfo)
862-
assert ex_msg == "Emitted signals: None. Missing: " \
863-
"[signal(), signal_args(QString,int), signal_args(QString,int)]"
869+
assert ex_msg == ("Emitted signals: None. Missing: "
870+
"[signal(), signal_args(QString,int), signal_args(QString,int)]")
864871

865872
def test_none_order_one_signal_emitted(self, qtbot, signaller):
866873
"""
@@ -879,8 +886,11 @@ def my_callback_2(str_param, int_param):
879886
check_params_cbs=[None, my_callback_1, my_callback_2], order="none", raising=True):
880887
signaller.signal_args.emit("1", 1)
881888
ex_msg = TestWaitSignalsSignalTimeoutErrorMessage.get_exception_message(excinfo)
882-
assert ex_msg == "Emitted signals: [signal_args('1', 1)]. Missing: " \
883-
"[signal(), signal_args(QString,int) (callback: my_callback_2)]"
889+
signal_args = "'1', 1"
890+
if PY_2:
891+
signal_args = "u'1', 1"
892+
assert ex_msg == ("Emitted signals: [signal_args({})]. Missing: "
893+
"[signal(), signal_args(QString,int) (callback: my_callback_2)]").format(signal_args)
884894

885895
def test_simple_order_first_signal_emitted(self, qtbot, signaller):
886896
"""
@@ -892,8 +902,8 @@ def test_simple_order_first_signal_emitted(self, qtbot, signaller):
892902
check_params_cbs=None, order="simple", raising=True):
893903
signaller.signal.emit()
894904
ex_msg = TestWaitSignalsSignalTimeoutErrorMessage.get_exception_message(excinfo)
895-
assert ex_msg == "Emitted signals: [signal]. Missing: " \
896-
"[signal_args(QString,int), signal_args(QString,int)]"
905+
assert ex_msg == ("Emitted signals: [signal]. Missing: "
906+
"[signal_args(QString,int), signal_args(QString,int)]")
897907

898908
def test_simple_order_second_signal_emitted(self, qtbot, signaller):
899909
"""
@@ -905,8 +915,11 @@ def test_simple_order_second_signal_emitted(self, qtbot, signaller):
905915
check_params_cbs=None, order="simple", raising=True):
906916
signaller.signal_args.emit("1", 1)
907917
ex_msg = TestWaitSignalsSignalTimeoutErrorMessage.get_exception_message(excinfo)
908-
assert ex_msg == "Emitted signals: [signal_args('1', 1)]. Missing: " \
909-
"[signal(), signal_args(QString,int), signal_args(QString,int)]"
918+
signal_args = "'1', 1"
919+
if PY_2:
920+
signal_args = "u'1', 1"
921+
assert ex_msg == ("Emitted signals: [signal_args({})]. Missing: "
922+
"[signal(), signal_args(QString,int), signal_args(QString,int)]").format(signal_args)
910923

911924
def test_strict_order_violation(self, qtbot, signaller):
912925
"""
@@ -920,9 +933,13 @@ def test_strict_order_violation(self, qtbot, signaller):
920933
signaller.signal_args.emit("1", 1)
921934
signaller.signal.emit()
922935
ex_msg = TestWaitSignalsSignalTimeoutErrorMessage.get_exception_message(excinfo)
923-
assert ex_msg == "Signal order violated! Expected signal() as 1st signal, " \
924-
"but received signal_args('1', 1) instead. Emitted signals: [signal_args('1', 1), signal]. " \
925-
"Missing: [signal(), signal_args(QString,int), signal_args(QString,int)]"
936+
signal_args = "'1', 1"
937+
if PY_2:
938+
signal_args = "u'1', 1"
939+
assert ex_msg == ("Signal order violated! Expected signal() as 1st signal, "
940+
"but received signal_args({}) instead. Emitted signals: [signal_args({}), signal]. "
941+
"Missing: [signal(), signal_args(QString,int), signal_args(QString,int)]").format(signal_args,
942+
signal_args)
926943

927944
def test_degenerate_error_msg(self, qtbot, signaller):
928945
"""
@@ -939,9 +956,9 @@ def test_degenerate_error_msg(self, qtbot, signaller):
939956
raising=True):
940957
signaller.signal.emit()
941958
ex_msg = TestWaitSignalsSignalTimeoutErrorMessage.get_exception_message(excinfo)
942-
assert ex_msg == "Received 1 of the 3 expected signals. " \
943-
"To improve this error message, provide the names of the signals " \
944-
"in the waitSignals() call."
959+
assert ex_msg == ("Received 1 of the 3 expected signals. "
960+
"To improve this error message, provide the names of the signals "
961+
"in the waitSignals() call.")
945962

946963
def test_self_defined_signal_name(self, qtbot, signaller):
947964
"""
@@ -959,8 +976,8 @@ def my_cb(str_param, int_param):
959976
raising=True):
960977
pass
961978
ex_msg = TestWaitSignalsSignalTimeoutErrorMessage.get_exception_message(excinfo)
962-
assert ex_msg == "Emitted signals: None. " \
963-
"Missing: [signal_without_args, signal_with_args (callback: my_cb)]"
979+
assert ex_msg == ("Emitted signals: None. "
980+
"Missing: [signal_without_args, signal_with_args (callback: my_cb)]")
964981

965982
@staticmethod
966983
def get_exception_message(excinfo):

0 commit comments

Comments
 (0)