pytest-dev / pytest-dev/pytest-qt
QApplication.processEvents() blocks qtbot on MacOS
Open
Nobody has claimed this yet.
bug :bug:
macos :apple:
- Dominant language
- Python
- Stars
- 455
- Forks
- 72
- Avg merge
- 12h 26m
- Merged PRs (30d)
- 1
Description
If qtbot tries to stop waiting while QApplication.processEvents() is being called, the test will hang indefinitely.
What happens is that:
- qtbot creates a
QEventLoop - an event calling
QApplication.processEvents()is processed byQEventLoop - The qtbot timer event that calls
_quit_loop_by_timeoutis processed byQApplication.processEvents() - Somehow
self._loop.quit()doesn't quit the loop if it is called fromQApplication.processEvents()
Code to reproduce (save as test_qtbot.py):
import pytest
import time
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtCore import QEventLoop, QTimer
class MyWidget(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._timer = QTimer(self)
self._timer.setSingleShot(True)
self._timer.setInterval(10)
self._timer.timeout.connect(self._wait_process_events)
self._timer.start()
def _wait_process_events(self):
time.sleep(1)
QApplication.processEvents()
def test_qtbot(qtbot):
"""
qtbot does the following:
1. start QEventLoop
2. process an event that calls QApplication.processEvents()
3. this processes an event that calls loop.quit()
which doesn't quit the wait loop
"""
widget = MyWidget()
qtbot.addWidget(widget)
widget.show()
qtbot.wait(500)
if __name__ == "__main__":
pytest.main()
Versions I am using:
PyQt5 5.12.3
pytest 5.3.1
pytest-qt 3.2.2
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the test_qtbot.py reproducer and trace qtbot's QEventLoop, the _quit_loop_by_timeout timer callback, and self._loop.quit(). Compare how QApplication.processEvents() dispatches the timeout event on macOS. Done means the reproduced qtbot.wait(500) test exits instead of hanging.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, python
- Domain
- desktop, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100