class PyMod_protocol_thread(QtCore.QThread): """ Class for a 'QThread' to launch a function where a time-consuming process is executed. It is used when showing a 'Protocol_exec_dialog' dialog. """ # Signals. terminate_thread_signal = QtCore.pyqtSignal(int) exception_thread_signal = QtCore.pyqtSignal(Exception) def set_params(self, function, args, wait_start, wait_end): self.function = function self.args = args self.wait_start = wait_start self.wait_end = wait_end def run(self): if self.wait_start is not None: time.sleep(self.wait_start) # Attempts to execute the function in this thread. try: if type(self.args) is dict: self.function(**self.args) else: self.function(*self.args) self._wait_end() self.terminate_thread_signal.emit(0) # Terminate sucessully. # If there was an error, emit the exception, so that it can be handled in the main thread. except Exception as e: self._wait_end() self.exception_thread_signal.emit( e) # Terminate by raising an exception. def _wait_end(self): if self.wait_end is not None: time.sleep(self.wait_end)
class InstallerQThread(QtCore.QThread): """ A QThread wrapper for the installers. Contains methods that make sense only when this class is extended together with a PyMod_component_installer (or sub) class, creating a subclass that inherits both from this class and PyMod_component_installer. """ critical_error = QtCore.pyqtSignal(str, PyMod_component) info_message = QtCore.pyqtSignal(str, PyMod_component) established_connection = QtCore.pyqtSignal(PyMod_component) retrieved_size = QtCore.pyqtSignal(PyMod_component, int) set_update_status = QtCore.pyqtSignal(PyMod_component, str, str) terminated_installation = QtCore.pyqtSignal(PyMod_component) freeze_thread = QtCore.pyqtSignal(PyMod_component, int) def run(self): """this method is never called alone (see QThread documentation) but is executed when the Qthread.start() method is called if the flag 'install_mode' is True, the thread will install the databases, if not, it will only retrieve the file size from the server.""" # Only pings the remote source. if self.install_mode == "ping": # Returns 'False' if there is a connection error. time.sleep(0.5) connection = self.ping() if connection: self.component.can_be_downloaded = True else: try: # Actually performs the installation. self.download_and_install() except TerminateQThread as e: pass # emette un type error, oltre al gaierror, se non c'e' connessione internet. # Emette anche un EOFError e un TimeoutError se non fa in tempo a scaricare. except (gaierror, TypeError) as e: self.critical_error.emit( "Cannot connect to server. Please check Internet connection.", self.component) except EOFError as e: self.critical_error.emit( "Timeout expired for connection. Try again later.", self.component) except Exception as e: msg = str(e) self.critical_error.emit(msg, self.component) traceback.print_exc() ########################################################## # Wrapper for the signals. Used in installer subclasses. # ########################################################## def emit_signal(self, signal_name, *args, **kwargs): # getattr(self, signal_name).emit(*args, **kwargs) if signal_name == "set_update_status": self.set_update_status.emit(*args, **kwargs) elif signal_name == "retrieved_size": self.retrieved_size.emit(*args, **kwargs) elif signal_name == "critical_error": self.critical_error.emit(*args, **kwargs) elif signal_name == "terminated_installation": self.terminated_installation.emit(*args, **kwargs) else: raise KeyError("Unknown 'signal_name': %s" % signal_name)