Skip to content

Commit

Permalink
Report success or failure after running algs
Browse files Browse the repository at this point in the history
And auto catch python exceptions and report failure of model
  • Loading branch information
nyalldawson committed Jun 23, 2017
1 parent a4f23fd commit 93b7c28
Show file tree
Hide file tree
Showing 9 changed files with 51 additions and 20 deletions.
4 changes: 3 additions & 1 deletion python/core/processing/qgsprocessingalgorithm.sip
Expand Up @@ -215,14 +215,16 @@ class QgsProcessingAlgorithm
%End

QVariantMap run( const QVariantMap &parameters,
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const;
QgsProcessingContext &context, QgsProcessingFeedback *feedback, bool *ok /Out/ = 0 ) const;
%Docstring
Executes the algorithm using the specified ``parameters``.

The ``context`` argument specifies the context in which the algorithm is being run.

Algorithm progress should be reported using the supplied ``feedback`` object.

If specified, ``ok`` will be set to true if algorithm was successfully run.

:return: A map of algorithm outputs. These may be output layer references, or calculated
values such as statistical calculations.
:rtype: QVariantMap
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/core/GeoAlgorithm.py
Expand Up @@ -335,7 +335,7 @@ def executeAlgorithm(alg, parameters, context=None, feedback=None, model=None):
#self.resolveOutputs()
#self.evaluateParameterValues()
#self.runPreExecutionScript(feedback)
result = alg.run(parameters, context, feedback)
result, ok = alg.run(parameters, context, feedback)
#self.processAlgorithm(parameters, context, feedback)
feedback.setProgress(100)
return result
Expand Down
4 changes: 2 additions & 2 deletions python/plugins/processing/gui/AlgorithmExecutor.py
Expand Up @@ -59,8 +59,8 @@ def execute(alg, parameters, context=None, feedback=None):
context = dataobjects.createContext()

try:
results = alg.run(parameters, context, feedback)
return True, results
results, ok = alg.run(parameters, context, feedback)
return ok, results
except GeoAlgorithmExecutionException as e:
QgsMessageLog.logMessage(str(sys.exc_info()[0]), 'Processing', QgsMessageLog.CRITICAL)
if feedback is not None:
Expand Down
9 changes: 5 additions & 4 deletions python/plugins/processing/tests/AlgorithmsTestBase.py
Expand Up @@ -128,14 +128,15 @@ def check_algorithm(self, name, defs):

if expectFailure:
try:
results = alg.run(parameters, context, feedback)
results, ok = alg.run(parameters, context, feedback)
self.check_results(results, context, defs['params'], defs['results'])
if ok:
raise _UnexpectedSuccess
except Exception:
pass
else:
raise _UnexpectedSuccess
else:
results = alg.run(parameters, context, feedback)
results, ok = alg.run(parameters, context, feedback)
self.assertTrue(ok)
self.check_results(results, context, defs['params'], defs['results'])

def load_params(self, params):
Expand Down
22 changes: 20 additions & 2 deletions src/core/processing/qgsprocessingalgorithm.cpp
Expand Up @@ -23,6 +23,9 @@
#include "qgsrectangle.h"
#include "qgsprocessingcontext.h"
#include "qgsprocessingutils.h"
#include "qgsprocessingexception.h"
#include "qgsmessagelog.h"
#include "qgsprocessingfeedback.h"

QgsProcessingAlgorithm::~QgsProcessingAlgorithm()
{
Expand Down Expand Up @@ -311,9 +314,24 @@ bool QgsProcessingAlgorithm::hasHtmlOutputs() const
return false;
}

