def test_AsyncNAM_tiff_success(self): """Test NAM in async mode with binary files to check for bytearray conversion.""" # test success self.checkEx = None def finishedListener(): try: httpResult = nam.httpResult() self.assertTrue(httpResult.ok) # No status code in offline #self.assertEqual(httpResult.status_code, 200) self.assertEqual(httpResult.content, open(tiff_file, 'rb').read(), "Image differs") except Exception as ex: self.checkEx = ex loop = QtCore.QEventLoop() tiff_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data', '1.1.01.tiff') nam = NetworkAccessManager(debug=True) (response, content) = nam.request("file://%s" % tiff_file, blocking=False) nam.reply.finished.connect(finishedListener) nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection) loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents) if self.checkEx: raise self.checkEx
def test_AsyncNAM_abort(self): """Test ANAM if it can manages abort during connection""" from threading import Timer # connection redirection self.checkEx = None def finishedListener(): try: httpResult = nam.httpResult() self.assertIn('Operation canceled', str(httpResult.exception)) self.assertIsInstance(httpResult.exception, RequestsExceptionUserAbort) except Exception as ex: self.checkEx = ex loop = QtCore.QEventLoop() nam = NetworkAccessManager(debug=True) nam.request(self.serverUrl + '/delay/5', blocking=False) nam.reply.finished.connect(finishedListener) nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection) # abort after 1sec t = Timer(1, nam.abort) t.start() loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents) if self.checkEx: raise self.checkEx
def start(self): try: worker = RequestWorker(self.url, self.method, self.payload, self.headers) pause = QtCore.QEventLoop() worker.finished.connect(pause.quit) worker.successfully_finished.connect(self.save_resp) worker.error.connect(self.save_exception) start_worker( worker, iface, QtWidgets.QApplication.translate( "LDMP", u'Contacting {} server...'.format(self.server_name))) pause.exec_() if self.get_exception(): raise self.get_exception() except requests.exceptions.ConnectionError: log('API unable to access server - check internet connection') QtWidgets.QMessageBox.critical( None, QtWidgets.QApplication.translate("LDMP", "Error"), QtWidgets.QApplication.translate( "LDMP", u"Unable to login to {} server. Check your internet connection." .format(self.server_name))) resp = None except requests.exceptions.Timeout: log('API unable to login - general error') QtWidgets.QMessageBox.critical( None, QtWidgets.QApplication.translate("LDMP", "Error"), QtWidgets.QApplication.translate( "LDMP", u"Unable to connect to {} server.".format( self.server_name))) resp = None
def execute(func, message=None): ''' Executes a lengthy tasks in a separate thread and displays a waiting dialog if needed. Sets the cursor to wait cursor while the task is running. This function does not provide any support for progress indication :param func: The function to execute. :param message: The message to display in the wait dialog. If not passed, the dialog won't be shown ''' global _dialog cursor = QtWidgets.QApplication.overrideCursor() waitCursor = (cursor is not None and cursor.shape() == QtCore.Qt.WaitCursor) dialogCreated = False try: QtCore.QCoreApplication.processEvents() if not waitCursor: QtWidgets.QApplication.setOverrideCursor( QtGui.QCursor(QtCore.Qt.WaitCursor)) if message is not None: t = ExecutorThread(func) loop = QtCore.QEventLoop() t.finished.connect(loop.exit, QtCore.Qt.QueuedConnection) if _dialog is None: dialogCreated = True _dialog = QtGui.QProgressDialog(message, "Running", 0, 0, iface.mainWindow()) _dialog.setWindowTitle("Running") _dialog.setWindowModality(QtCore.Qt.WindowModal) _dialog.setMinimumDuration(1000) _dialog.setMaximum(100) _dialog.setValue(0) _dialog.setMaximum(0) _dialog.setCancelButton(None) else: oldText = _dialog.labelText() _dialog.setLabelText(message) QtWidgets.QApplication.processEvents() t.start() loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents) if t.exception is not None: raise t.exception return t.returnValue else: return func() finally: if message is not None: if dialogCreated: _dialog.reset() _dialog = None else: _dialog.setLabelText(oldText) if not waitCursor: QtWidgets.QApplication.restoreOverrideCursor() QtCore.QCoreApplication.processEvents()
def start(self): try: worker = DownloadWorker(self.url, self.outfile) pause = QtCore.QEventLoop() worker.finished.connect(pause.quit) worker.successfully_finished.connect(self.save_resp) worker.error.connect(self.save_exception) start_worker( worker, iface, QtWidgets.QApplication.translate( "MISLAND", u'Downloading {}').format(self.outfile)) pause.exec_() if self.get_exception(): raise self.get_exception() except requests.exceptions.ChunkedEncodingError: log("Download failed due to ChunkedEncodingError - likely a connection loss" ) QtWidgets.QMessageBox.critical( None, QtWidgets.QApplication.translate("MISLAND", "Error"), QtWidgets.QApplication.translate( "MISLAND", "Download failed. Check your internet connection.")) return False except requests.exceptions.ConnectionError: log("Download failed due to connection error") QtWidgets.QMessageBox.critical( None, QtWidgets.QApplication.translate("MISLAND", "Error"), QtWidgets.QApplication.translate( "MISLAND", "Unable to access internet. Check your internet connection." )) return False except requests.exceptions.Timeout: log('Download timed out.') QtWidgets.QMessageBox.critical( None, QtWidgets.QApplication.translate("MISLAND", "Error"), QtWidgets.QApplication.translate( "MISLAND", "Download timed out. Check your internet connection.")) return False except DownloadError: log("Download failed.") QtWidgets.QMessageBox.critical( None, QtWidgets.QApplication.translate("MISLAND", "Error"), QtWidgets.QApplication.translate( "MISLAND", "Download failed. Task has expired. Kindly rerun task. ")) return False return True
def test_AsyncNAM_success(self): """Test ANAM if it can manages success.""" # test success self.checkEx = None def finishedListener(): try: httpResult = nam.httpResult() self.assertTrue(httpResult.ok) self.assertEqual(httpResult.status_code, 200) except Exception as ex: self.checkEx = ex loop = QtCore.QEventLoop() nam = NetworkAccessManager(debug=True) nam.request(self.serverUrl + '/get', blocking=False) nam.reply.finished.connect(finishedListener) nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection) loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents) if self.checkEx: raise self.checkEx
def test_AsyncNAM_forbidden(self): """Test ANAM if it can manages 403 (forbidden)""" # connection refused http 403 self.checkEx = None def finishedListener(): try: httpResult = nam.httpResult() self.assertIn('server replied: FORBIDDEN', str(httpResult.exception)) self.assertIsInstance(httpResult.exception, RequestsException) except Exception as ex: self.checkEx = ex loop = QtCore.QEventLoop() nam = NetworkAccessManager(debug=True) nam.request(self.serverUrl + '/status/403', blocking=False) nam.reply.finished.connect(finishedListener) nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection) loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents) if self.checkEx: raise self.checkEx
def test_AsyncNAM_url_not_found(self): """Test ANAM if it can manages 404""" # test Url not found self.checkEx = None def finishedListener(): try: httpResult = nam.httpResult() self.assertEqual(httpResult.status_code, 404) self.assertIn('server replied: NOT FOUND', str(httpResult.exception)) except Exception as ex: self.checkEx = ex loop = QtCore.QEventLoop() nam = NetworkAccessManager(debug=True) nam.request(self.serverUrl + '/somethingwrong', blocking=False) nam.reply.finished.connect(finishedListener) nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection) loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents) if self.checkEx: raise self.checkEx
def test_AsyncNAM_local_timeout(self): """Test ANAM if it can manages operation canceled by client.""" """!!!Note!!! that finishedListener is emitted before than timeoutListener. When timeoutListener is called the httpResult has been changed to notify timout.""" # test url timeout by client timout self.checkEx = None def finishedListener(): try: httpResult = nam.httpResult() self.assertIn('Operation canceled', str(httpResult.exception)) self.assertIsInstance(httpResult.exception, RequestsException) except Exception as ex: self.checkEx = ex def timeoutListener(): try: httpResult = nam.httpResult() self.assertIn('Timeout error', str(httpResult.exception)) self.assertIsInstance(httpResult.exception, RequestsExceptionTimeout) except Exception as ex: self.checkEx = ex self.timeoutOriginal = self.settings.value(self.timeoutEntry) self.settings.setValue(self.timeoutEntry, 1000) loop = QtCore.QEventLoop() nam = NetworkAccessManager(debug=True) nam.request(self.serverUrl + '/delay/60', blocking=False) QgsNetworkAccessManager.instance().requestTimedOut.connect( timeoutListener) nam.reply.finished.connect(finishedListener) nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection) loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents) self.settings.setValue(self.timeoutEntry, self.timeoutOriginal) if self.checkEx: raise self.checkEx
def test_AsyncNAM_redirect(self): """Test ANAM if it can manages url redirect""" # connection redirection self.checkEx = None def finishedListener(): try: httpResult = nam.httpResult() self.assertIn('Host requires authentication', str(httpResult.exception)) self.assertIsInstance(httpResult.exception, RequestsException) except Exception as ex: self.checkEx = ex loop = QtCore.QEventLoop() nam = NetworkAccessManager(debug=True) nam.request(self.serverUrl + '/redirect-to?url=./status/401', blocking=False) nam.reply.finished.connect(finishedListener) nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection) loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents) if self.checkEx: raise self.checkEx
def wait_for_signal( signal, timeout: int = 10000) -> typing.ContextManager[EventLoopResult]: """Fire up a custom event loop and wait for the input signal to be emitted This function allows running QT async code in a blocking fashion. It works by spawning a Qt event loop. This custom loop has its `quit()` slot bound to the input `signal`. The event loop is `exec_`'ed, thus blocking the current thread until the the input `signal` is emitted. The main purpose for this context manager is to allow using Qt network requests inside a QgsTask. Since QgsTask is already running in the background, we simplify the handling of network requests and responses in order to make the code easier to grasp. """ loop = QtCore.QEventLoop() signal.connect(loop.quit) loop_result = EventLoopResult(result=None) yield loop_result QtCore.QTimer.singleShot(timeout, partial(_forcibly_terminate_loop, loop)) loop_result.result = not bool(loop.exec_())
def test_AsyncNAM_customException(self): """Test ANAM raise curstom exception.""" # test success class customEx(Exception): pass self.checkEx = None def finishedListener(): try: httpResult = nam.httpResult() self.assertIsInstance(httpResult.exception, customEx) except Exception as ex: self.checkEx = ex loop = QtCore.QEventLoop() nam = NetworkAccessManager(debug=True, exception_class=customEx) nam.request(self.serverUrl + '/somethingwrong', blocking=False) nam.reply.finished.connect(finishedListener) nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection) loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents) if self.checkEx: raise self.checkEx
def test_AsyncNAM_emptyreturn(self): """Test ANAM return value.""" loop = QtCore.QEventLoop() nam = NetworkAccessManager(debug=True) ret = nam.request('anyurl', blocking=False) self.assertEqual(ret, (None, None))