def test_multiple_connections(qtbot): """Test the connect dict accepts a list of functions, and type checks""" test1_val = [0] test2_val = [0] def func(): return 1 def test1(v): test1_val[0] = 1 assert v == 1 def test2(v): test2_val[0] = 1 assert v == 1 thread_func = qthreading.thread_worker( func, connect={'returned': [test1, test2]}, start_thread=False) worker = thread_func() assert isinstance(worker, qthreading.FunctionWorker) with qtbot.waitSignal(worker.finished): worker.start() assert test1_val[0] == 1 assert test2_val[0] == 1 # they must all be functions with pytest.raises(TypeError): qthreading.thread_worker(func, connect={'returned': ['test1', test2]})() # they must all be functions with pytest.raises(TypeError): qthreading.thread_worker(func, connect=test1)()
def test_thread_generator_worker_in_main_thread(): """Test basic threadworker on a generator in the main thread with methods. """ def func(): i = 0 while i < 10: i += 1 incoming = yield i i = incoming if incoming is not None else i return 3 worker = qthreading.thread_worker(func, start_thread=False)() counter = 0 def handle_pause(): time.sleep(0.1) assert worker.is_paused worker.toggle_pause() def test_yield(v): nonlocal counter counter += 1 if v == 2: assert not worker.is_paused worker.pause() assert not worker.is_paused if v == 3: worker.send(7) if v == 9: worker.quit() def handle_abort(): assert counter == 5 # because we skipped a few by sending in 7 worker.paused.connect(handle_pause) assert isinstance(worker, qthreading.GeneratorWorker) worker.yielded.connect(test_yield) worker.aborted.connect(handle_abort) # NOTE: you shouldn't normally call worker.work()! If you do, it will NOT # be run in a separate thread (as it would for worker.start(). # This is for the sake of testing it in the main thread. assert worker.work() is None # because we aborted it assert not worker.is_paused assert counter == 5 worker2 = qthreading.thread_worker(func, start_thread=False)() assert worker2.work() == 3
def test_thread_worker(qtbot): """Test basic threadworker on a function""" func_val = [0] test_val = [0] def func(): func_val[0] = 1 return 1 def test(v): test_val[0] = 1 assert v == 1 thread_func = qthreading.thread_worker(func, connect={'returned': test}, start_thread=False) worker = thread_func() assert isinstance(worker, qthreading.FunctionWorker) assert func_val[0] == 0 with qtbot.waitSignal(worker.finished, timeout=20000): worker.start() assert func_val[0] == 1 assert test_val[0] == 1 assert worker.is_running is False
def test_thread_generator_worker(qtbot): """Test basic threadworker on a generator""" yeld_val = [0] test_val = [0] def func(): yield 1 yield 1 return 3 def test_return(v): yeld_val[0] = 1 assert v == 3 def test_yield(v): test_val[0] = 1 assert v == 1 thread_func = qthreading.thread_worker( func, connect={ 'returned': test_return, 'yielded': test_yield }, start_thread=False, ) worker = thread_func() assert isinstance(worker, qthreading.GeneratorWorker) with qtbot.waitSignal(worker.finished): worker.start() assert test_val[0] == 1 assert yeld_val[0] == 1
def test_thread_worker(qtbot): """Test basic threadworker on a function""" def func(): return 1 def test(v): assert v == 1 thread_func = qthreading.thread_worker(func, connect={'returned': test}) worker = thread_func() assert isinstance(worker, qthreading.FunctionWorker)
def test_function_worker_nonzero_total_warns(): def not_a_generator(): return with pytest.warns(RuntimeWarning): thread_func = qthreading.thread_worker( not_a_generator, progress={'total': 2}, start_thread=False, ) thread_func()
def test_generator_worker_with_no_total(): def func(): yield 1 thread_func = qthreading.thread_worker( func, progress=True, start_thread=False, ) worker = thread_func() assert worker.pbar.total == 0
def test_thread_worker_in_main_thread(): """Test basic threadworker on a function""" def func(x): return x thread_func = qthreading.thread_worker(func) worker = thread_func(2) # NOTE: you shouldn't normally call worker.work()! If you do, it will NOT # be run in a separate thread (as it would for worker.start(). # This is for the sake of testing it in the main thread. assert worker.work() == 2
def test_function_worker_0_total(): def func(): for _ in range(10): pass thread_func = qthreading.thread_worker( func, progress={'total': 0}, start_thread=False, ) worker = thread_func() assert worker.pbar.total == 0
def test_generator_worker_with_description(): def func(): yield 1 thread_func = qthreading.thread_worker( func, progress={ 'total': 1, 'desc': 'custom' }, start_thread=False, ) worker = thread_func() assert worker.pbar.desc == 'custom'
def test_thread_raises(qtbot): """Test exceptions get returned to main thread""" def func(): yield 1 yield 1 raise ValueError('whoops') def handle_raise(e): assert isinstance(e, ValueError) assert str(e) == 'whoops' thread_func = qthreading.thread_worker(func, connect={'errored': handle_raise}) worker = thread_func() assert isinstance(worker, qthreading.GeneratorWorker)
def test_function_worker_with_description(): def func(): for _ in range(10): pass thread_func = qthreading.thread_worker( func, progress={ 'total': 0, 'desc': 'custom' }, start_thread=False, ) worker = thread_func() assert worker.pbar.desc == 'custom'
def test_multiple_connections(qtbot): """Test the connect dict accepts a list of functions, and type checks""" def func(): return 1 def test1(v): assert v == 1 def test2(v): assert v == 1 thread_func = qthreading.thread_worker( func, connect={'returned': [test1, test2]}) worker = thread_func() assert isinstance(worker, qthreading.FunctionWorker) # they must all be functions with pytest.raises(TypeError): qthreading.thread_worker(func, connect={'returned': ['test1', test2]})() # they must all be functions with pytest.raises(TypeError): qthreading.thread_worker(func, connect=test1)()
def test_unstarted_worker_no_widget(make_napari_viewer): viewer = make_napari_viewer() def func(): for _ in range(5): yield thread_func = qthreading.thread_worker( func, progress={'total': 5}, start_thread=False, ) thread_func() assert not bool(viewer.window._qt_viewer.window()._activity_dialog. findChildren(QtLabeledProgressBar))
def test_thread_generator_worker(qtbot): """Test basic threadworker on a generator""" def func(): yield 1 yield 1 return 3 def test_return(v): assert v == 3 def test_yield(v): assert v == 1 thread_func = qthreading.thread_worker(func, connect={ 'returned': test_return, 'yielded': test_yield }) worker = thread_func() assert isinstance(worker, qthreading.GeneratorWorker)
def test_worker_with_progress(qtbot): test_val = [0] def func(): yield 1 yield 1 def test_yield(v): test_val[0] += 1 thread_func = qthreading.thread_worker( func, connect={'yielded': test_yield}, progress={'total': 2}, start_thread=False, ) worker = thread_func() with qtbot.waitSignal(worker.yielded): worker.start() assert worker.pbar.n == test_val[0]
def test_thread_raises(qtbot): """Test exceptions get returned to main thread""" handle_val = [0] def func(): yield 1 yield 1 raise ValueError('whoops') def handle_raise(e): handle_val[0] = 1 assert isinstance(e, ValueError) assert str(e) == 'whoops' thread_func = qthreading.thread_worker(func, connect={'errored': handle_raise}, start_thread=False) worker = thread_func() assert isinstance(worker, qthreading.GeneratorWorker) with qtbot.waitSignal(worker.finished): worker.start() assert handle_val[0] == 1
def test_abort_does_not_return(qtbot): loop_counter = 0 def long_running_func(): nonlocal loop_counter import time for i in range(5): yield loop_counter time.sleep(0.1) loop_counter += 1 abort_counter = 0 def count_abort(): nonlocal abort_counter abort_counter += 1 return_counter = 0 def returned_handler(value): nonlocal return_counter return_counter += 1 threaded_function = qthreading.thread_worker( long_running_func, connect={ 'returned': returned_handler, 'aborted': count_abort, }, ) worker = threaded_function() worker.quit() qtbot.wait(600) assert loop_counter < 4 assert abort_counter == 1 assert return_counter == 0