Skip to content

Commit d342ce9

Browse files
committedFeb 14, 2019
[processing] When converting models to Python, use friendlier (more
descriptive) names when storing child algorithm results Makes for much easier to understand scripts
1 parent 3ceea2a commit d342ce9

8 files changed

+79
-38
lines changed
 

‎python/core/auto_generated/processing/models/qgsprocessingmodelchildalgorithm.sip.in

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ Loads this child from a QVariant.
298298
.. seealso:: :py:func:`toVariant`
299299
%End
300300

301-
QStringList asPythonCode( QgsProcessing::PythonOutputType outputType, const QgsStringMap &extraParameters, int currentIndent, int indentSize ) const;
301+
QStringList asPythonCode( QgsProcessing::PythonOutputType outputType, const QgsStringMap &extraParameters, int currentIndent, int indentSize, const QMap<QString, QString> &friendlyChildNames ) const;
302302
%Docstring
303303
Attempts to convert the child to executable Python code, and returns a list of the generated lines of code.
304304

@@ -307,6 +307,8 @@ The ``outputType`` argument specifies the type of script to generate.
307307
Additional parameters to be passed to the child algorithm are specified in the ``extraParameters`` argument.
308308

309309
The ``currentIndent`` and ``indentSize`` are used to set the base line indent and size of further indented lines respectively.
310+
311+
The ``friendlyChildNames`` argument gives a map of child id to a friendly algorithm name, to be used in the code to identify that algorithm instead of the raw child id.
310312
%End
311313

312314
};

‎python/core/auto_generated/processing/models/qgsprocessingmodelchildparametersource.sip.in

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,11 @@ Loads this source from a QVariantMap.
240240
.. seealso:: :py:func:`toVariant`
241241
%End
242242

243-
QString asPythonCode( QgsProcessing::PythonOutputType outputType, const QgsProcessingParameterDefinition *definition ) const;
243+
QString asPythonCode( QgsProcessing::PythonOutputType outputType, const QgsProcessingParameterDefinition *definition, const QMap< QString, QString > &friendlydChildNames ) const;
244244
%Docstring
245245
Attempts to convert the source to executable Python code.
246+
247+
The ``friendlyChildNames`` argument gives a map of child id to a friendly algorithm name, to be used in the code to identify that algorithm instead of the raw child id.
246248
%End
247249

248250
};

