Skip to content
Permalink
Browse files

[processing] Instead of a hidden parameter for verbose model logging,

add an explicit log level getter/setter to QgsProcessingContext which
algorithms can use to determine an appropriate level of feedback
to push to users.

Initially the verbose log only triggers the full verbose output
of model executions (which is also used when running models through
the model designer), but the intention is that more algorithms
will fine tune their output based on the logging level.

qgis_process also gains a new --verbose switch to enable verbose
log output.
  • Loading branch information
nyalldawson committed Feb 19, 2021
1 parent 9489afe commit c8d61499fff8e39319eb52fcee177a40c5f04ef8
@@ -34,6 +34,12 @@ expression context.
typedef QFlags<QgsProcessingContext::Flag> Flags;


enum LogLevel
{
DefaultLevel,
Verbose,
};

QgsProcessingContext();
%Docstring
Constructor for QgsProcessingContext.
@@ -558,6 +564,24 @@ function will be used when creating these outputs.
.. seealso:: :py:func:`setPreferredVectorFormat`

.. versionadded:: 3.10
%End

LogLevel logLevel() const;
%Docstring
Returns the logging level for algorithms to use when pushing feedback messages to users.

.. seealso:: :py:func:`setLogLevel`

.. versionadded:: 3.20
%End

void setLogLevel( LogLevel level );
%Docstring
Sets the logging ``level`` for algorithms to use when pushing feedback messages to users.

.. seealso:: :py:func:`logLevel`

.. versionadded:: 3.20
%End

private:
@@ -107,6 +107,24 @@ the given ``format``.
.. seealso:: :py:func:`saveLog`

.. versionadded:: 3.2
%End

QgsProcessingContext::LogLevel logLevel() const;
%Docstring
Returns the logging level to use when running algorithms from the dialog.

.. seealso:: :py:func:`setLogLevel`

.. versionadded:: 3.20
%End

void setLogLevel( QgsProcessingContext::LogLevel level );
%Docstring
Sets the logging ``level`` to use when running algorithms from the dialog.

.. seealso:: :py:func:`logLevel`

.. versionadded:: 3.20
%End

public slots:
@@ -119,6 +119,7 @@ def createProcessingParameters(self, include_default=True):
def runAlgorithm(self):
self.feedback = self.createFeedback()
self.context = dataobjects.createContext(self.feedback)
self.context.setLogLevel(self.logLevel())

checkCRS = ProcessingConfig.getSetting(ProcessingConfig.WARN_UNMATCHING_CRS)
try:
@@ -41,6 +41,7 @@
QgsProject,
QgsProcessingModelParameter,
QgsSettings,
QgsProcessingContext
)
from qgis.gui import (QgsProcessingParameterDefinitionDialog,
QgsProcessingParameterWidgetContext,
@@ -152,6 +153,7 @@ def on_finished(successful, results):
self.setLastRunChildAlgorithmInputs(dlg.results().get('CHILD_INPUTS', {}))

dlg = AlgorithmDialog(self.model().create(), parent=self)
dlg.setLogLevel(QgsProcessingContext.Verbose)
dlg.setParameters(self.model().designerParameterValues())
dlg.algorithmFinished.connect(on_finished)
dlg.exec_()
@@ -42,9 +42,6 @@ QgsProcessingModelAlgorithm::QgsProcessingModelAlgorithm( const QString &name, c

void QgsProcessingModelAlgorithm::initAlgorithm( const QVariantMap & )
{
std::unique_ptr< QgsProcessingParameterBoolean > verboseLog = qgis::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "VERBOSE_LOG" ), QObject::tr( "Verbose logging" ), false, true );
verboseLog->setFlags( verboseLog->flags() | QgsProcessingParameterDefinition::FlagHidden );
addParameter( verboseLog.release() );
}

QString QgsProcessingModelAlgorithm::name() const
@@ -288,7 +285,7 @@ QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap &pa
QVariantMap childResults;
QVariantMap childInputs;

const bool verboseLog = parameterAsBool( parameters, QStringLiteral( "VERBOSE_LOG" ), context );
const bool verboseLog = context.logLevel() == QgsProcessingContext::Verbose;

QVariantMap finalResults;
QSet< QString > executed;
@@ -1348,9 +1345,6 @@ QVariant QgsProcessingModelAlgorithm::toVariant() const
QVariantMap paramDefMap;
for ( const QgsProcessingParameterDefinition *def : mParameters )
{
if ( def->name() == QLatin1String( "VERBOSE_LOG" ) )
continue;

paramDefMap.insert( def->name(), def->toVariantMap() );
}
map.insert( QStringLiteral( "parameterDefinitions" ), paramDefMap );
@@ -1948,10 +1942,7 @@ void QgsProcessingModelAlgorithm::setVariables( const QVariantMap &variables )

