Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH] ConcurrentWidgetMixin: Cancel task on input change #4219

Merged
merged 2 commits into from
Dec 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 20 additions & 17 deletions Orange/widgets/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -563,9 +563,10 @@ def test_setup_graph(self, timeout=DEFAULT_TIMEOUT):
properly set/updated"""
self.send_signal(self.widget.Inputs.data, self.data)

if self.widget.isBlocking():
spy = QSignalSpy(self.widget.blockingStateChanged)
self.assertTrue(spy.wait(timeout))
self.assertTrue(
self.signal_manager.wait_for_finished(self.widget, timeout),
f"Did not finish in the specified {timeout}ms timeout"
)

self.assertIsNotNone(self.widget.graph.scatterplot_item)

Expand Down Expand Up @@ -657,11 +658,10 @@ def test_plot_once(self, timeout=DEFAULT_TIMEOUT):

def test_subset_data_color(self, timeout=DEFAULT_TIMEOUT):
self.send_signal(self.widget.Inputs.data, self.data)

if self.widget.isBlocking():
spy = QSignalSpy(self.widget.blockingStateChanged)
self.assertTrue(spy.wait(timeout))

self.assertTrue(
self.signal_manager.wait_for_finished(self.widget, timeout),
f"Did not finish in the specified {timeout}ms timeout"
)
self.send_signal(self.widget.Inputs.data_subset, self.data[:10])
subset = [brush.color().name() == "#46befa" for brush in
self.widget.graph.scatterplot_item.data['brush'][:10]]
Expand Down Expand Up @@ -723,18 +723,20 @@ def test_invalidated_embedding(self, timeout=DEFAULT_TIMEOUT):

def test_saved_selection(self, timeout=DEFAULT_TIMEOUT):
self.send_signal(self.widget.Inputs.data, self.data)
if self.widget.isBlocking():
spy = QSignalSpy(self.widget.blockingStateChanged)
self.assertTrue(spy.wait(timeout))
self.assertTrue(
self.signal_manager.wait_for_finished(self.widget, timeout),
f"Did not finish in the specified {timeout}ms timeout"
)

self.widget.graph.select_by_indices(list(range(0, len(self.data), 10)))
settings = self.widget.settingsHandler.pack_data(self.widget)
w = self.create_widget(self.widget.__class__, stored_settings=settings)

self.send_signal(self.widget.Inputs.data, self.data, widget=w)
if w.isBlocking():
spy = QSignalSpy(w.blockingStateChanged)
self.assertTrue(spy.wait(timeout))
self.assertTrue(
self.signal_manager.wait_for_finished(w, timeout),
f"Did not finish in the specified {timeout}ms timeout"
)

self.assertEqual(np.sum(w.graph.selection), 15)
np.testing.assert_equal(self.widget.graph.selection, w.graph.selection)
Expand Down Expand Up @@ -770,9 +772,10 @@ def test_in_out_summary(self, timeout=DEFAULT_TIMEOUT):
self.assertEqual(info._StateInfo__output_summary.brief, "")

self.send_signal(self.widget.Inputs.data, self.data)
if self.widget.isBlocking():
spy = QSignalSpy(self.widget.blockingStateChanged)
self.assertTrue(spy.wait(timeout))
self.assertTrue(
self.signal_manager.wait_for_finished(self.widget, timeout),
f"Did not finish in the specified {timeout}ms timeout"
)
ind = self._select_data()
self.assertEqual(info._StateInfo__input_summary.brief,
str(len(self.data)))
Expand Down
1 change: 0 additions & 1 deletion Orange/widgets/unsupervised/owtsne.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,6 @@ def run(self):

def __ensure_task_same_for_pca(self, task: Task):
assert self.data is not None
assert task.data is self.data
assert task.normalize == self.normalize
assert task.pca_components == self.pca_components
assert isinstance(task.pca_projection, Table) and \
Expand Down
6 changes: 3 additions & 3 deletions Orange/widgets/unsupervised/tests/test_owdistances.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,12 @@ def test_too_big_array(self):

mock = Mock(side_effect=ValueError)
self.widget.compute_distances(mock, self.iris)
self.wait_until_stop_blocking()
self.wait_until_finished()
self.assertTrue(self.widget.Error.distances_value_error.is_shown())

mock = Mock(side_effect=MemoryError)
self.widget.compute_distances(mock, self.iris)
self.wait_until_stop_blocking()
self.wait_until_finished()
self.assertEqual(len(self.widget.Error.active), 1)
self.assertTrue(self.widget.Error.distances_memory_error.is_shown())

Expand All @@ -176,7 +176,7 @@ def test_negative_values_bhattacharyya(self):
if metric == distance.Bhattacharyya:
break
self.send_signal(self.widget.Inputs.data, self.iris)
self.wait_until_stop_blocking()
self.wait_until_finished()
self.assertTrue(self.widget.Error.distances_value_error.is_shown())
self.iris.X[0, 0] *= -1

Expand Down
4 changes: 2 additions & 2 deletions Orange/widgets/unsupervised/tests/test_owmds.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ def tearDown(self):
self.widget.onDeleteWidget()
super().tearDown()

def test_plot_once(self, timeout=5000):
def test_plot_once(self): # pylint: disable=arguments-differ
"""Test if data is plotted only once but committed on every input change"""
table = Table("heart_disease")
self.widget.setup_plot = Mock()
self.widget.commit = self.widget.unconditional_commit = Mock()
self.send_signal(self.widget.Inputs.data, table)
self.widget.commit.reset_mock()
self.wait_until_stop_blocking()
self.wait_until_finished()
self.widget.setup_plot.assert_called_once()
self.widget.commit.assert_called_once()

Expand Down
14 changes: 7 additions & 7 deletions Orange/widgets/unsupervised/tests/test_owtsne.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def test_normalize_data(self):
with patch("Orange.preprocess.preprocess.Normalize", wraps=Normalize) as normalize:
self.send_signal(self.widget.Inputs.data, self.data)
self.assertTrue(self.widget.controls.normalize.isEnabled())
self.wait_until_stop_blocking()
self.wait_until_finished()
normalize.assert_called_once()

# Disable checkbox
Expand All @@ -158,7 +158,7 @@ def test_normalize_data(self):
with patch("Orange.preprocess.preprocess.Normalize", wraps=Normalize) as normalize:
self.send_signal(self.widget.Inputs.data, self.data)
self.assertTrue(self.widget.controls.normalize.isEnabled())
self.wait_until_stop_blocking()
self.wait_until_finished()
normalize.assert_not_called()

# Normalization shouldn't work on sparse data
Expand All @@ -169,7 +169,7 @@ def test_normalize_data(self):
with patch("Orange.preprocess.preprocess.Normalize", wraps=Normalize) as normalize:
self.send_signal(self.widget.Inputs.data, sparse_data)
self.assertFalse(self.widget.controls.normalize.isEnabled())
self.wait_until_stop_blocking()
self.wait_until_finished()
normalize.assert_not_called()

@patch("Orange.projection.manifold.TSNEModel.optimize")
Expand All @@ -192,7 +192,7 @@ def _check_exaggeration(call, exaggeration):
self.wait_until_stop_blocking()
self.widget.controls.exaggeration.setValue(1)
self.widget.run_button.clicked.emit() # run with exaggeration 1
self.wait_until_stop_blocking()
self.wait_until_finished()
_check_exaggeration(optimize, 1)

# Reset and clear state
Expand All @@ -205,7 +205,7 @@ def _check_exaggeration(call, exaggeration):
self.wait_until_stop_blocking()
self.widget.controls.exaggeration.setValue(3)
self.widget.run_button.clicked.emit() # run with exaggeration 1
self.wait_until_stop_blocking()
self.wait_until_finished()
_check_exaggeration(optimize, 3)

def test_plot_once(self):
Expand All @@ -221,7 +221,7 @@ def test_plot_once(self):
# when the result was available.
self.widget.setup_plot.reset_mock()
self.widget.commit.reset_mock()
self.wait_until_stop_blocking()
self.wait_until_finished()

self.widget.setup_plot.assert_called_once()
self.widget.commit.assert_called_once()
Expand Down Expand Up @@ -295,7 +295,7 @@ def test_invalidation_flow(self):
# set global structure "on" (after the embedding is computed)
w.controls.multiscale.setChecked(False)
self.send_signal(w.Inputs.data, self.data)
self.wait_until_stop_blocking()
self.wait_until_finished()
self.assertFalse(self.widget.Information.modified.is_shown())
# All the embedding components should computed
self.assertIsNotNone(w.pca_projection)
Expand Down
4 changes: 2 additions & 2 deletions Orange/widgets/utils/concurrent.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,12 +560,12 @@ class ConcurrentWidgetMixin(ConcurrentMixin):
"""
def __set_state_ready(self):
self.progressBarFinished()
self.setBlocking(False)
self.setInvalidated(False)
self.setStatusMessage("")

