Skip to content

Commit 08841de

Browse files
authored
Merge pull request #319 from ales-erjavec/geo-datasets-init
[ENH] GEO Datasets: Move GDSInfo initialization in a worker thread
2 parents b2f9763 + e206735 commit 08841de

File tree

3 files changed

+50
-29
lines changed

3 files changed

+50
-29
lines changed

.pre-commit-config.yaml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
repos:
22
- repo: https://github.com/psf/black
3-
rev: 23.7.0
3+
rev: 24.3.0
44
hooks:
55
- id: black
66
language_version: python3
77

88
- repo: https://github.com/timothycrosley/isort
9-
rev: 5.12.0
9+
rev: 5.13.2
1010
hooks:
1111
- id: isort
1212
language_version: python3
1313

1414
- repo: https://github.com/pycqa/flake8
15-
rev: 6.1.0
15+
rev: 7.0.0
1616
hooks:
1717
- id: flake8
1818
language_version: python3

orangecontrib/bioinformatics/tests/widgets/test_OWGEODatasets.py

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ def setUp(self):
1313
self.test_sample = 'GDS1001'
1414
self.test_organism = '10090'
1515
self.widget = self.create_widget(OWGEODatasets)
16+
self.wait_until_finished(self.widget)
17+
self.process_events()
1618

1719
def test_minimum_size(self):
1820
pass

orangecontrib/bioinformatics/widgets/OWGEODatasets.py

+45-26
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
""" Gene Expression Omnibus datasets widget """
2+
23
import sys
34
from types import SimpleNamespace
4-
from typing import Any, Optional, DefaultDict
5+
from typing import Any, Union, Optional, DefaultDict
56
from collections import defaultdict
67

78
import requests
89

9-
from AnyQt.QtCore import Qt
10+
from AnyQt.QtCore import Qt, QTimer
1011
from AnyQt.QtWidgets import (
1112
QSplitter,
1213
QTreeWidget,
@@ -63,6 +64,8 @@ def callback():
6364
nonlocal current_iter
6465
current_iter += 1
6566
state.set_progress_value(100 * (current_iter / max_iter))
67+
if state.is_interruption_requested():
68+
raise KeyboardInterrupt
6669

6770
state.set_status("Downloading...")
6871
res.gds_dataset = dataset_download(
@@ -71,6 +74,16 @@ def callback():
7174
return res
7275

7376

77+
class GDSInfoResult(SimpleNamespace):
78+
gds_info: Optional[GDSInfo]
79+
80+
81+
def run_gds_info_task(state: TaskState):
82+
state.set_status("Fetching index...")
83+
gds_info = GDSInfo()
84+
return GDSInfoResult(gds_info=gds_info)
85+
86+
7487
class GEODatasetsModel(TableModel):
7588
(
7689
indicator_col,
@@ -108,9 +121,9 @@ def render_pubmed_url(row):
108121
TableModel.Column(
109122
title(""),
110123
{
111-
Qt.DisplayRole: lambda row: " "
112-
if is_cached(items[row]["name"])
113-
else "",
124+
Qt.DisplayRole: lambda row: (
125+
" " if is_cached(items[row]["name"]) else ""
126+
),
114127
Qt.UserRole: lambda row: items[row],
115128
},
116129
),
@@ -211,6 +224,7 @@ class Warning(OWWidget.Warning):
211224

212225
class Error(OWWidget.Error):
213226
no_connection = Msg("Widget can't connect to serverfiles.")
227+
error = Msg("{}")
214228

215229
class Outputs:
216230
gds_data = Output("Expression Data", Table)
@@ -232,14 +246,7 @@ class Outputs:
232246
def __init__(self):
233247
OWWidget.__init__(self)
234248
ConcurrentWidgetMixin.__init__(self)
235-
236-
try:
237-
self.gds_info: Optional[GDSInfo] = GDSInfo()
238-
except requests.exceptions.ConnectionError:
239-
self.gds_info = {}
240-
self.Error.no_connection()
241-
return
242-
249+
self.gds_info: Optional[GDSInfo] = None
243250
self.gds_data: Optional[Table] = None
244251
self.__updating_filter = False
245252

@@ -291,7 +298,7 @@ def __init__(self):
291298
self.table_view.verticalHeader().setVisible(False)
292299
self.table_view.viewport().setMouseTracking(True)
293300

294-
self.table_model = GEODatasetsModel(self.gds_info)
301+
self.table_model = GEODatasetsModel({})
295302
self.proxy_model = FilterProxyModel()
296303
self.proxy_model.setSourceModel(self.table_model)
297304
self.table_view.setModel(self.proxy_model)
@@ -343,7 +350,7 @@ def __init__(self):
343350
)
344351
self._apply_filter()
345352

346-
self.commit()
353+
self.start(run_gds_info_task)
347354

348355
def _splitter_moved(self, *args):
349356
self.splitter_settings = [bytes(sp.saveState()) for sp in self.splitters]
@@ -452,7 +459,7 @@ def current_changed():
452459

453460
def _run(self):
454461
self.Warning.using_local_files.clear()
455-
if self.selected_gds is not None:
462+
if self.gds_info and self.selected_gds is not None:
456463
self.gds_data = None
457464
self.start(
458465
run_download_task,
@@ -541,16 +548,28 @@ def commit(self):
541548
self._run()
542549

543550
def on_exception(self, ex: Exception):
544-
self.Warning.using_local_files()
545-
546-
def on_done(self, result: Result):
547-
assert isinstance(result.gds_dataset, Table)
548-
self.gds_data = result.gds_dataset
549-
550-
if self.gds_info:
551-
self.table_model.update_cache_indicator()
552-
553-
self.Outputs.gds_data.send(self.gds_data)
551+
if isinstance(ex, requests.exceptions.ConnectionError):
552+
self.Warning.using_local_files()
553+
else:
554+
self.Error.error("", exc_info=ex)
555+
556+
def on_done(self, result: Union[GDSInfoResult, Result]):
557+
self.Error.error.clear()
558+
if isinstance(result, GDSInfoResult):
559+
self.gds_info = result.gds_info
560+
self.table_model = GEODatasetsModel(result.gds_info)
561+
self.proxy_model.setSourceModel(self.table_model)
562+
self.table_view.resizeColumnsToContents()
563+
self._set_selection()
564+
QTimer.singleShot(0, lambda: self.unconditional_commit())
565+
else:
566+
assert isinstance(result.gds_dataset, Table)
567+
self.gds_data = result.gds_dataset
568+
569+
if self.gds_info:
570+
self.table_model.update_cache_indicator()
571+
572+
self.Outputs.gds_data.send(self.gds_data)
554573

555574
def on_partial_result(self, result: Any) -> None:
556575
pass

0 commit comments

Comments
 (0)