Your layer has a MultiPolygon
geometry type. Therefore, the source.wkbType()
test will return WkbType.MultiPolygon
which is why the processing exception is being raised.
Change your conditional statement to:
if source is None or QgsWkbTypes.geometryType(source.wkbType()) != QgsWkbTypes.PolygonGeometry:
raise QgsProcessingException('Invalid input source. Expected a polygon layer.')
I assume that you are already passing a list of types to the QgsProcessingParameterFeatureSource
constructor so that the input layer dropdown box is filtered e.g.
def initAlgorithm(self, config=None):
self.addParameter(QgsProcessingParameterFeatureSource(
self.INPUT,
self.tr("Input polygon layer"),
[QgsProcessing.TypeVectorPolygon]))
But, since it is still possible to select a different input type when using browse or select file...
...a check of the input geometry type is indeed prudent.
However, I suggest that an alternative (and perhaps better practice) way to run the input check is to re-implement and override the checkParameterValues
method of the QgsProcessingAlgorithm
class and do the check there.
def checkParameterValues(self, parameters, context):
source = self.parameterAsSource(parameters, self.INPUT, context)
if source is None or QgsWkbTypes.geometryType(source.wkbType()) != QgsWkbTypes.PolygonGeometry:
return False, self.tr('Invalid input source. Expected a polygon layer.')
return super().checkParameterValues(parameters, context)
Here, we can implement our own logic and return False
and a helpful message string if the check fails.
Following this recommendation given in the docs:
Overridden implementations should also check this base class
implementation.
we can use super() which returns an object which represents the base or parent class of a subclass (in this case QgsProcessingAlgorithm
) and call the default implementation of checkParameterValues()
, returning the result- as in this example.
Now, if you try to run the algorithm with a non-polygon layer input, you will see this:
Edit: There are a few other issues with your code. You have not passed is_child_algorithm=True
to your processing.run()
call. This is required since the "native:polygonstolines" alg is being run inside a parent algorithm.
As for the persistent error you were getting, I found that to get the child algorithm to accept the parent input, I had to call the materialize()
method on the QgsProcessingFeatureSource
object to return an in memory copy as a QgsVectorLayer
object.
Below is a complete working example. By the way, I guess that you will be adding some more processing steps because, as it is, this whole script is just a wrapper around an existing algorithm. If you add more steps you may want to use QgsProcessingMultiStepFeedback
. You can see an example in my recent answer here.
from qgis.PyQt.QtCore import QCoreApplication, QVariant
from qgis.core import (QgsProcessing, QgsProcessingAlgorithm,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterVectorDestination,
QgsWkbTypes, QgsFeatureRequest)
import processing
class ConvertPolygons(QgsProcessingAlgorithm):
INPUT = 'INPUT'
OUTPUT = 'OUTPUT'
def __init__(self):
super().__init__()
def name(self):
return "exportarpolygonos"
def tr(self, text):
return QCoreApplication.translate("exportarpolygonos", text)
def displayName(self):
return self.tr("Exportar Polygonos")
def group(self):
return self.tr("Examples")
def groupId(self):
return "examples"
def shortHelpString(self):
return self.tr("Exportar Polygonos")
def helpUrl(self):
return "https://qgis.org"
def createInstance(self):
return type(self)()
def checkParameterValues(self, parameters, context):
source = self.parameterAsSource(parameters, self.INPUT, context)
if source is None or QgsWkbTypes.geometryType(source.wkbType()) != QgsWkbTypes.PolygonGeometry:
return False, self.tr('Invalid input source. Expected a polygon layer.')
return super().checkParameterValues(parameters, context)
def initAlgorithm(self, config=None):
self.addParameter(QgsProcessingParameterFeatureSource(
self.INPUT,
self.tr("Input polygons"),
[QgsProcessing.TypeVectorPolygon]))
self.addParameter(QgsProcessingParameterVectorDestination(
self.OUTPUT,
self.tr('Output lines')))
def processAlgorithm(self, parameters, context, feedback):
source = self.parameterAsSource(parameters, self.INPUT, context).materialize(QgsFeatureRequest())
results = {}
outputs = {}
feedback.setProgressText('Converting polygons to lines...')
outputs['converted_lines'] = processing.run("native:polygonstolines",
{'INPUT':source, 'OUTPUT':parameters['OUTPUT']},
context=context,
feedback=feedback,
is_child_algorithm=True)
results['OUTPUT'] = outputs['converted_lines']['OUTPUT']
return results