def __set_state_busy(self):
self.progressBarInit()
self.setBlocking(True)
self.setInvalidated(True)

def start(self, task: Callable, *args, **kwargs):
self.__set_state_ready()
Expand Down
3 changes: 3 additions & 0 deletions Orange/widgets/utils/tests/concurrent_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ def on_done(self, result: Result):
self.run_button.setText("Start")
self.commit()

def on_exception(self, ex: Exception):
raise ex

# OWDataProjectionWidget
def set_data(self, data: Table):
super().set_data(data)
Expand Down
2 changes: 1 addition & 1 deletion Orange/widgets/utils/tests/test_concurrent_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def test_button_no_data(self):
def test_button_with_data(self):
self.send_signal(self.widget.Inputs.data, self.data)
self.assertEqual(self.widget.run_button.text(), "Stop")
self.wait_until_stop_blocking()
self.wait_until_finished()
self.assertEqual(self.widget.run_button.text(), "Start")

def test_button_toggle(self):
Expand Down
1 change: 1 addition & 0 deletions Orange/widgets/visualize/owfreeviz.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ def on_exception(self, ex: Exception):
# OWAnchorProjectionWidget
def set_data(self, data):
super().set_data(data)
self.graph.set_sample_size(None)
if self._invalidated:
self.init_projection()

Expand Down
6 changes: 5 additions & 1 deletion Orange/widgets/visualize/tests/test_owfreeviz.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def test_optimization_finish(self):
output1 = self.get_output(self.widget.Outputs.components)
self.widget.run_button.click()
self.assertEqual(self.widget.run_button.text(), "Stop")
self.wait_until_stop_blocking()
self.wait_until_finished()
self.assertEqual(self.widget.run_button.text(), "Start")
output2 = self.get_output(self.widget.Outputs.components)
self.assertTrue((output1.X != output2.X).any())
Expand Down Expand Up @@ -163,3 +163,7 @@ def test_run_do_not_modify_model_inplace(self):
self.assertIsNot(self.projection.proj, result.projection.proj)
self.assertTrue((self.projection.components_.T !=
result.projection.components_.T).any())


if __name__ == "__main__":
unittest.main()