Use an expression context when evaluating child parameters with expression sources

This commit is contained in:
Nyall Dawson 2017-07-03 15:12:36 +10:00
parent 3243a1a34c
commit 26cd6017b8
4 changed files with 20 additions and 9 deletions

View File

@ -81,6 +81,8 @@ def createContext(feedback=None):
settings = QgsSettings() settings = QgsSettings()
context.setDefaultEncoding(settings.value("/Processing/encoding", "System")) context.setDefaultEncoding(settings.value("/Processing/encoding", "System"))
context.setExpressionContext(createExpressionContext())
return context return context

View File

@ -351,7 +351,7 @@ QString QgsProcessingModelAlgorithm::helpUrl() const
return QgsProcessingUtils::formatHelpMapAsHtml( mHelpContent, this ); 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; QVariantMap childParams;
Q_FOREACH ( const QgsProcessingParameterDefinition *def, child.algorithm()->parameterDefinitions() ) Q_FOREACH ( const QgsProcessingParameterDefinition *def, child.algorithm()->parameterDefinitions() )
@ -389,7 +389,7 @@ QVariantMap QgsProcessingModelAlgorithm::parametersForChildAlgorithm( const Chil
case ChildParameterSource::Expression: case ChildParameterSource::Expression:
{ {
QgsExpression exp( source.expression() ); QgsExpression exp( source.expression() );
paramParts << exp.evaluate(); paramParts << exp.evaluate( &expressionContext );
break; break;
} }
} }
@ -492,6 +492,8 @@ QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap &pa
QTime totalTime; QTime totalTime;
totalTime.start(); totalTime.start();
QgsExpressionContext baseContext = createExpressionContext( parameters, context );
QMap< QString, QVariantMap > childResults; QMap< QString, QVariantMap > childResults;
QVariantMap finalResults; QVariantMap finalResults;
QSet< QString > executed; QSet< QString > executed;
@ -522,7 +524,10 @@ QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap &pa
const ChildAlgorithm &child = mChildAlgorithms[ childId ]; 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->setProgressText( QObject::tr( "Running %1 [%2/%3]" ).arg( child.description() ).arg( executed.count() + 1 ).arg( toExecute.count() ) );
//feedback->pushDebugInfo( "Parameters: " + ', '.join( [str( p ).strip() + //feedback->pushDebugInfo( "Parameters: " + ', '.join( [str( p ).strip() +
// '=' + str( p.value ) for p in alg.algorithm.parameters] ) ) // '=' + str( p.value ) for p in alg.algorithm.parameters] ) )

View File