QVariantMap QgsProcessingModelAlgorithm::designerParameterValues() const
{
QVariantMap res = mDesignerParameterValues;
// when running through the designer, we show a detailed verbose log to aid in model debugging
res.insert( QStringLiteral( "VERBOSE_LOG" ), true );
return res;
return mDesignerParameterValues;
}

///@endcond
@@ -128,6 +128,16 @@ QgsMapLayer *QgsProcessingContext::takeResultLayer( const QString &id )
return tempLayerStore.takeMapLayer( tempLayerStore.mapLayer( id ) );
}

QgsProcessingContext::LogLevel QgsProcessingContext::logLevel() const
{
return mLogLevel;
}

void QgsProcessingContext::setLogLevel( LogLevel level )
{
mLogLevel = level;
}

QgsDateTimeRange QgsProcessingContext::currentTimeRange() const
{
return mCurrentTimeRange;
@@ -51,6 +51,17 @@ class CORE_EXPORT QgsProcessingContext
};
Q_DECLARE_FLAGS( Flags, Flag )

/**
* Logging level for algorithms to use when pushing feedback messages.
*
* \since QGIS 3.20
*/
enum LogLevel
{
DefaultLevel = 0, //!< Default logging level
Verbose, //!< Verbose logging
};

/**
* Constructor for QgsProcessingContext.
*/
@@ -84,6 +95,7 @@ class CORE_EXPORT QgsProcessingContext
mEllipsoid = other.mEllipsoid;
mDistanceUnit = other.mDistanceUnit;
mAreaUnit = other.mAreaUnit;
mLogLevel = other.mLogLevel;
}

/**
@@ -625,6 +637,22 @@ class CORE_EXPORT QgsProcessingContext
*/
void setPreferredRasterFormat( const QString &format ) { mPreferredRasterFormat = format; }

/**
* Returns the logging level for algorithms to use when pushing feedback messages to users.
*
* \see setLogLevel()
* \since QGIS 3.20
*/
LogLevel logLevel() const;

/**
* Sets the logging \a level for algorithms to use when pushing feedback messages to users.
*
* \see logLevel()
* \since QGIS 3.20
*/
void setLogLevel( LogLevel level );

private:

QgsProcessingContext::Flags mFlags = QgsProcessingContext::Flags();
@@ -654,6 +682,8 @@ class CORE_EXPORT QgsProcessingContext
QString mPreferredVectorFormat;
QString mPreferredRasterFormat;

LogLevel mLogLevel = DefaultLevel;

#ifdef SIP_RUN
QgsProcessingContext( const QgsProcessingContext &other );
#endif
@@ -399,6 +399,16 @@ void QgsProcessingAlgorithmDialogBase::closeClicked()
close();
}

QgsProcessingContext::LogLevel QgsProcessingAlgorithmDialogBase::logLevel() const
{
return mLogLevel;
}

void QgsProcessingAlgorithmDialogBase::setLogLevel( QgsProcessingContext::LogLevel level )
{
mLogLevel = level;
}

