Skip to content

Commit

Permalink
Add method to QgsProcessingAlgorithm to create equivalent qgis_proces…
Browse files Browse the repository at this point in the history
…s command
  • Loading branch information
nyalldawson committed Dec 16, 2021
1 parent 6315133 commit fe471ea
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 0 deletions.
Expand Up @@ -445,6 +445,20 @@ Algorithms which cannot be run from a Python command should return an empty
string.
%End

virtual QString asQgisProcessCommand( const QVariantMap &parameters, QgsProcessingContext &context, bool &ok /Out/ ) const;
%Docstring
Returns a command string which will execut the algorithm using the specified ``parameters``
via the command line qgis_process tool.

Note that some combinations of parameter types and values cannot be represented as a qgis_process string.

:param parameters: algorithm parameters
:param context: processing context

:return: - equivalent qgis_process command
- ok: will be set to ``True`` if the command was successfully generated
%End

void setProvider( QgsProcessingProvider *provider );
%Docstring
Associates this algorithm with its provider. No transfer of ownership is involved.
Expand Down
34 changes: 34 additions & 0 deletions src/core/processing/qgsprocessingalgorithm.cpp
Expand Up @@ -306,6 +306,40 @@ QString QgsProcessingAlgorithm::asPythonCommand( const QVariantMap &parameters,
return s;
}

QString QgsProcessingAlgorithm::asQgisProcessCommand( const QVariantMap &parameters, QgsProcessingContext &context, bool &ok ) const
{
ok = true;
QStringList parts;
parts.append( QStringLiteral( "qgis_process" ) );
parts.append( QStringLiteral( "run" ) );
parts.append( id() );

QgsProcessingContext::ProcessArgumentFlags argumentFlags;
// we only include the project path argument if a project is actually required by the algorithm
if ( flags() & FlagRequiresProject )
argumentFlags |= QgsProcessingContext::ProcessArgumentFlag::IncludeProjectPath;

parts.append( context.asQgisProcessArguments( argumentFlags ) );

for ( const QgsProcessingParameterDefinition *def : mParameters )
{
if ( def->flags() & QgsProcessingParameterDefinition::FlagHidden )
continue;

if ( !parameters.contains( def->name() ) )
continue;

const QStringList partValues = def->valueAsStringList( parameters.value( def->name() ), context, ok );
if ( !ok )
return QString();

for ( const QString &partValue : partValues )
parts << QStringLiteral( "--%1=%2" ).arg( def->name(), partValue );
}

return parts.join( ' ' );
}

bool QgsProcessingAlgorithm::addParameter( QgsProcessingParameterDefinition *definition, bool createOutput )
{
if ( !definition )
Expand Down
14 changes: 14 additions & 0 deletions src/core/processing/qgsprocessingalgorithm.h
Expand Up @@ -461,6 +461,20 @@ class CORE_EXPORT QgsProcessingAlgorithm
*/
virtual QString asPythonCommand( const QVariantMap &parameters, QgsProcessingContext &context ) const;

/**
* Returns a command string which will execut the algorithm using the specified \a parameters
* via the command line qgis_process tool.
*
* Note that some combinations of parameter types and values cannot be represented as a qgis_process string.
*
* \param parameters algorithm parameters
* \param context processing context
* \param ok will be set to TRUE if the command was successfully generated
*
* \returns equivalent qgis_process command
*/
virtual QString asQgisProcessCommand( const QVariantMap &parameters, QgsProcessingContext &context, bool &ok SIP_OUT ) const;

/**
* Associates this algorithm with its provider. No transfer of ownership is involved.
*/
Expand Down
54 changes: 54 additions & 0 deletions tests/src/analysis/testqgsprocessing.cpp
Expand Up @@ -345,6 +345,51 @@ class DummyAlgorithm : public QgsProcessingAlgorithm
QCOMPARE( asPythonCommand( params, context ), QStringLiteral( "processing.run(\"test\", {'p1':'a','p2':'b'})" ) );
}

void runAsQgisProcessCommandChecks()
{
addParameter( new QgsProcessingParameterString( "p1" ) );
addParameter( new QgsProcessingParameterEnum( "p2", QString(), QStringList( {"a", "b"} ), true ) );
QgsProcessingParameterString *hidden = new QgsProcessingParameterString( "p3" );
hidden->setFlags( QgsProcessingParameterDefinition::FlagHidden );
addParameter( hidden );

QVariantMap params;
QgsProcessingContext context;

bool ok = false;
QCOMPARE( asQgisProcessCommand( params, context, ok ), QStringLiteral( "qgis_process run test" ) );
QVERIFY( ok );
params.insert( QStringLiteral( "p1" ), "a" );
QCOMPARE( asQgisProcessCommand( params, context, ok ), QStringLiteral( "qgis_process run test --p1=a" ) );
QVERIFY( ok );
params.insert( QStringLiteral( "p2" ), QVariant() );
QCOMPARE( asQgisProcessCommand( params, context, ok ), QStringLiteral( "qgis_process run test --p1=a" ) );
QVERIFY( ok );
params.insert( "p2", "b" );
QCOMPARE( asQgisProcessCommand( params, context, ok ), QStringLiteral( "qgis_process run test --p1=a --p2=b" ) );
QVERIFY( ok );

params.insert( "p2", QStringList( {"b", "c"} ) );
QCOMPARE( asQgisProcessCommand( params, context, ok ), QStringLiteral( "qgis_process run test --p1=a --p2=b --p2=c" ) );
QVERIFY( ok );

// hidden, shouldn't be shown
params.insert( "p3", "b" );
QCOMPARE( asQgisProcessCommand( params, context, ok ), QStringLiteral( "qgis_process run test --p1=a --p2=b --p2=c" ) );
QVERIFY( ok );

// test inclusion of a context setting
context.setDistanceUnit( QgsUnitTypes::DistanceMeters );
QCOMPARE( asQgisProcessCommand( params, context, ok ), QStringLiteral( "qgis_process run test --distance_units=meters --p1=a --p2=b --p2=c" ) );
QVERIFY( ok );

// test non-convertible parameter value
params.insert( "p2", QVariant::fromValue( QRectF( 0, 1, 2, 3 ) ) );
QCOMPARE( asQgisProcessCommand( params, context, ok ), QString() );
QVERIFY( !ok );
}


void addDestParams()
{
QgsProcessingParameterFeatureSink *sinkParam1 = new QgsProcessingParameterFeatureSink( "supports" );
Expand Down Expand Up @@ -686,6 +731,7 @@ class TestQgsProcessing: public QObject
void validateInputCrs();
void generateIteratingDestination();
void asPythonCommand();
void asQgisProcessCommand();
void modelerAlgorithm();
void modelExecution();
void modelBranchPruning();
Expand Down Expand Up @@ -10828,6 +10874,14 @@ void TestQgsProcessing::asPythonCommand()
alg.runAsPythonCommandChecks();
}

void TestQgsProcessing::asQgisProcessCommand()
{
// test converting an algorithm to a qgis_process command

DummyAlgorithm alg( "test" );
alg.runAsQgisProcessCommandChecks();
}

void TestQgsProcessing::modelerAlgorithm()
{
//static value source
Expand Down

0 comments on commit fe471ea

Please sign in to comment.