Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Update QgsProcessingModelChildAlgorithm::asPythonCode for 3.x API
  • Loading branch information
nyalldawson committed Feb 1, 2019
1 parent 946687c commit fb519ea
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 18 deletions.
Expand Up @@ -298,9 +298,15 @@ Loads this child from a QVariant.
.. seealso:: :py:func:`toVariant`
%End

QString asPythonCode() const;
QStringList asPythonCode( QgsProcessing::PythonOutputType outputType, const QgsStringMap &extraParameters, int currentIndent, int indentSize ) const;
%Docstring
Attempts to convert the child to executable Python code.
Attempts to convert the child to executable Python code, and returns a list of the generated lines of code.

The ``outputType`` argument specifies the type of script to generate.

Additional parameters to be passed to the child algorithm are specified in the ``extraParameters`` argument.

The ``currentIndent`` and ``indentSize`` are used to set the base line indent and size of further indented lines respectively.
%End

};
Expand Down
42 changes: 28 additions & 14 deletions src/core/processing/models/qgsprocessingmodelchildalgorithm.cpp
Expand Up @@ -162,39 +162,53 @@ bool QgsProcessingModelChildAlgorithm::loadVariant( const QVariant &child )
return true;
}

QString QgsProcessingModelChildAlgorithm::asPythonCode() const
QStringList QgsProcessingModelChildAlgorithm::asPythonCode( const QgsProcessing::PythonOutputType outputType, const QgsStringMap &extraParameters, int currentIndent, int indentSize ) const
{
QStringList lines;
const QString baseIndent = QString( ' ' ).repeated( currentIndent );
const QString lineIndent = QString( ' ' ).repeated( indentSize );

if ( !algorithm() )
return QString();
return QStringList();

QStringList paramParts;
QMap< QString, QgsProcessingModelChildParameterSources >::const_iterator paramIt = mParams.constBegin();
for ( ; paramIt != mParams.constEnd(); ++paramIt )
for ( auto paramIt = mParams.constBegin(); paramIt != mParams.constEnd(); ++paramIt )
{
QStringList sourceParts;
Q_FOREACH ( const QgsProcessingModelChildParameterSource &source, paramIt.value() )
const QgsProcessingParameterDefinition *def = algorithm() ? algorithm()->parameterDefinition( paramIt.key() ) : nullptr;
const auto parts = paramIt.value();
for ( const QgsProcessingModelChildParameterSource &source : parts )
{
QString part = source.asPythonCode();
QString part = source.asPythonCode( outputType, def );
if ( !part.isEmpty() )
sourceParts << QStringLiteral( "'%1':%2" ).arg( paramIt.key(), part );
sourceParts << part;
}
if ( sourceParts.count() == 1 )
paramParts << sourceParts.at( 0 );
paramParts << QStringLiteral( "'%1':%2" ).arg( paramIt.key(), sourceParts.at( 0 ) );
else
paramParts << QStringLiteral( "[%1]" ).arg( paramParts.join( ',' ) );
paramParts << QStringLiteral( "'%1':[%2]" ).arg( paramIt.key(), sourceParts.join( ',' ) );
}

lines << baseIndent + QStringLiteral( "alg_params = {" );
lines.reserve( lines.size() + paramParts.size() );
for ( const QString &p : qgis::as_const( paramParts ) )
{
lines << baseIndent + lineIndent + p + ',';
}
for ( auto it = extraParameters.constBegin(); it != extraParameters.constEnd(); ++it )
{
lines << baseIndent + lineIndent + QgsProcessingUtils::stringToPythonLiteral( it.key() ) + ':' + it.value() + ',';
}
lines << baseIndent + QStringLiteral( "}" );

lines << QStringLiteral( "outputs['%1']=processing.run('%2', {%3}, context=context, feedback=feedback)" ).arg( mId, mAlgorithmId, paramParts.join( ',' ) );
lines << baseIndent + QStringLiteral( "outputs['%1']=processing.run('%2', alg_params, context=context, feedback=feedback, is_child_algorithm=True)" ).arg( mId, mAlgorithmId );

QMap< QString, QgsProcessingModelOutput >::const_iterator outputIt = mModelOutputs.constBegin();
for ( ; outputIt != mModelOutputs.constEnd(); ++outputIt )
for ( auto outputIt = mModelOutputs.constBegin(); outputIt != mModelOutputs.constEnd(); ++outputIt )
{
lines << QStringLiteral( "results['%1']=outputs['%2']['%3']" ).arg( outputIt.key(), mId, outputIt.value().childOutputName() );
lines << baseIndent + QStringLiteral( "results['%1:%2']=outputs['%1']['%3']" ).arg( mId, outputIt.key(), outputIt.value().childOutputName() );
}

return lines.join( '\n' );
return lines;
}

