checkpoint. beginning download process

This commit is contained in:
Brennen Raimer
2019-05-01 17:03:57 -04:00
parent cb491c7bbd
commit 602273a219
4 changed files with 144 additions and 13 deletions

View File

@@ -0,0 +1,30 @@
import json
from urllib.parse import urlparse
from urllib.request import urlopen
from pathlib import Path
import pytest
json_url = "https://raw.githubusercontent.com/norweeg/portable-computing-toolkit-installer/initial_dev/portable_computing_toolkit_installer/resources/supported_tools.json"
class TestJSON(object):
def test_json_url_valid(self):
global json_url
parsed = urlparse(json_url)
assert len(parsed) == 6
assert Path(parsed.path).suffix == ".json"
def test_json_accessible(self):
global json_url
json_file = urlopen(json_url)
assert json_file.code < 400
json_file.close()
def test_json_valid(self):
global json_url
with urlopen(json_url) as json_file:
json_data = json.load(json_file)
assert json_data

View File

@@ -0,0 +1,26 @@
import json
from urllib.request import urlopen
import requests
from pathlib import Path
from parsel import Selector
from w3lib.url import canonicalize_url
import pytest
json_url = "https://raw.githubusercontent.com/norweeg/portable-computing-toolkit-installer/initial_dev/portable_computing_toolkit_installer/resources/supported_tools.json"
class TestPages(object):
def test_pages_accessible(self):
global json_url
with urlopen(json_url) as json_file:
json_data = json.load(json_file)
with requests.Session() as session:
for page in [canonicalize_url(item["homepage"]) for item in json_data]:
try:
response = session.get(page, allow_redirects = True, verify = False)
except:
response = session.get(page.replace("http", "https", 1), allow_redirects = True, verify = False)
assert response.status_code < 400
html = response.text
assert html
assert Selector(text = html, type="html").getall()

View File

@@ -1,18 +1,23 @@
from pathlib import Path from pathlib import Path
import webbrowser import webbrowser
from queue import Queue, Empty
from PyQt5 import QtCore, QtGui, QtNetwork, QtWebEngineWidgets, QtWidgets from PyQt5 import QtCore, QtGui, QtNetwork, QtWebEngineWidgets, QtWidgets
from PyQt5.uic import loadUi from PyQt5.uic import loadUi
class Downloader(QtWidgets.QMainWindow): class Downloader(QtWidgets.QMainWindow):
def __init__(self, tool_name, tool_info, download_directory, parent = None, flags = None):
download_progress = QtCore.pyqtSignal(str, int, int)
def __init__(self, download_queue, install_ready, download_directory, parent = None, flags = None):
super().__init__(parent, flags) super().__init__(parent, flags)
loadUi(Path(__file__).parent / "downloader.ui", baseinstance = self) loadUi(Path(__file__).parent / "downloader.ui", baseinstance = self)
self.hide() self.hide()
#create an off-the-record profile, isolated from other Downloader objects #create an off-the-record profile, isolated from other Downloader objects
new_page = QtWebEngineWidgets.QtWebEnginePage(QtWebEngineWidgets.QWebEngineProfile(self.web_view)) new_page = QtWebEngineWidgets.QtWebEnginePage(QtWebEngineWidgets.QWebEngineProfile(self.web_view))
self.web_view.setPage(new_page) self.web_view.setPage(new_page)
self._load_result = Queue(maxsize=1)
#set application style and decorate pushbuttons #set application style and decorate pushbuttons
self._style = QtWidgets.QApplication.instance().style() self._style = QtWidgets.QApplication.instance().style()
self.setWindowIcon(QtWidgets.QApplication.instance().windowIcon()) self.setWindowIcon(QtWidgets.QApplication.instance().windowIcon())
@@ -29,14 +34,10 @@ class Downloader(QtWidgets.QMainWindow):
self.actionCancel.triggered.connect(self._cancel_manual_search) self.actionCancel.triggered.connect(self._cancel_manual_search)
self.actionCancel_and_Open_Issue_on_Github.triggered.connect(self._cancel_manual_search_open_issue) self.actionCancel_and_Open_Issue_on_Github.triggered.connect(self._cancel_manual_search_open_issue)
#set attributes #set attributes
self._tool_name = tool_name self._download_queue = download_queue
self._tool_info = tool_info self._install_ready = install_ready
self._download_directory = download_directory self._download_directory = download_directory
#name window from attribute
self.setWindowTitle(f"Find {self._tool_name}")
#get homepage from attributes and set home button to load it
self._home_page = tool_info["homepage"]
self.home_button.clicked.connect(lambda: self.web_view.load(QtCore.QUrl(self._home_page)))
def _reload_becomes_stop(self): def _reload_becomes_stop(self):
"""Turns the reload button into a stop button. """Turns the reload button into a stop button.
@@ -86,15 +87,42 @@ class Downloader(QtWidgets.QMainWindow):
self.web_view.load(QtCore.QUrl(self._home_page)) self.web_view.load(QtCore.QUrl(self._home_page))
def begin_auto_search(self): def begin_auto_search(self):
pass try:
tool_info = self._download_queue.get(timeout = 1)
except Empty:
QtCore.QThread.currentThread().quit()
else:
self._tool_name = tool_info["name"]
self._tool_info = tool_info
self._home_page = tool_info["homepage"]
#name window from attribute
self.setWindowTitle(f"Find {self._tool_name}")
#get homepage from attributes and set home button to load it
self.home_button.clicked.connect(lambda: self.web_view.load(QtCore.QUrl(self._home_page)))
self.web_view.loadFinished.connect()
def _download_file(self): self._download_file(self._find_installer_url())
def _find_installer_url(self):
self.web_view.load(QtCore.QUrl(self._tool_info["page"]))
load_result = self._load_result.get()
def _download_file(self, url):
pass pass
class DownloadWorker(QtCore.QRunnable): class DownloadWorker(QtCore.QRunnable):
def __init__(self, tool_name, tool_info, download_directory): def __init__(self, download_queue, install_ready, download_error, download_directory, wizard):
super().__init__() super().__init__()
self._downloader = Downloader(tool_name, tool_info, download_directory) self._download_queue = download_queue
self._install_ready = install_ready
self._download_directory = download_directory
self._wizard = wizard
def run(self): def run(self):
self._downloader.begin_auto_search() downloader = Downloader(self.download_queue, self._install_ready, self._download_error, self._download_directory)
downloader.download_progress.connect(self._wizard.track_progress)
downloader.begin_auto_search()