‎src/core/processing/models/qgsprocessingmodelalgorithm.cpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -361,23 +361,42 @@ QStringList QgsProcessingModelAlgorithm::asPythonCode( const QgsProcessing::Pyth
361361
QString indent = QString( ' ' ).repeated( indentSize );
362362
QString currentIndent;
363363

364-
auto safeName = []( const QString & name )->QString
364+
QMap< QString, QString> friendlyChildNames;
365+
auto safeName = []( const QString & name, bool capitalize )->QString
365366
{
366367
QString n = name.toLower().trimmed();
367368
QRegularExpression rx( QStringLiteral( "[^\\sa-z_A-Z0-9]" ) );
368369
n.replace( rx, QString() );
369370
QRegularExpression rx2( QStringLiteral( "^\\d*" ) ); // name can't start in a digit
370371
n.replace( rx2, QString() );
371-
return QgsStringUtils::capitalize( n, QgsStringUtils::UpperCamelCase );
372+
if ( !capitalize )
373+
n = n.replace( ' ', '_' );
374+
return capitalize ? QgsStringUtils::capitalize( n, QgsStringUtils::UpperCamelCase ) : n;
372375
};
373376

374-
const QString algorithmClassName = safeName( name() );
377+
auto uniqueSafeName = [&friendlyChildNames, &safeName ]( const QString & name, bool capitalize )->QString
378+
{
379+
const QString base = safeName( name, capitalize );
380+
QString candidate = base;
381+
int i = 1;
382+
while ( friendlyChildNames.contains( candidate ) )
383+
{
384+
i++;
385+
candidate = QStringLiteral( "%1_%2" ).arg( base ).arg( i );
386+
}
387+
return candidate;
388+
};
389+
390+
const QString algorithmClassName = safeName( name(), true );
375391

376392
QSet< QString > toExecute;
377393
for ( auto childIt = mChildAlgorithms.constBegin(); childIt != mChildAlgorithms.constEnd(); ++childIt )
378394
{
379395
if ( childIt->isActive() && childIt->algorithm() )
396+
{
380397
toExecute.insert( childIt->childId() );
398+
friendlyChildNames.insert( childIt->childId(), uniqueSafeName( childIt->description().isEmpty() ? childIt->childId() : childIt->description(), !childIt->description().isEmpty() ) );
399+
}
381400
}
382401
const int totalSteps = toExecute.count();
383402

@@ -462,6 +481,7 @@ QStringList QgsProcessingModelAlgorithm::asPythonCode( const QgsProcessing::Pyth
462481

463482
lines << currentIndent + QStringLiteral( "results = {}" );
464483
lines << currentIndent + QStringLiteral( "outputs = {}" );
484+
lines << QString();
465485

466486
QSet< QString > executed;
467487
bool executedAlg = true;
@@ -536,7 +556,7 @@ QStringList QgsProcessingModelAlgorithm::asPythonCode( const QgsProcessing::Pyth
536556
}
537557
}
538558

539-
lines << child.asPythonCode( outputType, childParams, currentIndent.size(), indentSize );
559+
lines << child.asPythonCode( outputType, childParams, currentIndent.size(), indentSize, friendlyChildNames );
540560
currentStep++;
541561
if ( currentStep < totalSteps )
542562
{

‎src/core/processing/models/qgsprocessingmodelchildalgorithm.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ bool QgsProcessingModelChildAlgorithm::loadVariant( const QVariant &child )
162162
return true;
163163
}
164164

165-
QStringList QgsProcessingModelChildAlgorithm::asPythonCode( const QgsProcessing::PythonOutputType outputType, const QgsStringMap &extraParameters, int currentIndent, int indentSize ) const
165+
QStringList QgsProcessingModelChildAlgorithm::asPythonCode( const QgsProcessing::PythonOutputType outputType, const QgsStringMap &extraParameters, int currentIndent, int indentSize, const QMap<QString, QString> &friendlyChildNames ) const
166166
{
167167
QStringList lines;
168168
const QString baseIndent = QString( ' ' ).repeated( currentIndent );
@@ -181,7 +181,7 @@ QStringList QgsProcessingModelChildAlgorithm::asPythonCode( const QgsProcessing:
181181
const auto parts = paramIt.value();
182182
for ( const QgsProcessingModelChildParameterSource &source : parts )
183183
{
184-
QString part = source.asPythonCode( outputType, def );
184+
QString part = source.asPythonCode( outputType, def, friendlyChildNames );
185185
if ( !part.isEmpty() )
186186
sourceParts << part;
187187
}
@@ -207,11 +207,11 @@ QStringList QgsProcessingModelChildAlgorithm::asPythonCode( const QgsProcessing:
207207
}
208208
lines << baseIndent + QStringLiteral( "}" );
209209

210-
lines << baseIndent + QStringLiteral( "outputs['%1'] = processing.run('%2', alg_params, context=context, feedback=feedback, is_child_algorithm=True)" ).arg( mId, mAlgorithmId );
210+
lines << baseIndent + QStringLiteral( "outputs['%1'] = processing.run('%2', alg_params, context=context, feedback=feedback, is_child_algorithm=True)" ).arg( friendlyChildNames.value( mId, mId ), mAlgorithmId );
211211

212212
for ( auto outputIt = mModelOutputs.constBegin(); outputIt != mModelOutputs.constEnd(); ++outputIt )
213213
{
214-
lines << baseIndent + QStringLiteral( "results['%1:%2'] = outputs['%1']['%3']" ).arg( mId, outputIt.key(), outputIt.value().childOutputName() );
214+
lines << baseIndent + QStringLiteral( "results['%1:%2'] = outputs['%3']['%4']" ).arg( mId, outputIt.key(), friendlyChildNames.value( mId, mId ), outputIt.value().childOutputName() );
215215
}
216216

217217
return lines;

‎src/core/processing/models/qgsprocessingmodelchildalgorithm.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,10 @@ class CORE_EXPORT QgsProcessingModelChildAlgorithm : public QgsProcessingModelCo
285285
* Additional parameters to be passed to the child algorithm are specified in the \a extraParameters argument.
286286
*
287287
* The \a currentIndent and \a indentSize are used to set the base line indent and size of further indented lines respectively.
288+
*
289+
* The \a friendlyChildNames argument gives a map of child id to a friendly algorithm name, to be used in the code to identify that algorithm instead of the raw child id.
288290
*/
289-
QStringList asPythonCode( QgsProcessing::PythonOutputType outputType, const QgsStringMap &extraParameters, int currentIndent, int indentSize ) const;
291+
QStringList asPythonCode( QgsProcessing::PythonOutputType outputType, const QgsStringMap &extraParameters, int currentIndent, int indentSize, const QMap<QString, QString> &friendlyChildNames ) const;
290292

291293
private:
292294

‎src/core/processing/models/qgsprocessingmodelchildparametersource.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,15 @@ bool QgsProcessingModelChildParameterSource::loadVariant( const QVariantMap &map
147147
return true;
148148
}
149149

150-
QString QgsProcessingModelChildParameterSource::asPythonCode( const QgsProcessing::PythonOutputType, const QgsProcessingParameterDefinition *definition ) const
150+
QString QgsProcessingModelChildParameterSource::asPythonCode( const QgsProcessing::PythonOutputType, const QgsProcessingParameterDefinition *definition, const QMap< QString, QString > &friendlydChildNames ) const
151151
{
152152
switch ( mSource )
153153
{
154154
case ModelParameter:
155155
return QStringLiteral( "parameters['%1']" ).arg( mParameterName );
156156

157157
case ChildOutput:
158-
return QStringLiteral( "outputs['%1']['%2']" ).arg( mChildId, mOutputName );
158+
return QStringLiteral( "outputs['%1']['%2']" ).arg( friendlydChildNames.value( mChildId, mChildId ), mOutputName );
159159

160160
case StaticValue:
161161
if ( definition )

‎src/core/processing/models/qgsprocessingmodelchildparametersource.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,10 @@ class CORE_EXPORT QgsProcessingModelChildParameterSource
215215

216216
/**
217217
* Attempts to convert the source to executable Python code.
218+
*
219+
* The \a friendlyChildNames argument gives a map of child id to a friendly algorithm name, to be used in the code to identify that algorithm instead of the raw child id.
218220
*/
219-
QString asPythonCode( QgsProcessing::PythonOutputType outputType, const QgsProcessingParameterDefinition *definition ) const;
221+
QString asPythonCode( QgsProcessing::PythonOutputType outputType, const QgsProcessingParameterDefinition *definition, const QMap< QString, QString > &friendlydChildNames ) const;
220222

221223
private:
222224

‎tests/src/analysis/testqgsprocessing.cpp

Lines changed: 37 additions & 24 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.