void QgsProcessingAlgorithmDialogBase::reportError( const QString &error, bool fatalError )
{
setInfo( error, true );
@@ -163,6 +163,22 @@ class GUI_EXPORT QgsProcessingAlgorithmDialogBase : public QDialog, public QgsPr
*/
void saveLogToFile( const QString &path, LogFormat format = FormatPlainText );

/**
* Returns the logging level to use when running algorithms from the dialog.
*
* \see setLogLevel()
* \since QGIS 3.20
*/
QgsProcessingContext::LogLevel logLevel() const;

/**
* Sets the logging \a level to use when running algorithms from the dialog.
*
* \see logLevel()
* \since QGIS 3.20
*/
void setLogLevel( QgsProcessingContext::LogLevel level );

public slots:

/**
@@ -399,6 +415,8 @@ class GUI_EXPORT QgsProcessingAlgorithmDialogBase : public QDialog, public QgsPr

bool mHelpCollapsed = false;

QgsProcessingContext::LogLevel mLogLevel = QgsProcessingContext::DefaultLevel;

QString formatHelp( QgsProcessingAlgorithm *algorithm );
void scrollToBottomOfLog();
void processEvents();
@@ -240,6 +240,14 @@ int QgsProcessingExec::run( const QStringList &constArgs )
args.removeAt( jsonIndex );
}

const int verboseIndex = args.indexOf( QLatin1String( "--verbose" ) );
QgsProcessingContext::LogLevel logLevel = QgsProcessingContext::DefaultLevel;
if ( verboseIndex >= 0 )
{
logLevel = QgsProcessingContext::Verbose;
args.removeAt( verboseIndex );
}

if ( args.size() == 1 )
{
showUsage( args.at( 0 ) );
@@ -418,7 +426,7 @@ int QgsProcessingExec::run( const QStringList &constArgs )
}
}

return execute( algId, params, ellipsoid, distanceUnit, areaUnit, useJson, projectPath );
return execute( algId, params, ellipsoid, distanceUnit, areaUnit, logLevel, useJson, projectPath );
}
else
{
@@ -433,9 +441,10 @@ void QgsProcessingExec::showUsage( const QString &appName )

msg << "QGIS Processing Executor - " << VERSION << " '" << RELEASE_NAME << "' ("
<< Qgis::version() << ")\n"
<< "Usage: " << appName << " [--json] [command] [algorithm id or path to model file] [parameters]\n"
<< "Usage: " << appName << " [--json] [--verbose] [command] [algorithm id or path to model file] [parameters]\n"
<< "\nOptions:\n"
<< "\t--json\t\tOutput results as JSON objects\n"
<< "\t--verbose\tOutput verbose logs\n"
<< "\nAvailable commands:\n"
<< "\tplugins\t\tlist available and active plugins\n"
<< "\tplugins enable\tenables an installed plugin. The plugin name must be specified, e.g. \"plugins enable cartography_tools\"\n"
@@ -822,7 +831,7 @@ int QgsProcessingExec::showAlgorithmHelp( const QString &id, bool useJson )
return 0;
}

int QgsProcessingExec::execute( const QString &id, const QVariantMap &params, const QString &ellipsoid, QgsUnitTypes::DistanceUnit distanceUnit, QgsUnitTypes::AreaUnit areaUnit, bool useJson, const QString &projectPath )
int QgsProcessingExec::execute( const QString &id, const QVariantMap &params, const QString &ellipsoid, QgsUnitTypes::DistanceUnit distanceUnit, QgsUnitTypes::AreaUnit areaUnit, QgsProcessingContext::LogLevel logLevel, bool useJson, const QString &projectPath )
{
QVariantMap json;
if ( useJson )
@@ -952,6 +961,7 @@ int QgsProcessingExec::execute( const QString &id, const QVariantMap &params, co
context.setDistanceUnit( distanceUnit );
context.setAreaUnit( areaUnit );
context.setProject( project.get() );
context.setLogLevel( logLevel );

const QgsProcessingParameterDefinitions defs = alg->parameterDefinitions();
QList< const QgsProcessingParameterDefinition * > missingParams;
@@ -21,6 +21,7 @@
#include "qgspythonrunner.h"
#include "qgspythonutils.h"
#include "qgsunittypes.h"
#include "qgsprocessingcontext.h"
#include <QElapsedTimer>

class QgsApplication;
@@ -81,6 +82,7 @@ class QgsProcessingExec
const QString &ellipsoid,
QgsUnitTypes::DistanceUnit distanceUnit,
QgsUnitTypes::AreaUnit areaUnit,
QgsProcessingContext::LogLevel logLevel,
bool useJson,
const QString &projectPath = QString() );

@@ -989,6 +989,9 @@ void TestQgsProcessing::context()
QCOMPARE( context.distanceUnit(), QgsUnitTypes::DistanceFeet );
QCOMPARE( context.areaUnit(), QgsUnitTypes::AreaHectares );

context.setLogLevel( QgsProcessingContext::Verbose );
QCOMPARE( static_cast< int >( context.logLevel() ), static_cast< int >( QgsProcessingContext::Verbose ) );

context.setInvalidGeometryCheck( QgsFeatureRequest::GeometrySkipInvalid );
QCOMPARE( context.invalidGeometryCheck(), QgsFeatureRequest::GeometrySkipInvalid );

@@ -1002,6 +1005,7 @@ void TestQgsProcessing::context()
QCOMPARE( context2.invalidGeometryCheck(), context.invalidGeometryCheck() );
QCOMPARE( context2.flags(), context.flags() );
QCOMPARE( context2.project(), context.project() );
QCOMPARE( static_cast< int >( context2.logLevel() ), static_cast< int >( QgsProcessingContext::Verbose ) );
// layers from temporaryLayerStore must not be copied by copyThreadSafeSettings
QVERIFY( context2.temporaryLayerStore()->mapLayers().isEmpty() );

lastParams.insert( QStringLiteral( "a" ), 2 );
lastParams.insert( QStringLiteral( "b" ), 4 );
alg.setDesignerParameterValues( lastParams );

// we expect the result to add in some custom parameters -- namely the verbose log switch
lastParams.insert( QStringLiteral( "VERBOSE_LOG" ), true );
QCOMPARE( alg.designerParameterValues(), lastParams );

// child algorithms
@@ -377,7 +377,6 @@ void TestProcessingGui::testModelUndo()
// the last used parameter values setting should not be affected by undo stack changes
QVariantMap params;
params.insert( QStringLiteral( "a" ), 1 );
params.insert( QStringLiteral( "VERBOSE_LOG" ), true );
model.setDesignerParameterValues( params );
command.undo();
QCOMPARE( model.designerParameterValues(), params );

0 comments on commit c8d6149

Please sign in to comment.