View File

@@ -10,6 +10,7 @@ import json
from collections import deque from collections import deque
from itertools import product from itertools import product
from functools import partial from functools import partial
from threading import Lock
import psutil import psutil
from PyQt5 import QtCore, QtGui, QtNetwork, QtWebEngineWidgets, QtWidgets from PyQt5 import QtCore, QtGui, QtNetwork, QtWebEngineWidgets, QtWidgets
@@ -24,6 +25,7 @@ except ImportError:
from validators.location_validator import Location_Validator from validators.location_validator import Location_Validator
from .menu_iterator import MenuIterator from .menu_iterator import MenuIterator
from .downloader import DownloadWorker, Downloader
class InstallerWizard(QtWidgets.QWizard): class InstallerWizard(QtWidgets.QWizard):
def __init__(self, parent=None): def __init__(self, parent=None):
@@ -49,6 +51,7 @@ class InstallerWizard(QtWidgets.QWizard):
self._network_manager = QtNetwork.QNetworkAccessManager(parent=QtWidgets.QApplication.instance()) self._network_manager = QtNetwork.QNetworkAccessManager(parent=QtWidgets.QApplication.instance())
self._thread_pool = QtCore.QThreadPool.globalInstance() self._thread_pool = QtCore.QThreadPool.globalInstance()
self._project_page=Path("https://github.com/norweeg/portable-computing-toolkit-installer/") self._project_page=Path("https://github.com/norweeg/portable-computing-toolkit-installer/")
self._progress_update_lock = Lock()
@QtCore.pyqtSlot("QUrl") @QtCore.pyqtSlot("QUrl")
def _link_clicked(self, address): def _link_clicked(self, address):
@@ -327,3 +330,47 @@ class InstallerWizard(QtWidgets.QWizard):
self._display_error(f"{str().join(names_of_dependant_items)} {depend_text} on {item.text(0)}") self._display_error(f"{str().join(names_of_dependant_items)} {depend_text} on {item.text(0)}")
item.setCheckState(0, QtCore.Qt.Checked) item.setCheckState(0, QtCore.Qt.Checked)
def _begin_downloads(self, download_queue = None, install_ready = None, download_directory = None):
if download_queue:
pass
else:
self._download_queue = Queue()
if install_ready:
pass
else:
self._install_ready = Queue()
self._download_error = Queue()
if download_directory:
pass
else:
try:
self._download_directory = QtCore.QTemporaryDir()
except Exception as e:
self._display_error(str(e), self._download_directory.errorString()).accepted.connect(lambda: self.back())
if self._download_queue.empty():
tools_by_name = {tool["name"]:tool for tool in self.__tools__}
self._download_progress = {}
for selected_tool in self._get_selections():
self._download_queue.put_nowait(tools_by_name[selected_tool.text(0)])
self.progress_bar.setRange(0, self._download_queue.qsize())
while self._thread_pool.activeThreadCount() < self._thread_pool.maxThreadCount() and not self._download_queue.empty():
self._thread_pool.tryStart(DownloadWorker(self._download_queue, self._install_ready, self._download_error, self._download_directory, self))
QtCore.QThread.currentThread().msleep(250)
assert self._download_error.empty()
@QtCore.pyqtSignal(str, int, int)
def track_progress(self, tool_name, bytes_received, bytes_total):
if tool_name not in [tool["name"] for tool in self.__tools__]:
return
else:
self._download_progress[tool_name] = bytes_received/bytes_total
self._progress_update_lock.acquire()
self.progress_bar.setValue(sum(self._download_progress.values()))
self._progress_update_lock.release()