Update QgsProcessingModelChildAlgorithm::asPythonCode for 3.x API

This commit is contained in:
Nyall Dawson 2019-02-01 11:28:57 +10:00
parent 946687c87b
commit fb519ead46
4 changed files with 54 additions and 19 deletions

View File

@ -298,9 +298,15 @@ Loads this child from a QVariant.
.. seealso:: :py:func:`toVariant` .. seealso:: :py:func:`toVariant`
%End %End
QString asPythonCode() const; QStringList asPythonCode( QgsProcessing::PythonOutputType outputType, const QgsStringMap &extraParameters, int currentIndent, int indentSize ) const;
%Docstring %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 %End
}; };

View File

@ -162,39 +162,53 @@ bool QgsProcessingModelChildAlgorithm::loadVariant( const QVariant &child )
return true; return true;
} }
QString QgsProcessingModelChildAlgorithm::asPythonCode() const QStringList QgsProcessingModelChildAlgorithm::asPythonCode( const QgsProcessing::PythonOutputType outputType, const QgsStringMap &extraParameters, int currentIndent, int indentSize ) const
{ {
QStringList lines; QStringList lines;
const QString baseIndent = QString( ' ' ).repeated( currentIndent );
const QString lineIndent = QString( ' ' ).repeated( indentSize );
if ( !algorithm() ) if ( !algorithm() )
return QString(); return QStringList();
QStringList paramParts; QStringList paramParts;
QMap< QString, QgsProcessingModelChildParameterSources >::const_iterator paramIt = mParams.constBegin(); for ( auto paramIt = mParams.constBegin(); paramIt != mParams.constEnd(); ++paramIt )
for ( ; paramIt != mParams.constEnd(); ++paramIt )
{ {
QStringList sourceParts; 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() ) if ( !part.isEmpty() )
sourceParts << QStringLiteral( "'%1':%2" ).arg( paramIt.key(), part ); sourceParts << part;
} }
if ( sourceParts.count() == 1 ) if ( sourceParts.count() == 1 )
paramParts << sourceParts.at( 0 ); paramParts << QStringLiteral( "'%1':%2" ).arg( paramIt.key(), sourceParts.at( 0 ) );
else else
paramParts << QStringLiteral( "[%1]" ).arg( paramParts.join( ',' ) ); paramParts << QStringLiteral( "'%1':[%2]" ).arg( paramIt.key(), sourceParts.join( ',' ) );
} }
lines << QStringLiteral( "outputs['%1']=processing.run('%2', {%3}, context=context, feedback=feedback)" ).arg( mId, mAlgorithmId, paramParts.join( ',' ) ); lines << baseIndent + QStringLiteral( "alg_params = {" );
lines.reserve( lines.size() + paramParts.size() );
QMap< QString, QgsProcessingModelOutput >::const_iterator outputIt = mModelOutputs.constBegin(); for ( const QString &p : qgis::as_const( paramParts ) )
for ( ; outputIt != mModelOutputs.constEnd(); ++outputIt )
{ {
lines << QStringLiteral( "results['%1']=outputs['%2']['%3']" ).arg( outputIt.key(), mId, outputIt.value().childOutputName() ); 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 << baseIndent + QStringLiteral( "outputs['%1']=processing.run('%2', alg_params, context=context, feedback=feedback, is_child_algorithm=True)" ).arg( mId, mAlgorithmId );
for ( auto outputIt = mModelOutputs.constBegin(); outputIt != mModelOutputs.constEnd(); ++outputIt )
{
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 QVariantMap QgsProcessingModelChildAlgorithm::configuration() const

View File

@ -278,9 +278,15 @@ class CORE_EXPORT QgsProcessingModelChildAlgorithm : public QgsProcessingModelCo
bool loadVariant( const QVariant &child ); 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: private:

View File

@ -6152,6 +6152,11 @@ void TestQgsProcessing::modelerAlgorithm()
QVERIFY( child.setAlgorithmId( QStringLiteral( "native:centroids" ) ) ); QVERIFY( child.setAlgorithmId( QStringLiteral( "native:centroids" ) ) );
QVERIFY( child.algorithm() ); QVERIFY( child.algorithm() );
QCOMPARE( child.algorithm()->id(), QStringLiteral( "native:centroids" ) ); 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! // bit of a hack -- but try to simulate an algorithm not originally available!
child.mAlgorithm.reset(); child.mAlgorithm.reset();
QVERIFY( !child.algorithm() ); QVERIFY( !child.algorithm() );
@ -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( 0 ).staticValue().toInt(), 7 );
QCOMPARE( child.parameterSources().value( QStringLiteral( "b" ) ).at( 1 ).staticValue().toInt(), 9 ); 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; QgsProcessingModelOutput testModelOut;
testModelOut.setChildId( QStringLiteral( "my_id" ) ); testModelOut.setChildId( QStringLiteral( "my_id" ) );
QCOMPARE( testModelOut.childId(), QStringLiteral( "my_id" ) ); QCOMPARE( testModelOut.childId(), QStringLiteral( "my_id" ) );
@ -6228,6 +6235,8 @@ void TestQgsProcessing::modelerAlgorithm()
QCOMPARE( child.modelOutput( "a" ).description(), QStringLiteral( "my output" ) ); QCOMPARE( child.modelOutput( "a" ).description(), QStringLiteral( "my output" ) );
child.modelOutput( "a" ).setDescription( QStringLiteral( "my output 2" ) ); child.modelOutput( "a" ).setDescription( QStringLiteral( "my output 2" ) );
QCOMPARE( child.modelOutput( "a" ).description(), 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 // no existent
child.modelOutput( "b" ).setDescription( QStringLiteral( "my output 3" ) ); child.modelOutput( "b" ).setDescription( QStringLiteral( "my output 3" ) );
QCOMPARE( child.modelOutput( "b" ).description(), QStringLiteral( "my output 3" ) ); QCOMPARE( child.modelOutput( "b" ).description(), QStringLiteral( "my output 3" ) );