QVariantMap QgsProcessingModelChildAlgorithm::configuration() const
Expand Down
10 changes: 8 additions & 2 deletions src/core/processing/models/qgsprocessingmodelchildalgorithm.h
Expand Up @@ -278,9 +278,15 @@ class CORE_EXPORT QgsProcessingModelChildAlgorithm : public QgsProcessingModelCo
bool loadVariant( const QVariant &child );

/**
* Attempts to convert the child to executable Python code.
* Attempts to convert the child to executable Python code, and returns a list of the generated lines of code.
*
* The \a outputType argument specifies the type of script to generate.
*
* Additional parameters to be passed to the child algorithm are specified in the \a extraParameters argument.
*
* The \a currentIndent and \a indentSize are used to set the base line indent and size of further indented lines respectively.
*/
QString asPythonCode() const;
QStringList asPythonCode( QgsProcessing::PythonOutputType outputType, const QgsStringMap &extraParameters, int currentIndent, int indentSize ) const;

private:

Expand Down
9 changes: 9 additions & 0 deletions tests/src/analysis/testqgsprocessing.cpp
Expand Up @@ -6152,6 +6152,11 @@ void TestQgsProcessing::modelerAlgorithm()
QVERIFY( child.setAlgorithmId( QStringLiteral( "native:centroids" ) ) );
QVERIFY( child.algorithm() );
QCOMPARE( child.algorithm()->id(), QStringLiteral( "native:centroids" ) );
QCOMPARE( child.asPythonCode( QgsProcessing::PythonQgsProcessingAlgorithmSubclass, QgsStringMap(), 4, 2 ).join( '\n' ), QStringLiteral( " alg_params = {\n }\n outputs['']=processing.run('native:centroids', alg_params, context=context, feedback=feedback, is_child_algorithm=True)" ) );
QgsStringMap extraParams;
extraParams[QStringLiteral( "SOMETHING" )] = QStringLiteral( "SOMETHING_ELSE" );
extraParams[QStringLiteral( "SOMETHING2" )] = QStringLiteral( "SOMETHING_ELSE2" );
QCOMPARE( child.asPythonCode( QgsProcessing::PythonQgsProcessingAlgorithmSubclass, extraParams, 4, 2 ).join( '\n' ), QStringLiteral( " alg_params = {\n 'SOMETHING':SOMETHING_ELSE,\n 'SOMETHING2':SOMETHING_ELSE2,\n }\n outputs['']=processing.run('native:centroids', alg_params, context=context, feedback=feedback, is_child_algorithm=True)" ) );
// bit of a hack -- but try to simulate an algorithm not originally available!
child.mAlgorithm.reset();
QVERIFY( !child.algorithm() );
Expand Down Expand Up @@ -6194,6 +6199,8 @@ void TestQgsProcessing::modelerAlgorithm()
QCOMPARE( child.parameterSources().value( QStringLiteral( "b" ) ).at( 0 ).staticValue().toInt(), 7 );
QCOMPARE( child.parameterSources().value( QStringLiteral( "b" ) ).at( 1 ).staticValue().toInt(), 9 );

QCOMPARE( child.asPythonCode( QgsProcessing::PythonQgsProcessingAlgorithmSubclass, extraParams, 4, 2 ).join( '\n' ), QStringLiteral( " alg_params = {\n 'a':5,\n 'b':[7,9],\n 'SOMETHING':SOMETHING_ELSE,\n 'SOMETHING2':SOMETHING_ELSE2,\n }\n outputs['my_id']=processing.run('native:centroids', alg_params, context=context, feedback=feedback, is_child_algorithm=True)" ) );

QgsProcessingModelOutput testModelOut;
testModelOut.setChildId( QStringLiteral( "my_id" ) );
QCOMPARE( testModelOut.childId(), QStringLiteral( "my_id" ) );
Expand Down Expand Up @@ -6228,6 +6235,8 @@ void TestQgsProcessing::modelerAlgorithm()
QCOMPARE( child.modelOutput( "a" ).description(), QStringLiteral( "my output" ) );
child.modelOutput( "a" ).setDescription( QStringLiteral( "my output 2" ) );
QCOMPARE( child.modelOutput( "a" ).description(), QStringLiteral( "my output 2" ) );
QCOMPARE( child.asPythonCode( QgsProcessing::PythonQgsProcessingAlgorithmSubclass, extraParams, 4, 2 ).join( '\n' ), QStringLiteral( " alg_params = {\n 'a':5,\n 'b':[7,9],\n 'SOMETHING':SOMETHING_ELSE,\n 'SOMETHING2':SOMETHING_ELSE2,\n }\n outputs['my_id']=processing.run('native:centroids', alg_params, context=context, feedback=feedback, is_child_algorithm=True)\n results['my_id:a']=outputs['my_id']['']" ) );

// no existent
child.modelOutput( "b" ).setDescription( QStringLiteral( "my output 3" ) );
QCOMPARE( child.modelOutput( "b" ).description(), QStringLiteral( "my output 3" ) );
Expand Down

0 comments on commit fb519ea

Please sign in to comment.