예제 #1
0
def parse_input_definition(param: QgsProcessingParameterDefinition,
                           kwargs,
                           context: MapContext = None) -> WPSInput:
    """ Convert processing input to File Input 
    """
    typ = param.type()

    if typ == 'crs':
        kwargs['data_type'] = 'string'
        return LiteralInput(**kwargs)
    elif typ == "extent":
        return parse_extent_input(param, kwargs, context)
    elif isinstance(param, GeometryParameterTypes):
        kwargs['supported_formats'] = [
            Format.from_definition(FORMATS.GEOJSON),
            Format.from_definition(FORMATS.GML),
            Format.from_definition(FORMATS.WKT)
        ]
        if isinstance(param, QgsProcessingParameterGeometry):
            # Add metadata from requiered geometryTypes
            kwargs['metadata'].extend(
                Metadata('processing:geometryType', QgsWkbTypes.geometryDisplayString(geomtype)) \
                for geomtype in param.geometryTypes()
            )
            if param.allowMultipart():
                kwargs['metadata'].append(
                    Metadata('processing:allowMultipart'))
        return ComplexInput(**kwargs)

    return None
예제 #2
0
    def get_processes(self):
        def hello(request):
            pass

        hello_string = WPSProcess(
            hello,
            'hello_string',
            'Process Hello',
            inputs=[LiteralInput('the_name', 'Input name')],
            metadata=[
                Metadata('process metadata 1', 'http://example.org/1'),
                Metadata('process metadata 2', 'http://example.org/2')
            ])

        def hello(request):
            pass

        hello_integer = WPSProcess(hello,
                                   'hello_integer',
                                   'Process Hello',
                                   inputs=[
                                       LiteralInput(
                                           'the_number',
                                           'Input number',
                                           data_type='positiveInteger')
                                   ])
        return [hello_string, hello_integer]
예제 #3
0
def parse_input_definition(param: QgsProcessingParameterDefinition,
                           kwargs) -> Union[LiteralInput, ComplexInput]:
    """ Convert processing input to File Input 
    """
    typ = param.type()
    if typ == 'file':
        if param.behavior() == QgsProcessingParameterFile.Folder:
            kwargs['data_type'] = 'string'
            return LiteralInput(**kwargs)
        ext = param.extension()
        if ext:
            mime = mimetypes.types_map.get(ext)
            if mime is not None:
                kwargs['supported_formats'] = [Format(mime)]
            kwargs['metadata'].append(
                Metadata('processing:extension', param.extension()))
        return ComplexInput(**kwargs)
    elif typ == 'fileDestination':
        extension = '.' + param.defaultFileExtension()
        kwargs['data_type'] = 'string'
        kwargs['metadata'].append(
            Metadata('processing:format',
                     mimetypes.types_map.get(extension, '')))
        return LiteralInput(**kwargs)
    elif typ == 'folderDestination':
        kwargs['data_type'] = 'string'
        return LiteralInput(**kwargs)
예제 #4
0
def parse_input_definition(param: QgsProcessingParameterDefinition,
                           kwargs,
                           context: MapContext = None) -> LiteralInput:
    """ Layers input may be passed in various forms:

        - For input layers and if a context is given: it will be a list of  available layers from 
          the source project as literal string.
        - If there is no context, the input will be defined as a complex input for valid
          gis data.

        We treat layer destination the same as input since they refer to
        layers ids in qgisProject
    """
    if isinstance(param, INPUT_LAYER_TYPES):
        typ = param.type()

        if typ == 'multilayer':
            num_inputs = param.minimumNumberInputs()
            kwargs['min_occurs'] = num_inputs if num_inputs >= 1 else 0
            kwargs['max_occurs'] = kwargs['min_occurs']

        # Set metadata for geometry type
        datatypes = get_layers_type(param, kwargs)

        kwargs['data_type'] = 'string'

        if context is not None:
            # Retrieve the list of layers
            # Inputs will be a list of strings from the source
            # project
            get_layers_from_context(kwargs, context, datatypes)
            # Set max occurs accordingly
            if typ == 'multilayer':
                kwargs['max_occurs'] = len(kwargs['allowed_values'])
        return LiteralInput(**kwargs)

    elif isinstance(param, DESTINATION_LAYER_TYPES):
        # Since QgsProcessingOutputLayerDefinition may
        # be defined as default value, get extension
        # and layer name from it
        extension, defval = get_default_destination_values(
            param, kwargs['default'])
        kwargs['default'] = defval

        kwargs['data_type'] = 'string'
        # Used to retrieve extension when handling wps response
        kwargs['metadata'].append(Metadata('processing:extension', extension))
        if isinstance(param, DESTINATION_VECTOR_LAYER_TYPES):
            kwargs['metadata'].append(
                Metadata('processing:dataType', str(param.dataType())))
        return LiteralInput(**kwargs)

    else:
        return None
예제 #5
0
    def get_processes(self):
        def pr1():
            pass

        def pr2():
            pass

        return [
            WPSProcess(pr1,
                       'pr1',
                       'Process 1',
                       metadata=[Metadata('pr1 metadata')]),
            WPSProcess(pr2,
                       'pr2',
                       'Process 2',
                       metadata=[Metadata('pr2 metadata')])
        ]