QVariantMap QgsProcessingAlgorithm::run( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const
QVariantMap QgsProcessingAlgorithm::run( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback, bool *ok ) const
{
return processAlgorithm( parameters, context, feedback );
if ( ok )
*ok = false;

QVariantMap results;
try
{
results = processAlgorithm( parameters, context, feedback );
if ( ok )
*ok = true;
}
catch ( QgsProcessingException &e )
{
QgsMessageLog::logMessage( e.what(), QObject::tr( "Processing" ), QgsMessageLog::CRITICAL );
feedback->reportError( e.what() );
}
return results;
}

QString QgsProcessingAlgorithm::parameterAsString( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
Expand Down
4 changes: 3 additions & 1 deletion src/core/processing/qgsprocessingalgorithm.h
Expand Up @@ -223,11 +223,13 @@ class CORE_EXPORT QgsProcessingAlgorithm
*
* Algorithm progress should be reported using the supplied \a feedback object.
*
* If specified, \a ok will be set to true if algorithm was successfully run.
*
* \returns A map of algorithm outputs. These may be output layer references, or calculated
* values such as statistical calculations.
*/
QVariantMap run( const QVariantMap &parameters,
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const;
QgsProcessingContext &context, QgsProcessingFeedback *feedback, bool *ok SIP_OUT = nullptr ) const;

/**
* If an algorithm subclass implements a custom parameters widget, a copy of this widget
Expand Down
5 changes: 3 additions & 2 deletions src/core/processing/qgsprocessingalgrunnertask.cpp
Expand Up @@ -39,8 +39,9 @@ void QgsProcessingAlgRunnerTask::cancel()
bool QgsProcessingAlgRunnerTask::run()
{
connect( mFeedback.get(), &QgsFeedback::progressChanged, this, &QgsProcessingAlgRunnerTask::setProgress );
mResults = mAlgorithm->run( mParameters, mContext, mFeedback.get() );
return !mFeedback->isCanceled();
bool ok = false;
mResults = mAlgorithm->run( mParameters, mContext, mFeedback.get(), &ok );
return ok && !mFeedback->isCanceled();
}

void QgsProcessingAlgRunnerTask::finished( bool result )
Expand Down
5 changes: 5 additions & 0 deletions src/core/processing/qgsprocessingexception.h
Expand Up @@ -25,10 +25,15 @@
* \class QgsProcessingException
* \ingroup core
* Custom exception class for processing related exceptions.
* \since QGIS 3.0
*/
class CORE_EXPORT QgsProcessingException : public QgsException
{
public:

/**
* Constructor for QgsProcessingException.
*/
QgsProcessingException( const QString &what ) : QgsException( what ) {}

};
Expand Down
16 changes: 9 additions & 7 deletions src/core/processing/qgsprocessingmodelalgorithm.cpp
Expand Up @@ -19,6 +19,7 @@
#include "qgsprocessingregistry.h"
#include "qgsprocessingfeedback.h"
#include "qgsxmlutils.h"
#include "qgsprocessingexception.h"
#include <QFile>
#include <QTextStream>

Expand Down Expand Up @@ -437,7 +438,14 @@ QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap &pa
QTime childTime;
childTime.start();

QVariantMap results = child.algorithm()->run( childParams, context, feedback );
bool ok = false;
QVariantMap results = child.algorithm()->run( childParams, context, feedback, &ok );
if ( !ok )
{
QString error = QObject::tr( "Error encountered while running %1" ).arg( child.description() );
feedback->reportError( error );
throw QgsProcessingException( error );
}
childResults.insert( childId, results );

// look through child alg's outputs to determine whether any of these should be copied
Expand All @@ -451,12 +459,6 @@ QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap &pa

executed.insert( childId );
feedback->pushDebugInfo( QObject::tr( "OK. Execution took %1 s (%2 outputs)." ).arg( childTime.elapsed() / 1000.0 ).arg( results.count() ) );
#if 0
except GeoAlgorithmExecutionException as e:
feedback.pushDebugInfo( self.tr( 'Failed', 'ModelerAlgorithm' ) )
raise GeoAlgorithmExecutionException(
self.tr( 'Error executing algorithm {0}\n{1}', 'ModelerAlgorithm' ).format( alg.description, e.msg ) )
#endif
}
}
feedback->pushDebugInfo( QObject::tr( "Model processed ok. Executed %1 algorithms total in %2 s." ).arg( executed.count() ).arg( totalTime.elapsed() / 1000.0 ) );
Expand Down

0 comments on commit 93b7c28

Please sign in to comment.