mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-07 00:04:15 +02:00
[view.qt] refactoring: using a different approach to cancel file downloads to keep compatibility with older Python versions
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import operator
|
import operator
|
||||||
import os
|
import os
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
from logging import Logger
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
from typing import List, Optional, Dict
|
from typing import List, Optional, Dict
|
||||||
|
|
||||||
@@ -71,12 +72,13 @@ class PackagesTable(QTableWidget):
|
|||||||
COL_NUMBER = 9
|
COL_NUMBER = 9
|
||||||
DEFAULT_ICON_SIZE = QSize(16, 16)
|
DEFAULT_ICON_SIZE = QSize(16, 16)
|
||||||
|
|
||||||
def __init__(self, parent: QWidget, icon_cache: MemoryCache, download_icons: bool):
|
def __init__(self, parent: QWidget, icon_cache: MemoryCache, download_icons: bool, logger: Logger):
|
||||||
super(PackagesTable, self).__init__()
|
super(PackagesTable, self).__init__()
|
||||||
self.setObjectName('table_packages')
|
self.setObjectName('table_packages')
|
||||||
self.setParent(parent)
|
self.setParent(parent)
|
||||||
self.window = parent
|
self.window = parent
|
||||||
self.download_icons = download_icons
|
self.download_icons = download_icons
|
||||||
|
self.logger = logger
|
||||||
self.setColumnCount(self.COL_NUMBER)
|
self.setColumnCount(self.COL_NUMBER)
|
||||||
self.setFocusPolicy(Qt.NoFocus)
|
self.setFocusPolicy(Qt.NoFocus)
|
||||||
self.setShowGrid(False)
|
self.setShowGrid(False)
|
||||||
@@ -614,9 +616,10 @@ class PackagesTable(QTableWidget):
|
|||||||
return reduce(operator.add, [self.columnWidth(i) for i in range(self.columnCount())])
|
return reduce(operator.add, [self.columnWidth(i) for i in range(self.columnCount())])
|
||||||
|
|
||||||
def _setup_file_downloader(self, max_workers: int = 50, max_downloads: int = -1) -> None:
|
def _setup_file_downloader(self, max_workers: int = 50, max_downloads: int = -1) -> None:
|
||||||
self.file_downloader = URLFileDownloader(parent=self,
|
self.file_downloader = URLFileDownloader(logger=self.logger,
|
||||||
max_workers=max_workers,
|
max_workers=max_workers,
|
||||||
max_downloads=max_downloads)
|
max_downloads=max_downloads,
|
||||||
|
parent=self)
|
||||||
self.file_downloader.signal_downloaded.connect(self._update_pkg_icon)
|
self.file_downloader.signal_downloaded.connect(self._update_pkg_icon)
|
||||||
self.file_downloader.start()
|
self.file_downloader.start()
|
||||||
|
|
||||||
|
|||||||
@@ -1117,9 +1117,10 @@ class URLFileDownloader(QThread):
|
|||||||
|
|
||||||
signal_downloaded = pyqtSignal(str, bytes, object)
|
signal_downloaded = pyqtSignal(str, bytes, object)
|
||||||
|
|
||||||
def __init__(self, max_workers: int = 50, request_timeout: int = 30, inactivity_timeout: int = 3,
|
def __init__(self, logger: Logger, max_workers: int = 50, request_timeout: int = 30, inactivity_timeout: int = 3,
|
||||||
max_downloads: int = -1, parent: Optional[QWidget] = None):
|
max_downloads: int = -1, parent: Optional[QWidget] = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
self._logger = logger
|
||||||
self._queue = Queue()
|
self._queue = Queue()
|
||||||
self._max_workers = max_workers
|
self._max_workers = max_workers
|
||||||
self._request_timeout = request_timeout
|
self._request_timeout = request_timeout
|
||||||
@@ -1129,6 +1130,7 @@ class URLFileDownloader(QThread):
|
|||||||
|
|
||||||
def _get(self, url_: str, id_: Optional[object]):
|
def _get(self, url_: str, id_: Optional[object]):
|
||||||
if self._stop:
|
if self._stop:
|
||||||
|
self._logger.info(f"File '{url_}' download cancelled")
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -1136,21 +1138,31 @@ class URLFileDownloader(QThread):
|
|||||||
content = res.content if res.status_code == 200 else None
|
content = res.content if res.status_code == 200 else None
|
||||||
self.signal_downloaded.emit(url_, content, id_)
|
self.signal_downloaded.emit(url_, content, id_)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
sys.stderr.write(f"[ERROR] could not download file from '{url_}': "
|
self._logger.error(f"[ERROR] could not download file from '{url_}': "
|
||||||
f"{e.__class__.__name__}({str(e.args)})\n")
|
f"{e.__class__.__name__}({str(e.args)})\n")
|
||||||
|
|
||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
download_count = 0
|
download_count = 0
|
||||||
|
futures = []
|
||||||
with ThreadPoolExecutor(max_workers=self._max_workers) as executor:
|
with ThreadPoolExecutor(max_workers=self._max_workers) as executor:
|
||||||
while not self._stop and (self._max_downloads <= 0 or download_count < self._max_downloads):
|
while not self._stop and (self._max_downloads <= 0 or download_count < self._max_downloads):
|
||||||
try:
|
try:
|
||||||
url_, id_ = self._queue.get(timeout=self._inactivity_timeout)
|
url_, id_ = self._queue.get(timeout=self._inactivity_timeout)
|
||||||
executor.submit(self._get, url_, id_)
|
futures.append(executor.submit(self._get, url_, id_))
|
||||||
download_count += 1
|
download_count += 1
|
||||||
except Exception:
|
except Exception:
|
||||||
self._stop = True
|
self._stop = True
|
||||||
|
|
||||||
executor.shutdown(wait=False, cancel_futures=True)
|
cancelled_count = 0
|
||||||
|
for f in futures:
|
||||||
|
if not f.done():
|
||||||
|
f.cancel()
|
||||||
|
cancelled_count += 1
|
||||||
|
|
||||||
|
if cancelled_count > 0:
|
||||||
|
self._logger.info(f"{cancelled_count} file downloads cancelled")
|
||||||
|
|
||||||
|
self._logger.info(f"Finished to download files (count={download_count})")
|
||||||
|
|
||||||
def stop(self) -> None:
|
def stop(self) -> None:
|
||||||
self._stop = True
|
self._stop = True
|
||||||
|
|||||||
@@ -290,8 +290,10 @@ class ManageWindow(QWidget):
|
|||||||
self.table_container.setLayout(QVBoxLayout())
|
self.table_container.setLayout(QVBoxLayout())
|
||||||
self.table_container.layout().setContentsMargins(0, 0, 0, 0)
|
self.table_container.layout().setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
self.table_apps = PackagesTable(self, self.icon_cache,
|
self.table_apps = PackagesTable(parent=self,
|
||||||
download_icons=bool(self.config['download']['icons']))
|
icon_cache=self.icon_cache,
|
||||||
|
download_icons=bool(self.config['download']['icons']),
|
||||||
|
logger=logger)
|
||||||
self.table_apps.change_headers_policy()
|
self.table_apps.change_headers_policy()
|
||||||
self.table_container.layout().addWidget(self.table_apps)
|
self.table_container.layout().addWidget(self.table_apps)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user