From 26cd6017b8aeb016663f471b84127de35cc3f669 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Mon, 3 Jul 2017 15:12:36 +1000 Subject: [PATCH] Use an expression context when evaluating child parameters with expression sources --- python/plugins/processing/tools/dataobjects.py | 2 ++ .../processing/qgsprocessingmodelalgorithm.cpp | 11 ++++++++--- src/core/processing/qgsprocessingmodelalgorithm.h | 2 +- tests/src/core/testqgsprocessing.cpp | 14 +++++++++----- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/python/plugins/processing/tools/dataobjects.py b/python/plugins/processing/tools/dataobjects.py index 2656f01cf6a..311755e85cc 100644 --- a/python/plugins/processing/tools/dataobjects.py +++ b/python/plugins/processing/tools/dataobjects.py @@ -81,6 +81,8 @@ def createContext(feedback=None): settings = QgsSettings() context.setDefaultEncoding(settings.value("/Processing/encoding", "System")) + context.setExpressionContext(createExpressionContext()) + return context diff --git a/src/core/processing/qgsprocessingmodelalgorithm.cpp b/src/core/processing/qgsprocessingmodelalgorithm.cpp index 4d38a54cbed..4fea0213d19 100644 --- a/src/core/processing/qgsprocessingmodelalgorithm.cpp +++ b/src/core/processing/qgsprocessingmodelalgorithm.cpp @@ -351,7 +351,7 @@ QString QgsProcessingModelAlgorithm::helpUrl() const return QgsProcessingUtils::formatHelpMapAsHtml( mHelpContent, this ); } -QVariantMap QgsProcessingModelAlgorithm::parametersForChildAlgorithm( const ChildAlgorithm &child, const QVariantMap &modelParameters, const QMap< QString, QVariantMap > &results ) const +QVariantMap QgsProcessingModelAlgorithm::parametersForChildAlgorithm( const ChildAlgorithm &child, const QVariantMap &modelParameters, const QMap< QString, QVariantMap > &results, const QgsExpressionContext &expressionContext ) const { QVariantMap childParams; Q_FOREACH ( const QgsProcessingParameterDefinition *def, child.algorithm()->parameterDefinitions() ) @@ -389,7 +389,7 @@ QVariantMap QgsProcessingModelAlgorithm::parametersForChildAlgorithm( const Chil case ChildParameterSource::Expression: { QgsExpression exp( source.expression() ); - paramParts << exp.evaluate(); + paramParts << exp.evaluate( &expressionContext ); break; } } @@ -492,6 +492,8 @@ QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap &pa QTime totalTime; totalTime.start(); + QgsExpressionContext baseContext = createExpressionContext( parameters, context ); + QMap< QString, QVariantMap > childResults; QVariantMap finalResults; QSet< QString > executed; @@ -522,7 +524,10 @@ QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap &pa const ChildAlgorithm &child = mChildAlgorithms[ childId ]; - QVariantMap childParams = parametersForChildAlgorithm( child, parameters, childResults ); + QgsExpressionContext expContext = baseContext; + expContext << QgsExpressionContextUtils::processingAlgorithmScope( child.algorithm(), parameters, context ); + + QVariantMap childParams = parametersForChildAlgorithm( child, parameters, childResults, expContext ); feedback->setProgressText( QObject::tr( "Running %1 [%2/%3]" ).arg( child.description() ).arg( executed.count() + 1 ).arg( toExecute.count() ) ); //feedback->pushDebugInfo( "Parameters: " + ', '.join( [str( p ).strip() + // '=' + str( p.value ) for p in alg.algorithm.parameters] ) ) diff --git a/src/core/processing/qgsprocessingmodelalgorithm.h b/src/core/processing/qgsprocessingmodelalgorithm.h index d55ea780a24..db4581ba867 100644 --- a/src/core/processing/qgsprocessingmodelalgorithm.h +++ b/src/core/processing/qgsprocessingmodelalgorithm.h @@ -879,7 +879,7 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm void dependsOnChildAlgorithmsRecursive( const QString &childId, QSet &depends ) const; void dependentChildAlgorithmsRecursive( const QString &childId, QSet &depends ) const; - QVariantMap parametersForChildAlgorithm( const ChildAlgorithm &child, const QVariantMap &modelParameters, const QMap &results ) const; + QVariantMap parametersForChildAlgorithm( const ChildAlgorithm &child, const QVariantMap &modelParameters, const QMap &results, const QgsExpressionContext &expressionContext ) const; /** * Returns true if an output from a child algorithm is required elsewhere in diff --git a/tests/src/core/testqgsprocessing.cpp b/tests/src/core/testqgsprocessing.cpp index 8e33599f69d..6cf0b3d18b9 100644 --- a/tests/src/core/testqgsprocessing.cpp +++ b/tests/src/core/testqgsprocessing.cpp @@ -4761,11 +4761,15 @@ void TestQgsProcessing::modelExecution() model2.addModelParameter( new QgsProcessingParameterFeatureSource( "SOURCE_LAYER" ), QgsProcessingModelAlgorithm::ModelParameter( "SOURCE_LAYER" ) ); model2.addModelParameter( new QgsProcessingParameterNumber( "DIST", QString(), QgsProcessingParameterNumber::Double ), QgsProcessingModelAlgorithm::ModelParameter( "DIST" ) ); QgsProcessingModelAlgorithm::ChildAlgorithm alg2c1; + QgsExpressionContext expContext; + QgsExpressionContextScope *scope = new QgsExpressionContextScope(); + scope->setVariable( "myvar", 8 ); + expContext.appendScope( scope ); alg2c1.setChildId( "cx1" ); alg2c1.setAlgorithmId( "native:buffer" ); alg2c1.addParameterSources( "INPUT", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromModelParameter( "SOURCE_LAYER" ) ); alg2c1.addParameterSources( "DISTANCE", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromModelParameter( "DIST" ) ); - alg2c1.addParameterSources( "SEGMENTS", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromExpression( QStringLiteral( "8*2" ) ) ); + alg2c1.addParameterSources( "SEGMENTS", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromExpression( QStringLiteral( "@myvar*2" ) ) ); alg2c1.addParameterSources( "END_CAP_STYLE", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromStaticValue( 1 ) ); alg2c1.addParameterSources( "JOIN_STYLE", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromStaticValue( 2 ) ); alg2c1.addParameterSources( "DISSOLVE", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromStaticValue( false ) ); @@ -4784,7 +4788,7 @@ void TestQgsProcessing::modelExecution() layerDef.destinationName = "my_dest"; modelInputs.insert( "cx3:MY_OUT", QVariant::fromValue( layerDef ) ); QMap childResults; - QVariantMap params = model2.parametersForChildAlgorithm( model2.childAlgorithm( "cx1" ), modelInputs, childResults ); + QVariantMap params = model2.parametersForChildAlgorithm( model2.childAlgorithm( "cx1" ), modelInputs, childResults, expContext ); QCOMPARE( params.value( "DISSOLVE" ).toBool(), false ); QCOMPARE( params.value( "DISTANCE" ).toInt(), 271 ); QCOMPARE( params.value( "SEGMENTS" ).toInt(), 16 ); @@ -4804,7 +4808,7 @@ void TestQgsProcessing::modelExecution() alg2c2.setAlgorithmId( "native:centroids" ); alg2c2.addParameterSources( "INPUT", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromChildOutput( "cx1", "OUTPUT" ) ); model2.addChildAlgorithm( alg2c2 ); - params = model2.parametersForChildAlgorithm( model2.childAlgorithm( "cx2" ), modelInputs, childResults ); + params = model2.parametersForChildAlgorithm( model2.childAlgorithm( "cx2" ), modelInputs, childResults, expContext ); QCOMPARE( params.value( "INPUT" ).toString(), QStringLiteral( "dest.shp" ) ); QCOMPARE( params.value( "OUTPUT" ).toString(), QStringLiteral( "memory:" ) ); QCOMPARE( params.count(), 2 ); @@ -4824,7 +4828,7 @@ void TestQgsProcessing::modelExecution() alg2c3.setModelOutputs( outputs3 ); model2.addChildAlgorithm( alg2c3 ); - params = model2.parametersForChildAlgorithm( model2.childAlgorithm( "cx3" ), modelInputs, childResults ); + params = model2.parametersForChildAlgorithm( model2.childAlgorithm( "cx3" ), modelInputs, childResults, expContext ); QCOMPARE( params.value( "INPUT" ).toString(), QStringLiteral( "dest.shp" ) ); QCOMPARE( params.value( "EXPRESSION" ).toString(), QStringLiteral( "true" ) ); QVERIFY( params.value( "OUTPUT" ).canConvert() ); @@ -4840,7 +4844,7 @@ void TestQgsProcessing::modelExecution() "##model_out_layer=output outputVector\n" "##my_out=output outputVector\n" "results={}\n" - "outputs['cx1']=processing.run('native:buffer', {'DISSOLVE':false,'DISTANCE':parameters['DIST'],'END_CAP_STYLE':1,'INPUT':parameters['SOURCE_LAYER'],'JOIN_STYLE':2,'SEGMENTS':QgsExpression('8*2').evaluate()}, context=context, feedback=feedback)\n" + "outputs['cx1']=processing.run('native:buffer', {'DISSOLVE':false,'DISTANCE':parameters['DIST'],'END_CAP_STYLE':1,'INPUT':parameters['SOURCE_LAYER'],'JOIN_STYLE':2,'SEGMENTS':QgsExpression('@myvar*2').evaluate()}, context=context, feedback=feedback)\n" "results['MODEL_OUT_LAYER']=outputs['cx1']['OUTPUT']\n" "outputs['cx2']=processing.run('native:centroids', {'INPUT':outputs['cx1']['OUTPUT']}, context=context, feedback=feedback)\n" "outputs['cx3']=processing.run('native:extractbyexpression', {'EXPRESSION':true,'INPUT':outputs['cx1']['OUTPUT'],'OUTPUT':parameters['MY_OUT']}, context=context, feedback=feedback)\n"