Files
superqt/tests/test_ensure_thread.py
Talley Lambert d25f4c1cf7 Use qtpy, deprecate superqt.qtcompat, drop support for Qt <5.12 (#39)
* remove qtcompat

* change imports

* change codecov

* add dep

* run tests against dalthviz branch

* update

* more replace

* pin pyside6 for sake of test

* add deprecation

* drop qt 5.11

* unpin pyside6
2022-01-07 12:19:59 -05:00

220 lines
6.6 KiB
Python

import inspect
import os
import time
from concurrent.futures import Future, TimeoutError
import pytest
from qtpy.QtCore import QCoreApplication, QObject, QThread, Signal
from superqt.utils import ensure_main_thread, ensure_object_thread
skip_on_ci = pytest.mark.skipif(bool(os.getenv("CI")), reason="github hangs")
class SampleObject(QObject):
assigment_done = Signal()
def __init__(self):
super().__init__()
self.main_thread_res = {}
self.object_thread_res = {}
self.main_thread_prop_val = None
self.sample_thread_prop_val = None
def long_wait(self):
time.sleep(1)
@property
def sample_main_thread_property(self):
return self.main_thread_prop_val
@sample_main_thread_property.setter # type: ignore
@ensure_main_thread()
def sample_main_thread_property(self, value):
if QThread.currentThread() is not QCoreApplication.instance().thread():
raise RuntimeError("Wrong thread")
self.main_thread_prop_val = value
self.assigment_done.emit()
@property
def sample_object_thread_property(self):
return self.sample_thread_prop_val
@sample_object_thread_property.setter # type: ignore
@ensure_object_thread()
def sample_object_thread_property(self, value):
if QThread.currentThread() is not self.thread():
raise RuntimeError("Wrong thread")
self.sample_thread_prop_val = value
self.assigment_done.emit()
@ensure_main_thread
def check_main_thread(self, a, *, b=1):
if QThread.currentThread() is not QCoreApplication.instance().thread():
raise RuntimeError("Wrong thread")
self.main_thread_res = {"a": a, "b": b}
self.assigment_done.emit()
@ensure_object_thread
def check_object_thread(self, a, *, b=1):
if QThread.currentThread() is not self.thread():
raise RuntimeError("Wrong thread")
self.object_thread_res = {"a": a, "b": b}
self.assigment_done.emit()
@ensure_object_thread(await_return=True)
def check_object_thread_return(self, a):
if QThread.currentThread() is not self.thread():
raise RuntimeError("Wrong thread")
return a * 7
@ensure_object_thread(await_return=True, timeout=200)
def check_object_thread_return_timeout(self, a):
if QThread.currentThread() is not self.thread():
raise RuntimeError("Wrong thread")
time.sleep(1)
return a * 7
@ensure_object_thread(await_return=False)
def check_object_thread_return_future(self, a: int):
"""sample docstring"""
if QThread.currentThread() is not self.thread():
raise RuntimeError("Wrong thread")
time.sleep(0.4)
return a * 7
@ensure_main_thread(await_return=True)
def check_main_thread_return(self, a):
if QThread.currentThread() is not QCoreApplication.instance().thread():
raise RuntimeError("Wrong thread")
return a * 8
class LocalThread(QThread):
def __init__(self, ob):
super().__init__()
self.ob = ob
def run(self):
assert QThread.currentThread() is not QCoreApplication.instance().thread()
self.ob.check_main_thread(5, b=8)
self.ob.main_thread_prop_val = "text2"
class LocalThread2(QThread):
def __init__(self, ob):
super().__init__()
self.ob = ob
self.executed = False
def run(self):
assert QThread.currentThread() is not QCoreApplication.instance().thread()
assert self.ob.check_main_thread_return(5) == 40
self.executed = True
def test_only_main_thread(qapp):
ob = SampleObject()
ob.check_main_thread(1, b=3)
assert ob.main_thread_res == {"a": 1, "b": 3}
ob.check_object_thread(2, b=4)
assert ob.object_thread_res == {"a": 2, "b": 4}
ob.sample_main_thread_property = 5
assert ob.sample_main_thread_property == 5
ob.sample_object_thread_property = 7
assert ob.sample_object_thread_property == 7
def test_main_thread(qtbot):
ob = SampleObject()
t = LocalThread(ob)
with qtbot.waitSignal(t.finished):
t.start()
assert ob.main_thread_res == {"a": 5, "b": 8}
assert ob.sample_main_thread_property == "text2"
def test_main_thread_return(qtbot):
ob = SampleObject()
t = LocalThread2(ob)
with qtbot.wait_signal(t.finished):
t.start()
assert t.executed
def test_names(qapp):
ob = SampleObject()
assert ob.check_object_thread.__name__ == "check_object_thread"
assert ob.check_object_thread_return.__name__ == "check_object_thread_return"
assert (
ob.check_object_thread_return_timeout.__name__
== "check_object_thread_return_timeout"
)
assert (
ob.check_object_thread_return_future.__name__
== "check_object_thread_return_future"
)
assert ob.check_object_thread_return_future.__doc__ == "sample docstring"
signature = inspect.signature(ob.check_object_thread_return_future)
assert len(signature.parameters) == 1
assert list(signature.parameters.values())[0].name == "a"
assert list(signature.parameters.values())[0].annotation == int
assert ob.check_main_thread_return.__name__ == "check_main_thread_return"
@skip_on_ci
def test_object_thread_return(qtbot):
ob = SampleObject()
thread = QThread()
thread.start()
ob.moveToThread(thread)
assert ob.check_object_thread_return(2) == 14
assert ob.thread() is thread
with qtbot.waitSignal(thread.finished):
thread.quit()
@skip_on_ci
def test_object_thread_return_timeout(qtbot):
ob = SampleObject()
thread = QThread()
thread.start()
ob.moveToThread(thread)
with pytest.raises(TimeoutError):
ob.check_object_thread_return_timeout(2)
with qtbot.waitSignal(thread.finished):
thread.quit()
@skip_on_ci
def test_object_thread_return_future(qtbot):
ob = SampleObject()
thread = QThread()
thread.start()
ob.moveToThread(thread)
future = ob.check_object_thread_return_future(2)
assert isinstance(future, Future)
assert future.result() == 14
with qtbot.waitSignal(thread.finished):
thread.quit()
@skip_on_ci
def test_object_thread(qtbot):
ob = SampleObject()
thread = QThread()
thread.start()
ob.moveToThread(thread)
with qtbot.waitSignal(ob.assigment_done):
ob.check_object_thread(2, b=4)
assert ob.object_thread_res == {"a": 2, "b": 4}
with qtbot.waitSignal(ob.assigment_done):
ob.sample_object_thread_property = "text"
assert ob.sample_object_thread_property == "text"
assert ob.thread() is thread
with qtbot.waitSignal(thread.finished):
thread.quit()