예제 #6
0
def parse_input_definition(param: QgsProcessingParameterDefinition,
                           alg: QgsProcessingAlgorithm = None,
                           context: MapContext = None) -> WPSInput:
    """ Create WPS input from QgsProcessingParamDefinition
the description is used in QGIS UI as the title in WPS.
        see https://qgis.org/api/qgsprocessingparameters_8h_source.html#l01312
    """
    kwargs = {
        'identifier': param.name(),
        'title': param.description() or param.name().replace('_', ' '),
        'abstract': param.help(),
        'metadata': [
            Metadata('processing:type', param.type()),
        ]
    }

    # Handle defaultValue
    # XXX In some case QVariant are
    # not converted to python object (SIP bug ?)
    # Problem stated in getting QgsProcessingParameterFeatureSource
    # from processing.core.parameters.getParameterFromString
    defaultValue = param.defaultValue()
    if isinstance(defaultValue, QVariant):
        defaultValue = None if defaultValue.isNull() else defaultValue.value()

    kwargs['default'] = defaultValue

    # Check for optional flags
    if _is_optional(param):
        kwargs['min_occurs'] = 0

    inp = parse_literal_input(param,kwargs) \
        or layersio.parse_input_definition(param, kwargs, context) \
        or geometryio.parse_input_definition(param, kwargs, context) \
        or filesio.parse_input_definition(param, kwargs) \
        or datetimeio.parse_input_definition(param, kwargs)
    if inp is None:
        raise ProcessingInputTypeNotSupported("%s:'%s'" %
                                              (type(param), param.type()))

    parse_metadata(param, kwargs)

    return inp
예제 #7
0
def get_layers_type(param: QgsProcessingParameterDefinition, kwargs) -> None:
    """ Set datatype as metadata
    """
    datatypes = []
    if isinstance(param, QgsProcessingParameterLimitedDataTypes):
        datatypes = param.dataTypes()

    if not datatypes:
        if isinstance(param, INPUT_VECTOR_LAYER_TYPES):
            datatypes = [QgsProcessing.TypeVector]
        elif isinstance(param, INPUT_RASTER_LAYER_TYPES):
            datatypes = [QgsProcessing.TypeRaster]
        elif isinstance(param, QgsProcessingParameterMultipleLayers):
            datatypes = [param.layerType()]
        elif isinstance(param, QgsProcessingParameterMeshLayer):
            datatypes = [QgsProcessing.TypeMesh]
        else:
            datatypes = [QgsProcessing.TypeMapLayer]

    kwargs['metadata'].append(
        Metadata('processing:dataTypes',
                 ','.join(SourceTypes[dtyp] for dtyp in datatypes)))

    return datatypes
예제 #8
0
def parse_literal_input(param: QgsProcessingParameterDefinition,
                        kwargs) -> LiteralInput:
    """ Convert processing input to Literal Input 
    """
    typ = param.type()

    if typ == 'string':
        kwargs['data_type'] = 'string'
    elif typ == 'boolean':
        kwargs['data_type'] = 'boolean'
    elif typ == 'enum':
        options = param.options()
        kwargs['data_type'] = 'string'
        kwargs['allowed_values'] = options
        kwargs['max_occurs'] = len(options) if param.allowMultiple() else 1
        default_value = param.defaultValue()
        if default_value is not None:
            # XXX Values for processing enum are indices
            if isinstance(default_value, list):
                default_value = default_value[0]
            if not isinstance(default_value, int):
                raise InvalidParameterValue(
                    'Unsupported default value for parameter %s: %s' %
                    (param.name(), default_value))
            if default_value < 0 or default_value >= len(options):
                LOGGER.error(
                    "Out of range default value for enum parameter %s: %s",
                    param.name(), default_value)
                default_value = 0

            kwargs['default'] = options[default_value]

    elif typ == 'number':
        kwargs['data_type'] = _number_data_type(param)
        kwargs['allowed_values'] = [(param.minimum(), param.maximum())]
    elif typ == 'distance':
        kwargs['data_type'] = 'length'
        kwargs['allowed_values'] = [(param.minimum(), param.maximum())]
        kwargs['metadata'].extend((
            Metadata('processing:parentParameterName',
                     param.parentParameterName()),
            Metadata('processing:defaultUnit',
                     QgsUnitTypes.toString(param.defaultUnit())),
        ))
    elif typ == 'scale':
        kwargs['data_type'] = 'scale'
        kwargs['allowed_values'] = [(param.minimum(), param.maximum())]
    elif typ == 'duration':
        # XXX OGC duration is defined as time dataType
        kwargs['data_type'] = 'time'
        kwargs['allowed_values'] = [(param.minimum(), param.maximum())]
        kwargs['metadata'].append(
            Metadata('processing:defaultUnit',
                     QgsUnitTypes.toString(param.defaultUnit())), )
    elif typ == 'field':
        kwargs['data_type'] = 'string'
        kwargs['metadata'].append(
            Metadata('processing:parentLayerParameterName',
                     param.parentLayerParameterName()))
        kwargs['metadata'].append(
            Metadata(
                'processing:dataType', {
                    QgsProcessingParameterField.Any: 'Any',
                    QgsProcessingParameterField.Numeric: 'Numeric',
                    QgsProcessingParameterField.String: 'String',
                    QgsProcessingParameterField.DateTime: 'DateTime',
                }[param.dataType()]))
    elif typ == 'band':
        kwargs['data_type'] = 'nonNegativeInteger'
    else:
        return None

    return LiteralInput(**kwargs)
예제 #9
0
def parse_metadata(param: QgsProcessingParameterDefinition, kwargs) -> None:
    """ Parse freeform metadata
    """
    kwargs['metadata'].extend(
        Metadata('processing:meta:%s' % k, str(v))
        for k, v in param.metadata().items())