Skip to content

Commit 37774f9

Browse files
committed
[processing] Add util to convert QVariant value to Python literal
1 parent ffa49df commit 37774f9

File tree

4 files changed

+124
-0
lines changed

4 files changed

+124
-0
lines changed

python/core/auto_generated/processing/qgsprocessingutils.sip.in

+11
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,22 @@ This function creates a new object and the caller takes responsibility for delet
131131
%Docstring
132132
Normalizes a layer ``source`` string for safe comparison across different
133133
operating system environments.
134+
%End
135+
136+
static QString variantToPythonLiteral( const QVariant &value );
137+
%Docstring
138+
Converts a variant to a Python literal.
139+
140+
.. seealso:: :py:func:`stringToPythonLiteral`
141+
142+
.. versionadded:: 3.6
134143
%End
135144

136145
static QString stringToPythonLiteral( const QString &string );
137146
%Docstring
138147
Converts a string to a Python string literal. E.g. by replacing ' with \'.
148+
149+
.. seealso:: :py:func:`variantToPythonLiteral`
139150
%End
140151

141152

src/core/processing/qgsprocessingutils.cpp

+79
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "qgsvectorlayer.h"
3232
#include "qgsproviderregistry.h"
3333
#include "qgsmeshlayer.h"
34+
#include "qgsreferencedgeometry.h"
3435

3536
QList<QgsRasterLayer *> QgsProcessingUtils::compatibleRasterLayers( QgsProject *project, bool sort )
3637
{
@@ -389,6 +390,84 @@ QString QgsProcessingUtils::normalizeLayerSource( const QString &source )
389390
return normalized.trimmed();
390391
}
391392

393+
QString QgsProcessingUtils::variantToPythonLiteral( const QVariant &value )
394+
{
395+
if ( !value.isValid() )
396+
return QStringLiteral( "None" );
397+
398+
if ( value.canConvert<QgsProperty>() )
399+
return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );
400+
else if ( value.canConvert<QgsCoordinateReferenceSystem>() )
401+
{
402+
if ( !value.value< QgsCoordinateReferenceSystem >().isValid() )
403+
return QStringLiteral( "QgsCoordinateReferenceSystem()" );
404+
else
405+
return QStringLiteral( "QgsCoordinateReferenceSystem('%1')" ).arg( value.value< QgsCoordinateReferenceSystem >().authid() );
406+
}
407+
else if ( value.canConvert< QgsRectangle >() )
408+
{
409+
QgsRectangle r = value.value<QgsRectangle>();
410+
return QStringLiteral( "'%1, %3, %2, %4'" ).arg( qgsDoubleToString( r.xMinimum() ),
411+
qgsDoubleToString( r.yMinimum() ),
412+
qgsDoubleToString( r.xMaximum() ),
413+
qgsDoubleToString( r.yMaximum() ) );
414+
}
415+
else if ( value.canConvert< QgsReferencedRectangle >() )
416+
{
417+
QgsReferencedRectangle r = value.value<QgsReferencedRectangle>();
418+
return QStringLiteral( "'%1, %3, %2, %4 [%5]'" ).arg( qgsDoubleToString( r.xMinimum() ),
419+
qgsDoubleToString( r.yMinimum() ),
420+
qgsDoubleToString( r.xMaximum() ),
421+
qgsDoubleToString( r.yMaximum() ), r.crs().authid() );
422+
}
423+
else if ( value.canConvert< QgsPointXY >() )
424+
{
425+
QgsPointXY r = value.value<QgsPointXY>();
426+
return QStringLiteral( "'%1,%2'" ).arg( qgsDoubleToString( r.x() ),
427+
qgsDoubleToString( r.y() ) );
428+
}
429+
else if ( value.canConvert< QgsReferencedPointXY >() )
430+
{
431+
QgsReferencedPointXY r = value.value<QgsReferencedPointXY>();
432+
return QStringLiteral( "'%1,%2 [%3]'" ).arg( qgsDoubleToString( r.x() ),
433+
qgsDoubleToString( r.y() ),
434+
r.crs().authid() );
435+
}
436+
437+
switch ( value.type() )
438+
{
439+
case QVariant::Bool:
440+
return value.toBool() ? QStringLiteral( "True" ) : QStringLiteral( "False" );
441+
442+
case QVariant::Double:
443+
return QString::number( value.toDouble() );
444+
445+
case QVariant::Int:
446+
case QVariant::UInt:
447+
return QString::number( value.toInt() );
448+
449+
case QVariant::LongLong:
450+
case QVariant::ULongLong:
451+
return QString::number( value.toLongLong() );
452+
453+
case QVariant::List:
454+
{
455+
QStringList parts;
456+
const QVariantList vl = value.toList();
457+
for ( const QVariant &v : vl )
458+
{
459+
parts << variantToPythonLiteral( v );
460+
}
461+
return parts.join( ',' ).prepend( '[' ).append( ']' );
462+
}
463+
464+
default:
465+
break;
466+
}
467+
468+
return QgsProcessingUtils::stringToPythonLiteral( value.toString() );
469+
}
470+
392471
QString QgsProcessingUtils::stringToPythonLiteral( const QString &string )
393472
{
394473
QString s = string;

src/core/processing/qgsprocessingutils.h

+10
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,18 @@ class CORE_EXPORT QgsProcessingUtils
149149
*/
150150
static QString normalizeLayerSource( const QString &source );
151151

152+
/**
153+
* Converts a variant to a Python literal.
154+
*
155+
* \see stringToPythonLiteral()
156+
* \since QGSIS 3.6
157+
*/
158+
static QString variantToPythonLiteral( const QVariant &value );
159+
152160
/**
153161
* Converts a string to a Python string literal. E.g. by replacing ' with \'.
162+
*
163+
* \see variantToPythonLiteral()
154164
*/
155165
static QString stringToPythonLiteral( const QString &string );
156166

tests/src/analysis/testqgsprocessing.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,7 @@ class TestQgsProcessing: public QObject
576576
void combineFields();
577577
void fieldNamesToIndices();
578578
void indicesToFields();
579+
void variantToPythonLiteral();
579580
void stringToPythonLiteral();
580581
void defaultExtensionsForProvider();
581582
void supportedExtensions();
@@ -7506,6 +7507,29 @@ void TestQgsProcessing::indicesToFields()
75067507
QCOMPARE( fields3, QgsFields() );
75077508
}
75087509

