Beispiel #1
0
    def test_bad_script_dont_crash(self):  # spellok
        """Test regression #21270 (segfault)"""

        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())
        feedback = ConsoleFeedBack()

        task = QgsProcessingAlgRunnerTask(CrashingProcessingAlgorithm(), {}, context=context, feedback=feedback)
        self.assertTrue(task.isCanceled())
        self.assertIn('name \'ExampleProcessingAlgorithm\' is not defined', feedback._error)
    def test_bad_script_dont_crash(self):  # spellok
        """Test regression #21270 (segfault)"""

        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())
        feedback = ConsoleFeedBack()

        task = QgsProcessingAlgRunnerTask(CrashingProcessingAlgorithm(), {}, context=context, feedback=feedback)
        self.assertTrue(task.isCanceled())
        self.assertIn('name \'ExampleProcessingAlgorithm\' is not defined', feedback._error)
Beispiel #3
0
    def runAlgorithm(self):
        self.feedback = self.createFeedback()
        self.context = dataobjects.createContext(self.feedback)

        checkCRS = ProcessingConfig.getSetting(
            ProcessingConfig.WARN_UNMATCHING_CRS)
        try:
            parameters = self.getParameterValues()

            if checkCRS and not self.algorithm().validateInputCrs(
                    parameters, self.context):
                reply = QMessageBox.question(
                    self, self.tr("Unmatching CRS's"),
                    self.tr('Parameters do not all use the same CRS. This can '
                            'cause unexpected results.\nDo you want to '
                            'continue?'), QMessageBox.Yes | QMessageBox.No,
                    QMessageBox.No)
                if reply == QMessageBox.No:
                    return
            ok, msg = self.algorithm().checkParameterValues(
                parameters, self.context)
            if not ok:
                QMessageBox.warning(self,
                                    self.tr('Unable to execute algorithm'),
                                    msg)
                return
            self.runButton().setEnabled(False)
            self.cancelButton().setEnabled(False)
            buttons = self.mainWidget().iterateButtons
            self.iterateParam = None

            for i in range(len(list(buttons.values()))):
                button = list(buttons.values())[i]
                if button.isChecked():
                    self.iterateParam = list(buttons.keys())[i]
                    break

            self.clearProgress()
            self.setProgressText(
                QCoreApplication.translate('AlgorithmDialog',
                                           'Processing algorithm…'))

            self.setInfo(QCoreApplication.translate(
                'AlgorithmDialog',
                '<b>Algorithm \'{0}\' starting&hellip;</b>').format(
                    self.algorithm().displayName()),
                         escapeHtml=False)

            self.feedback.pushInfo(self.tr('Input parameters:'))
            display_params = []
            for k, v in parameters.items():
                display_params.append("'" + k + "' : " + self.algorithm(
                ).parameterDefinition(k).valueAsPythonString(v, self.context))
            self.feedback.pushCommandInfo('{ ' + ', '.join(display_params) +
                                          ' }')
            self.feedback.pushInfo('')
            start_time = time.time()

            if self.iterateParam:
                # Make sure the Log tab is visible before executing the algorithm
                try:
                    self.showLog()
                    self.repaint()
                except:
                    pass

                self.cancelButton().setEnabled(
                    self.algorithm().flags()
                    & QgsProcessingAlgorithm.FlagCanCancel)
                if executeIterating(self.algorithm(), parameters,
                                    self.iterateParam, self.context,
                                    self.feedback):
                    self.feedback.pushInfo(
                        self.tr('Execution completed in {0:0.2f} seconds').
                        format(time.time() - start_time))
                    self.cancelButton().setEnabled(False)
                    self.finish(True, parameters, self.context, self.feedback)
                else:
                    self.cancelButton().setEnabled(False)
                    self.resetGui()
            else:
                command = self.algorithm().asPythonCommand(
                    parameters, self.context)
                if command:
                    ProcessingLog.addToLog(command)
                QgsGui.instance().processingRecentAlgorithmLog().push(
                    self.algorithm().id())
                self.cancelButton().setEnabled(
                    self.algorithm().flags()
                    & QgsProcessingAlgorithm.FlagCanCancel)

                def on_complete(ok, results):
                    if ok:
                        self.feedback.pushInfo(
                            self.tr('Execution completed in {0:0.2f} seconds').
                            format(time.time() - start_time))
                        self.feedback.pushInfo(self.tr('Results:'))
                        self.feedback.pushCommandInfo(pformat(results))
                    else:
                        self.feedback.reportError(
                            self.tr('Execution failed after {0:0.2f} seconds').
                            format(time.time() - start_time))
                    self.feedback.pushInfo('')

                    if self.feedback_dialog is not None:
                        self.feedback_dialog.close()
                        self.feedback_dialog.deleteLater()
                        self.feedback_dialog = None

                    self.cancelButton().setEnabled(False)

                    if not self.in_place:
                        self.finish(ok, results, self.context, self.feedback)
                    elif ok:
                        self.close()

                    self.feedback = None
                    self.context = None

                if not self.in_place and not (
                        self.algorithm().flags()
                        & QgsProcessingAlgorithm.FlagNoThreading):
                    # Make sure the Log tab is visible before executing the algorithm
                    self.showLog()

                    task = QgsProcessingAlgRunnerTask(self.algorithm(),
                                                      parameters, self.context,
                                                      self.feedback)
                    if task.isCanceled():
                        on_complete(False, {})
                    else:
                        task.executed.connect(on_complete)
                        self.setCurrentTask(task)
                else:
                    self.proxy_progress = QgsProxyProgressTask(
                        QCoreApplication.translate(
                            "AlgorithmDialog", "Executing “{}”").format(
                                self.algorithm().displayName()))
                    QgsApplication.taskManager().addTask(self.proxy_progress)
                    self.feedback.progressChanged.connect(
                        self.proxy_progress.setProxyProgress)
                    self.feedback_dialog = self.createProgressDialog()
                    self.feedback_dialog.show()
                    if self.in_place:
                        ok, results = execute_in_place(self.algorithm(),
                                                       parameters,
                                                       self.context,
                                                       self.feedback)
                    else:
                        ok, results = execute(self.algorithm(), parameters,
                                              self.context, self.feedback)
                    self.feedback.progressChanged.disconnect()
                    self.proxy_progress.finalize(ok)
                    on_complete(ok, results)

        except AlgorithmDialogBase.InvalidParameterValue as e:
            try:
                self.buttonBox().accepted.connect(
                    lambda e=e: e.widget.setPalette(QPalette()))
                palette = e.widget.palette()
                palette.setColor(QPalette.Base, QColor(255, 255, 0))
                e.widget.setPalette(palette)
            except:
                pass
            self.messageBar().clearWidgets()
            self.messageBar().pushMessage(
                "",
                self.tr("Wrong or missing parameter value: {0}").format(
                    e.parameter.description()),
                level=Qgis.Warning,
                duration=5)
        except AlgorithmDialogBase.InvalidOutputExtension as e:
            try:
                self.buttonBox().accepted.connect(
                    lambda e=e: e.widget.setPalette(QPalette()))
                palette = e.widget.palette()
                palette.setColor(QPalette.Base, QColor(255, 255, 0))
                e.widget.setPalette(palette)
            except:
                pass
            self.messageBar().clearWidgets()
            self.messageBar().pushMessage("",
                                          e.message,
                                          level=Qgis.Warning,
                                          duration=5)
