Skip to content

Commit 7ea16a2

Browse files
committed
Merge remote-tracking branch 'fabioz/weak_widget_references'
2 parents aa77557 + ac6a89a commit 7ea16a2

File tree

3 files changed

+52
-30
lines changed

3 files changed

+52
-30
lines changed

pytestqt/_tests/pytest.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[pytest]
2+
addopts = -p pytestqt.plugin

pytestqt/_tests/test_basics.py

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
1-
from pytestqt.qt_compat import QtGui, Qt, QEvent, QtCore
1+
import weakref
22
import pytest
3+
from pytestqt.qt_compat import QtGui, Qt, QEvent, QtCore
34

45

56
def test_basics(qtbot):
67
"""
78
Basic test that works more like a sanity check to ensure we are setting up a QApplication
8-
properly and are able to display a simple event_recorder.
9+
properly and are able to display a simple event_recorder.
910
"""
10-
assert type(QtGui.qApp) is QtGui.QApplication
11+
assert isinstance(QtGui.qApp, QtGui.QApplication)
1112
widget = QtGui.QWidget()
1213
qtbot.addWidget(widget)
1314
widget.setWindowTitle('W1')
1415
widget.show()
15-
16+
1617
assert widget.isVisible()
1718
assert widget.windowTitle() == 'W1'
18-
19-
19+
20+
2021
def test_key_events(qtbot, event_recorder):
2122
"""
2223
Basic key events test.
@@ -27,16 +28,16 @@ def extract(key_event):
2728
key_event.key(),
2829
key_event.text(),
2930
)
30-
31+
3132
event_recorder.registerEvent(QtGui.QKeyEvent, extract)
32-
33+
3334
qtbot.keyPress(event_recorder, 'a')
3435
assert event_recorder.event_data == (QEvent.KeyPress, int(Qt.Key_A), 'a')
35-
36+
3637
qtbot.keyRelease(event_recorder, 'a')
3738
assert event_recorder.event_data == (QEvent.KeyRelease, int(Qt.Key_A), 'a')
38-
39-
39+
40+
4041
def test_mouse_events(qtbot, event_recorder):
4142
"""
4243
Basic mouse events test.
@@ -49,10 +50,10 @@ def extract(mouse_event):
4950
)
5051

5152
event_recorder.registerEvent(QtGui.QMouseEvent, extract)
52-
53+
5354
qtbot.mousePress(event_recorder, Qt.LeftButton)
5455
assert event_recorder.event_data == (QEvent.MouseButtonPress, Qt.LeftButton, Qt.NoModifier)
55-
56+
5657
qtbot.mousePress(event_recorder, Qt.RightButton, Qt.AltModifier)
5758
assert event_recorder.event_data == (QEvent.MouseButtonPress, Qt.RightButton, Qt.AltModifier)
5859

@@ -67,32 +68,41 @@ def test_stop_for_interaction(qtbot):
6768
QtCore.QTimer.singleShot(0, widget.close)
6869
qtbot.stopForInteraction()
6970

70-
71+
72+
def test_widget_kept_as_weakref(qtbot):
73+
"""
74+
Test if the widget is kept as a weak reference in QtBot
75+
"""
76+
widget = QtGui.QWidget()
77+
qtbot.add_widget(widget)
78+
widget = weakref.ref(widget)
79+
assert widget() is None
80+
81+
7182
class EventRecorder(QtGui.QWidget):
83+
7284
"""
7385
Widget that records some kind of events sent to it.
74-
86+
7587
When this event_recorder receives a registered event (by calling `registerEvent`), it will call
76-
the associated *extract* function and hold the return value from the function in the
88+
the associated *extract* function and hold the return value from the function in the
7789
`event_data` member.
7890
"""
79-
91+
8092
def __init__(self):
8193
QtGui.QWidget.__init__(self)
8294
self._event_types = {}
8395
self.event_data = None
84-
85-
96+
8697
def registerEvent(self, event_type, extract_func):
8798
self._event_types[event_type] = extract_func
88-
89-
99+
90100
def event(self, ev):
91101
for event_type, extract_func in self._event_types.items():
92-
if type(ev) is event_type:
102+
if isinstance(ev, event_type):
93103
self.event_data = extract_func(ev)
94104
return True
95-
105+
96106
return False
97107

98108

@@ -101,5 +111,3 @@ def event_recorder(qtbot):
101111
widget = EventRecorder()
102112
qtbot.addWidget(widget)
103113
return widget
104-
105-

pytestqt/plugin.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import functools
33
import sys
44
import traceback
5+
import weakref
56

67
import pytest
78

@@ -173,7 +174,9 @@ def _close(self):
173174
Clear up method. Called at the end of each test that uses a ``qtbot`` fixture.
174175
"""
175176
for w in self._widgets:
176-
w.close()
177+
w = w()
178+
if w is not None:
179+
w.close()
177180
self._widgets[:] = []
178181

179182
def addWidget(self, widget):
@@ -184,7 +187,9 @@ def addWidget(self, widget):
184187
:param QWidget widget:
185188
Widget to keep track of.
186189
"""
187-
self._widgets.append(widget)
190+
self._widgets.append(weakref.ref(widget))
191+
192+
add_widget = addWidget # pep-8 alias
188193

189194
def waitForWindowShown(self, widget):
190195
"""
@@ -197,6 +202,8 @@ def waitForWindowShown(self, widget):
197202
"""
198203
QtTest.QTest.qWaitForWindowShown(widget)
199204

205+
wait_for_window_shown = waitForWindowShown # pep-8 alias
206+
200207
def stopForInteraction(self):
201208
"""
202209
Stops the current test flow, letting the user interact with any visible widget.
@@ -209,12 +216,15 @@ def stopForInteraction(self):
209216
210217
.. note:: As a convenience, it is also aliased as `stop`.
211218
"""
212-
widget_visibility = [widget.isVisible() for widget in self._widgets]
219+
widget_and_visibility = []
220+
for weak_widget in self._widgets:
221+
widget = weak_widget()
222+
if widget is not None:
223+
widget_and_visibility.append((widget, widget.isVisible()))
213224

214225
self._app.exec_()
215226

216-
for index, visible in enumerate(widget_visibility):
217-
widget = self._widgets[index]
227+
for widget, visible in widget_and_visibility:
218228
widget.setVisible(visible)
219229

220230
stop = stopForInteraction
@@ -256,6 +266,8 @@ def waitSignal(self, signal=None, timeout=1000):
256266
blocker.connect(signal)
257267
return blocker
258268

269+
wait_signal = waitSignal # pep-8 alias
270+
259271

260272
class SignalBlocker(object):
261273

0 commit comments

Comments
 (0)