7510+
void TestQgsProcessing::variantToPythonLiteral()
7511+
{
7512+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( QVariant() ), QStringLiteral( "None" ) );
7513+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( QVariant::fromValue( QgsProperty::fromExpression( QStringLiteral( "1+2" ) ) ) ), QStringLiteral( "QgsProperty.fromExpression('1+2')" ) );
7514+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( QVariant::fromValue( QgsCoordinateReferenceSystem() ) ), QStringLiteral( "QgsCoordinateReferenceSystem()" ) );
7515+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( QVariant::fromValue( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3111" ) ) ) ), QStringLiteral( "QgsCoordinateReferenceSystem('EPSG:3111')" ) );
7516+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( QVariant::fromValue( QgsRectangle( 1, 2, 3, 4 ) ) ), QStringLiteral( "'1, 3, 2, 4'" ) );
7517+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( QVariant::fromValue( QgsReferencedRectangle( QgsRectangle( 1, 2, 3, 4 ), QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:28356" ) ) ) ) ), QStringLiteral( "'1, 3, 2, 4 [EPSG:28356]'" ) );
7518+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( QVariant::fromValue( QgsPointXY( 1, 2 ) ) ), QStringLiteral( "'1,2'" ) );
7519+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( QVariant::fromValue( QgsReferencedPointXY( QgsPointXY( 1, 2 ), QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:28356" ) ) ) ) ), QStringLiteral( "'1,2 [EPSG:28356]'" ) );
7520+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( true ), QStringLiteral( "True" ) );
7521+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( false ), QStringLiteral( "False" ) );
7522+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( 5 ), QStringLiteral( "5" ) );
7523+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( 5.5 ), QStringLiteral( "5.5" ) );
7524+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( 5LL ), QStringLiteral( "5" ) );
7525+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( QVariantList() << true << QVariant() << QStringLiteral( "a" ) ), QStringLiteral( "[True,None,'a']" ) );
7526+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( QStringLiteral( "a" ) ), QStringLiteral( "'a'" ) );
7527+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( QString() ), QStringLiteral( "''" ) );
7528+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( QStringLiteral( "a 'string'" ) ), QStringLiteral( "'a \\'string\\''" ) );
7529+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( QStringLiteral( "a \"string\"" ) ), QStringLiteral( "'a \\\"string\\\"'" ) );
7530+
QCOMPARE( QgsProcessingUtils::variantToPythonLiteral( QStringLiteral( "a \n str\tin\\g" ) ), QStringLiteral( "'a \\n str\\tin\\\\g'" ) );
7531+
}
7532+
75097533
void TestQgsProcessing::stringToPythonLiteral()
75107534
{
75117535
QCOMPARE( QgsProcessingUtils::stringToPythonLiteral( QStringLiteral( "a" ) ), QStringLiteral( "'a'" ) );

0 commit comments

Comments
 (0)