Beispiel #4
0
    def runAlgorithm(self):
        self.feedback = self.createFeedback()
        self.context = dataobjects.createContext(self.feedback)

        checkCRS = ProcessingConfig.getSetting(ProcessingConfig.WARN_UNMATCHING_CRS)
        try:
            parameters = self.getParameterValues()

            if checkCRS and not self.algorithm().validateInputCrs(parameters, self.context):
                reply = QMessageBox.question(self, self.tr("Unmatching CRS's"),
                                             self.tr('Parameters do not all use the same CRS. This can '
                                                     'cause unexpected results.\nDo you want to '
                                                     'continue?'),
                                             QMessageBox.Yes | QMessageBox.No,
                                             QMessageBox.No)
                if reply == QMessageBox.No:
                    return
            ok, msg = self.algorithm().checkParameterValues(parameters, self.context)
            if not ok:
                QMessageBox.warning(
                    self, self.tr('Unable to execute algorithm'), msg)
                return
            self.runButton().setEnabled(False)
            self.cancelButton().setEnabled(False)
            buttons = self.mainWidget().iterateButtons
            self.iterateParam = None

            for i in range(len(list(buttons.values()))):
                button = list(buttons.values())[i]
                if button.isChecked():
                    self.iterateParam = list(buttons.keys())[i]
                    break

            self.clearProgress()
            self.setProgressText(QCoreApplication.translate('AlgorithmDialog', 'Processing algorithm…'))

            self.setInfo(
                QCoreApplication.translate('AlgorithmDialog', '<b>Algorithm \'{0}\' starting&hellip;</b>').format(self.algorithm().displayName()), escapeHtml=False)

            self.feedback.pushInfo(self.tr('Input parameters:'))
            display_params = []
            for k, v in parameters.items():
                display_params.append("'" + k + "' : " + self.algorithm().parameterDefinition(k).valueAsPythonString(v, self.context))
            self.feedback.pushCommandInfo('{ ' + ', '.join(display_params) + ' }')
            self.feedback.pushInfo('')
            start_time = time.time()

            if self.iterateParam:
                # Make sure the Log tab is visible before executing the algorithm
                try:
                    self.showLog()
                    self.repaint()
                except:
                    pass

                self.cancelButton().setEnabled(self.algorithm().flags() & QgsProcessingAlgorithm.FlagCanCancel)
                if executeIterating(self.algorithm(), parameters, self.iterateParam, self.context, self.feedback):
                    self.feedback.pushInfo(
                        self.tr('Execution completed in {0:0.2f} seconds').format(time.time() - start_time))
                    self.cancelButton().setEnabled(False)
                    self.finish(True, parameters, self.context, self.feedback)
                else:
                    self.cancelButton().setEnabled(False)
                    self.resetGui()
            else:
                command = self.algorithm().asPythonCommand(parameters, self.context)
                if command:
                    ProcessingLog.addToLog(command)
                QgsGui.instance().processingRecentAlgorithmLog().push(self.algorithm().id())
                self.cancelButton().setEnabled(self.algorithm().flags() & QgsProcessingAlgorithm.FlagCanCancel)

                def on_complete(ok, results):
                    if ok:
                        self.feedback.pushInfo(self.tr('Execution completed in {0:0.2f} seconds').format(time.time() - start_time))
                        self.feedback.pushInfo(self.tr('Results:'))
                        self.feedback.pushCommandInfo(pformat(results))
                    else:
                        self.feedback.reportError(
                            self.tr('Execution failed after {0:0.2f} seconds').format(time.time() - start_time))
                    self.feedback.pushInfo('')

                    if self.feedback_dialog is not None:
                        self.feedback_dialog.close()
                        self.feedback_dialog.deleteLater()
                        self.feedback_dialog = None

                    self.cancelButton().setEnabled(False)

                    if not self.in_place:
                        self.finish(ok, results, self.context, self.feedback)
                    elif ok:
                        self.close()

                    self.feedback = None
                    self.context = None

                if not self.in_place and not (self.algorithm().flags() & QgsProcessingAlgorithm.FlagNoThreading):
                    # Make sure the Log tab is visible before executing the algorithm
                    self.showLog()

                    task = QgsProcessingAlgRunnerTask(self.algorithm(), parameters, self.context, self.feedback)
                    if task.isCanceled():
                        on_complete(False, {})
                    else:
                        task.executed.connect(on_complete)
                        self.setCurrentTask(task)
                else:
                    self.proxy_progress = QgsProxyProgressTask(QCoreApplication.translate("AlgorithmDialog", "Executing “{}”").format(self.algorithm().displayName()))
                    QgsApplication.taskManager().addTask(self.proxy_progress)
                    self.feedback.progressChanged.connect(self.proxy_progress.setProxyProgress)
                    self.feedback_dialog = self.createProgressDialog()
                    self.feedback_dialog.show()
                    if self.in_place:
                        ok, results = execute_in_place(self.algorithm(), parameters, self.context, self.feedback)
                    else:
                        ok, results = execute(self.algorithm(), parameters, self.context, self.feedback)
                    self.feedback.progressChanged.disconnect()
                    self.proxy_progress.finalize(ok)
                    on_complete(ok, results)

        except AlgorithmDialogBase.InvalidParameterValue as e:
            try:
                self.buttonBox().accepted.connect(lambda e=e:
                                                  e.widget.setPalette(QPalette()))
                palette = e.widget.palette()
                palette.setColor(QPalette.Base, QColor(255, 255, 0))
                e.widget.setPalette(palette)
            except:
                pass
            self.messageBar().clearWidgets()
            self.messageBar().pushMessage("", self.tr("Wrong or missing parameter value: {0}").format(e.parameter.description()),
                                          level=Qgis.Warning, duration=5)
        except AlgorithmDialogBase.InvalidOutputExtension as e:
            try:
                self.buttonBox().accepted.connect(lambda e=e:
                                                  e.widget.setPalette(QPalette()))
                palette = e.widget.palette()
                palette.setColor(QPalette.Base, QColor(255, 255, 0))
                e.widget.setPalette(palette)
            except:
                pass
            self.messageBar().clearWidgets()
            self.messageBar().pushMessage("", e.message,
                                          level=Qgis.Warning, duration=5)