@ -879,7 +879,7 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
void dependsOnChildAlgorithmsRecursive( const QString &childId, QSet<QString> &depends ) const; void dependsOnChildAlgorithmsRecursive( const QString &childId, QSet<QString> &depends ) const;
void dependentChildAlgorithmsRecursive( const QString &childId, QSet<QString> &depends ) const; void dependentChildAlgorithmsRecursive( const QString &childId, QSet<QString> &depends ) const;
QVariantMap parametersForChildAlgorithm( const ChildAlgorithm &child, const QVariantMap &modelParameters, const QMap<QString, QVariantMap> &results ) const; QVariantMap parametersForChildAlgorithm( const ChildAlgorithm &child, const QVariantMap &modelParameters, const QMap<QString, QVariantMap> &results, const QgsExpressionContext &expressionContext ) const;
/** /**
* Returns true if an output from a child algorithm is required elsewhere in * Returns true if an output from a child algorithm is required elsewhere in

View File

@ -4761,11 +4761,15 @@ void TestQgsProcessing::modelExecution()
model2.addModelParameter( new QgsProcessingParameterFeatureSource( "SOURCE_LAYER" ), QgsProcessingModelAlgorithm::ModelParameter( "SOURCE_LAYER" ) ); model2.addModelParameter( new QgsProcessingParameterFeatureSource( "SOURCE_LAYER" ), QgsProcessingModelAlgorithm::ModelParameter( "SOURCE_LAYER" ) );
model2.addModelParameter( new QgsProcessingParameterNumber( "DIST", QString(), QgsProcessingParameterNumber::Double ), QgsProcessingModelAlgorithm::ModelParameter( "DIST" ) ); model2.addModelParameter( new QgsProcessingParameterNumber( "DIST", QString(), QgsProcessingParameterNumber::Double ), QgsProcessingModelAlgorithm::ModelParameter( "DIST" ) );
QgsProcessingModelAlgorithm::ChildAlgorithm alg2c1; QgsProcessingModelAlgorithm::ChildAlgorithm alg2c1;
QgsExpressionContext expContext;
QgsExpressionContextScope *scope = new QgsExpressionContextScope();
scope->setVariable( "myvar", 8 );
expContext.appendScope( scope );
alg2c1.setChildId( "cx1" ); alg2c1.setChildId( "cx1" );
alg2c1.setAlgorithmId( "native:buffer" ); alg2c1.setAlgorithmId( "native:buffer" );
alg2c1.addParameterSources( "INPUT", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromModelParameter( "SOURCE_LAYER" ) ); alg2c1.addParameterSources( "INPUT", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromModelParameter( "SOURCE_LAYER" ) );
alg2c1.addParameterSources( "DISTANCE", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromModelParameter( "DIST" ) ); 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( "END_CAP_STYLE", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromStaticValue( 1 ) );
alg2c1.addParameterSources( "JOIN_STYLE", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromStaticValue( 2 ) ); alg2c1.addParameterSources( "JOIN_STYLE", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromStaticValue( 2 ) );
alg2c1.addParameterSources( "DISSOLVE", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromStaticValue( false ) ); alg2c1.addParameterSources( "DISSOLVE", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromStaticValue( false ) );
@ -4784,7 +4788,7 @@ void TestQgsProcessing::modelExecution()
layerDef.destinationName = "my_dest"; layerDef.destinationName = "my_dest";
modelInputs.insert( "cx3:MY_OUT", QVariant::fromValue( layerDef ) ); modelInputs.insert( "cx3:MY_OUT", QVariant::fromValue( layerDef ) );
QMap<QString, QVariantMap> childResults; QMap<QString, QVariantMap> 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( "DISSOLVE" ).toBool(), false );
QCOMPARE( params.value( "DISTANCE" ).toInt(), 271 ); QCOMPARE( params.value( "DISTANCE" ).toInt(), 271 );
QCOMPARE( params.value( "SEGMENTS" ).toInt(), 16 ); QCOMPARE( params.value( "SEGMENTS" ).toInt(), 16 );
@ -4804,7 +4808,7 @@ void TestQgsProcessing::modelExecution()
alg2c2.setAlgorithmId( "native:centroids" ); alg2c2.setAlgorithmId( "native:centroids" );
alg2c2.addParameterSources( "INPUT", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromChildOutput( "cx1", "OUTPUT" ) ); alg2c2.addParameterSources( "INPUT", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromChildOutput( "cx1", "OUTPUT" ) );
model2.addChildAlgorithm( alg2c2 ); 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( "INPUT" ).toString(), QStringLiteral( "dest.shp" ) );
QCOMPARE( params.value( "OUTPUT" ).toString(), QStringLiteral( "memory:" ) ); QCOMPARE( params.value( "OUTPUT" ).toString(), QStringLiteral( "memory:" ) );
QCOMPARE( params.count(), 2 ); QCOMPARE( params.count(), 2 );
@ -4824,7 +4828,7 @@ void TestQgsProcessing::modelExecution()
alg2c3.setModelOutputs( outputs3 ); alg2c3.setModelOutputs( outputs3 );
model2.addChildAlgorithm( alg2c3 ); 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( "INPUT" ).toString(), QStringLiteral( "dest.shp" ) );
QCOMPARE( params.value( "EXPRESSION" ).toString(), QStringLiteral( "true" ) ); QCOMPARE( params.value( "EXPRESSION" ).toString(), QStringLiteral( "true" ) );
QVERIFY( params.value( "OUTPUT" ).canConvert<QgsProcessingOutputLayerDefinition>() ); QVERIFY( params.value( "OUTPUT" ).canConvert<QgsProcessingOutputLayerDefinition>() );
@ -4840,7 +4844,7 @@ void TestQgsProcessing::modelExecution()
"##model_out_layer=output outputVector\n" "##model_out_layer=output outputVector\n"
"##my_out=output outputVector\n" "##my_out=output outputVector\n"
"results={}\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" "results['MODEL_OUT_LAYER']=outputs['cx1']['OUTPUT']\n"
"outputs['cx2']=processing.run('native:centroids', {'INPUT':outputs['cx1']['OUTPUT']}, context=context, feedback=feedback)\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" "outputs['cx3']=processing.run('native:extractbyexpression', {'EXPRESSION':true,'INPUT':outputs['cx1']['OUTPUT'],'OUTPUT':parameters['MY_OUT']}, context=context, feedback=feedback)\n"