Beispiel #5
0
    def runAlgorithm(self):
        self.feedback = self.createFeedback()
        self.context = dataobjects.createContext(self.feedback)
        self.context.setLogLevel(self.logLevel())

        checkCRS = ProcessingConfig.getSetting(
            ProcessingConfig.WARN_UNMATCHING_CRS)
        try:
            # messy as all heck, but we don't want to call the dialog's implementation of
            # createProcessingParameters as we want to catch the exceptions raised by the
            # parameter panel instead...
            parameters = {} if self.mainWidget() is None else self.mainWidget(
            ).createProcessingParameters()

            if checkCRS and not self.algorithm().validateInputCrs(
                    parameters, self.context):
                reply = QMessageBox.question(
                    self, self.tr("Unmatching CRS's"),
                    self.tr('Parameters do not all use the same CRS. This can '
                            'cause unexpected results.\nDo you want to '
                            'continue?'), QMessageBox.Yes | QMessageBox.No,
                    QMessageBox.No)
                if reply == QMessageBox.No:
                    return
            ok, msg = self.algorithm().checkParameterValues(
                parameters, self.context)
            if not ok:
                QMessageBox.warning(self,
                                    self.tr('Unable to execute algorithm'),
                                    msg)
                return

            self.blockControlsWhileRunning()
            self.setExecutedAnyResult(True)
            self.cancelButton().setEnabled(False)

            self.iterateParam = None

            for param in self.algorithm().parameterDefinitions():
                if isinstance(
                        parameters.get(param.name(), None),
                        QgsProcessingFeatureSourceDefinition
                ) and parameters[param.name(
                )].flags & QgsProcessingFeatureSourceDefinition.FlagCreateIndividualOutputPerInputFeature:
                    self.iterateParam = param.name()
                    break

            self.clearProgress()
            self.feedback.pushVersionInfo(self.algorithm().provider())
            if self.algorithm().provider().warningMessage():
                self.feedback.reportError(
                    self.algorithm().provider().warningMessage())

            self.feedback.pushInfo(
                QCoreApplication.translate('AlgorithmDialog',
                                           'Algorithm started at: {}').format(
                                               datetime.datetime.now().replace(
                                                   microsecond=0).isoformat()))

            self.setInfo(QCoreApplication.translate(
                'AlgorithmDialog',
                '<b>Algorithm \'{0}\' starting&hellip;</b>').format(
                    self.algorithm().displayName()),
                         escapeHtml=False)

            self.feedback.pushInfo(self.tr('Input parameters:'))
            display_params = []
            for k, v in parameters.items():
                display_params.append("'" + k + "' : " + self.algorithm(
                ).parameterDefinition(k).valueAsPythonString(v, self.context))
            self.feedback.pushCommandInfo('{ ' + ', '.join(display_params) +
                                          ' }')
            self.feedback.pushInfo('')
            start_time = time.time()

            def elapsed_time(start_time, result):
                delta_t = time.time() - start_time
                hours = int(delta_t / 3600)
                minutes = int((delta_t % 3600) / 60)
                seconds = delta_t - hours * 3600 - minutes * 60

                str_hours = [self.tr("hour"), self.tr("hours")][hours > 1]
                str_minutes = [self.tr("minute"),
                               self.tr("minutes")][minutes > 1]
                str_seconds = [self.tr("second"),
                               self.tr("seconds")][seconds != 1]

                if hours > 0:
                    elapsed = '{0} {1:0.2f} {2} ({3} {4} {5} {6} {7:0.0f} {2})'.format(
                        result, delta_t, str_seconds, hours, str_hours,
                        minutes, str_minutes, seconds)
                elif minutes > 0:
                    elapsed = '{0} {1:0.2f} {2} ({3} {4} {5:0.0f} {2})'.format(
                        result, delta_t, str_seconds, minutes, str_minutes,
                        seconds)
                else:
                    elapsed = '{0} {1:0.2f} {2}'.format(
                        result, delta_t, str_seconds)

                return (elapsed)

            if self.iterateParam:
                # Make sure the Log tab is visible before executing the algorithm
                try:
                    self.showLog()
                    self.repaint()
                except:
                    pass

                self.cancelButton().setEnabled(
                    self.algorithm().flags()
                    & QgsProcessingAlgorithm.FlagCanCancel)
                if executeIterating(self.algorithm(), parameters,
                                    self.iterateParam, self.context,
                                    self.feedback):
                    self.feedback.pushInfo(
                        self.tr(
                            elapsed_time(start_time,
                                         'Execution completed in')))
                    self.cancelButton().setEnabled(False)
                    self.finish(True, parameters, self.context, self.feedback)
                else:
                    self.cancelButton().setEnabled(False)
                    self.resetGui()
            else:
                self.history_details = {
                    'python_command':
                    self.algorithm().asPythonCommand(parameters, self.context),
                    'algorithm_id':
                    self.algorithm().id(),
                    'parameters':
                    self.algorithm().asMap(parameters, self.context)
                }
                process_command, command_ok = self.algorithm(
                ).asQgisProcessCommand(parameters, self.context)
                if command_ok:
                    self.history_details['process_command'] = process_command
                self.history_log_id, _ = QgsGui.historyProviderRegistry(
                ).addEntry('processing', self.history_details)

                QgsGui.instance().processingRecentAlgorithmLog().push(
                    self.algorithm().id())
                self.cancelButton().setEnabled(
                    self.algorithm().flags()
                    & QgsProcessingAlgorithm.FlagCanCancel)

                def on_complete(ok, results):
                    if ok:
                        self.feedback.pushInfo(
                            self.tr(
                                elapsed_time(start_time,
                                             'Execution completed in')))
                        self.feedback.pushInfo(self.tr('Results:'))
                        r = {
                            k: v
                            for k, v in results.items()
                            if k not in ('CHILD_RESULTS', 'CHILD_INPUTS')
                        }
                        self.feedback.pushCommandInfo(pformat(r))
                    else:
                        self.feedback.reportError(
                            self.tr(
                                elapsed_time(start_time,
                                             'Execution failed after')))
                    self.feedback.pushInfo('')

                    if self.history_log_id is not None:
                        self.history_details['results'] = results
                        QgsGui.historyProviderRegistry().updateEntry(
                            self.history_log_id, self.history_details)

                    if self.feedback_dialog is not None:
                        self.feedback_dialog.close()
                        self.feedback_dialog.deleteLater()
                        self.feedback_dialog = None

                    self.cancelButton().setEnabled(False)

                    self.finish(ok,
                                results,
                                self.context,
                                self.feedback,
                                in_place=self.in_place)

                    self.feedback = None
                    self.context = None

                if not self.in_place and not (
                        self.algorithm().flags()
                        & QgsProcessingAlgorithm.FlagNoThreading):
                    # Make sure the Log tab is visible before executing the algorithm
                    self.showLog()

                    task = QgsProcessingAlgRunnerTask(self.algorithm(),
                                                      parameters, self.context,
                                                      self.feedback)
                    if task.isCanceled():
                        on_complete(False, {})
                    else:
                        task.executed.connect(on_complete)
                        self.setCurrentTask(task)
                else:
                    self.proxy_progress = QgsProxyProgressTask(
                        QCoreApplication.translate(
                            "AlgorithmDialog", "Executing “{}”").format(
                                self.algorithm().displayName()))
                    QgsApplication.taskManager().addTask(self.proxy_progress)
                    self.feedback.progressChanged.connect(
                        self.proxy_progress.setProxyProgress)
                    self.feedback_dialog = self.createProgressDialog()
                    self.feedback_dialog.show()
                    if self.in_place:
                        ok, results = execute_in_place(self.algorithm(),
                                                       parameters,
                                                       self.context,
                                                       self.feedback)
                    else:
                        ok, results = execute(self.algorithm(), parameters,
                                              self.context, self.feedback)
                    self.feedback.progressChanged.disconnect()
                    self.proxy_progress.finalize(ok)
                    on_complete(ok, results)

        except AlgorithmDialogBase.InvalidParameterValue as e:
            self.flag_invalid_parameter_value(e.parameter.description(),
                                              e.widget)
        except AlgorithmDialogBase.InvalidOutputExtension as e:
            self.flag_invalid_output_extension(e.message, e.widget)