|
1 | | -import logging |
| 1 | +import sys |
2 | 2 | from typing import Optional |
3 | 3 |
|
4 | | -from qgis.analysis import QgsNativeAlgorithms, QgsPdalAlgorithms |
5 | | -from qgis.core import Qgis, QgsApplication, QgsProviderRegistry |
6 | | -from qgis.processing import ProcessingAlgFactory |
| 4 | +from qgis.analysis import QgsNativeAlgorithms |
| 5 | +from qgis.core import ( |
| 6 | + Qgis, |
| 7 | + QgsApplication, |
| 8 | + QgsProcessingAlgorithm, |
| 9 | + QgsProcessingContext, |
| 10 | + QgsProcessingFeedback, |
| 11 | + QgsProcessingOutputBoolean, |
| 12 | + QgsProcessingOutputDefinition, |
| 13 | + QgsProcessingOutputNumber, |
| 14 | + QgsProcessingOutputRasterLayer, |
| 15 | + QgsProcessingOutputString, |
| 16 | + QgsProcessingOutputVectorLayer, |
| 17 | + QgsProcessingParameterBand, |
| 18 | + QgsProcessingParameterBoolean, |
| 19 | + QgsProcessingParameterDefinition, |
| 20 | + QgsProcessingParameterEnum, |
| 21 | + QgsProcessingParameterExtent, |
| 22 | + QgsProcessingParameterFeatureSink, |
| 23 | + QgsProcessingParameterFeatureSource, |
| 24 | + QgsProcessingParameterField, |
| 25 | + QgsProcessingParameterMapTheme, |
| 26 | + QgsProcessingParameterMultipleLayers, |
| 27 | + QgsProcessingParameterNumber, |
| 28 | + QgsProcessingParameterRasterDestination, |
| 29 | + QgsProcessingParameterRasterLayer, |
| 30 | + QgsProcessingParameterString, |
| 31 | +) |
7 | 32 |
|
8 | | -from qgis_server_light.interface.job.common.input import QslJobInfoParameter |
| 33 | +from qgis_server_light.interface.exporter.extract import ( |
| 34 | + Algorithm, |
| 35 | + Output, |
| 36 | + Parameter, |
| 37 | + Process, |
| 38 | +) |
| 39 | +from qgis_server_light.interface.job.common.input import QslJobLayer |
| 40 | +from qgis_server_light.interface.job.common.output import JobResult |
| 41 | +from qgis_server_light.interface.job.process.input import ( |
| 42 | + QslJobInfoExecuteProcess, |
| 43 | + QslJobParameterExecuteProcess, |
| 44 | +) |
9 | 45 | from qgis_server_light.worker.runner.common import JobContext, MapRunner |
10 | 46 |
|
11 | 47 |
|
| 48 | +def parameter_from_qgs_definition(param: QgsProcessingParameterDefinition) -> Parameter: |
| 49 | + if isinstance(param, QgsProcessingParameterFeatureSource): |
| 50 | + schema = {"type": "string"} |
| 51 | + elif isinstance(param, QgsProcessingParameterRasterLayer): |
| 52 | + schema = {"type": "string"} |
| 53 | + elif isinstance(param, QgsProcessingParameterFeatureSink): |
| 54 | + schema = {"type": "string"} |
| 55 | + elif isinstance(param, QgsProcessingParameterMultipleLayers): |
| 56 | + schema = {"type": "array", "items": {"type": "string"}} |
| 57 | + if (min_items := param.minimumNumberInputs()) >= 1: |
| 58 | + schema["minItems"] = min_items |
| 59 | + elif isinstance(param, QgsProcessingParameterRasterDestination): |
| 60 | + schema = {"type": "string"} |
| 61 | + elif isinstance(param, QgsProcessingParameterBand): |
| 62 | + schema = {"type": "integer", "minimum": 1} |
| 63 | + if param.allowMultiple(): |
| 64 | + schema = {"type": "array", "minItems": 1, "items": schema} |
| 65 | + elif isinstance(param, QgsProcessingParameterNumber): |
| 66 | + match param.dataType(): |
| 67 | + case Qgis.ProcessingNumberParameterType.Double: |
| 68 | + schema = {"type": "number"} |
| 69 | + case Qgis.ProcessingNumberParameterType.Integer: |
| 70 | + schema = {"type": "integer"} |
| 71 | + if (maximum := param.maximum()) < sys.float_info.max: |
| 72 | + schema["maximum"] = maximum |
| 73 | + if (minimum := param.minimum()) > sys.float_info.min: |
| 74 | + schema["minimum"] = minimum |
| 75 | + elif isinstance(param, QgsProcessingParameterString): |
| 76 | + schema = {"type": "string"} |
| 77 | + elif isinstance(param, QgsProcessingParameterField): |
| 78 | + schema = {"type": "string"} |
| 79 | + if param.allowMultiple(): |
| 80 | + schema = {"type": "array", "minItems": 1, "items": schema} |
| 81 | + elif isinstance(param, QgsProcessingParameterEnum): |
| 82 | + schema = {"type": "string", "enum": param.options()} |
| 83 | + elif isinstance(param, QgsProcessingParameterBoolean): |
| 84 | + schema = {"type": "boolean"} |
| 85 | + elif isinstance(param, QgsProcessingParameterExtent): |
| 86 | + schema = { |
| 87 | + "oneOf": [ |
| 88 | + { |
| 89 | + "type": "array", |
| 90 | + "items": {"type": "number"}, |
| 91 | + "minItems": 4, |
| 92 | + "maxItems": 4, |
| 93 | + }, |
| 94 | + { |
| 95 | + "type": "array", |
| 96 | + "items": {"type": "number"}, |
| 97 | + "minItems": 6, |
| 98 | + "maxItems": 6, |
| 99 | + }, |
| 100 | + ] |
| 101 | + } |
| 102 | + elif isinstance(param, QgsProcessingParameterMapTheme): |
| 103 | + schema = {"type": "string"} |
| 104 | + else: |
| 105 | + print(f"parameter: {param}") |
| 106 | + raise NotImplementedError(f"parameter: {param}") |
| 107 | + |
| 108 | + return Parameter( |
| 109 | + name=param.name(), |
| 110 | + type=param.type(), |
| 111 | + description=param.description(), |
| 112 | + schema=schema, |
| 113 | + optional=bool(param.flags() & Qgis.ProcessingParameterFlag.Optional), |
| 114 | + default=param.defaultValue(), |
| 115 | + ) |
| 116 | + |
| 117 | + |
| 118 | +def output_from_qgs_definition(output: QgsProcessingOutputDefinition) -> Output: |
| 119 | + if isinstance(output, QgsProcessingOutputVectorLayer): |
| 120 | + schema = {"type": "string"} |
| 121 | + elif isinstance(output, QgsProcessingOutputRasterLayer): |
| 122 | + schema = {"type": "string"} |
| 123 | + elif isinstance(output, QgsProcessingOutputNumber): |
| 124 | + schema = {"type": "number"} |
| 125 | + elif isinstance(output, QgsProcessingOutputString): |
| 126 | + schema = {"type": "string"} |
| 127 | + elif isinstance(output, QgsProcessingOutputBoolean): |
| 128 | + schema = {"type": "boolean"} |
| 129 | + else: |
| 130 | + print(f"output: {output}") |
| 131 | + raise NotImplementedError(f"output: {output}") |
| 132 | + return Output( |
| 133 | + name=output.name(), |
| 134 | + type=output.type(), |
| 135 | + description=output.description(), |
| 136 | + schema=schema, |
| 137 | + ) |
| 138 | + |
| 139 | + |
| 140 | +def algorithm_from_qgs_definition(alg: QgsProcessingAlgorithm) -> Algorithm: |
| 141 | + algorithm = Algorithm( |
| 142 | + id=alg.id(), |
| 143 | + name=alg.name(), |
| 144 | + display_name=alg.displayName(), |
| 145 | + help_string=alg.helpString(), |
| 146 | + ) |
| 147 | + for param in alg.parameterDefinitions(): |
| 148 | + algorithm.parameters.append(parameter_from_qgs_definition(param)) |
| 149 | + for output in alg.outputDefinitions(): |
| 150 | + algorithm.outputs.append(output_from_qgs_definition(output)) |
| 151 | + return algorithm |
| 152 | + |
| 153 | + |
12 | 154 | class ProcessRunner(MapRunner): |
| 155 | + job_info_class = QslJobInfoExecuteProcess |
| 156 | + |
13 | 157 | def __init__( |
14 | 158 | self, |
15 | 159 | qgis: QgsApplication, |
16 | 160 | context: JobContext, |
17 | | - job_info: QslJobInfoParameter, |
| 161 | + job_info: QslJobInfoExecuteProcess, |
18 | 162 | layer_cache: Optional[dict], |
19 | 163 | ): |
20 | 164 | super().__init__(qgis, context, job_info, layer_cache) |
| 165 | + self.registry = self.qgis.processingRegistry() |
| 166 | + self.registry.addProvider(QgsNativeAlgorithms()) |
| 167 | + |
| 168 | + @classmethod |
| 169 | + def info(cls, qgis: Qgis) -> Process: |
| 170 | + registry = qgis.processingRegistry() |
| 171 | + algorithms = registry.algorithms() |
| 172 | + process = Process() |
| 173 | + for alg in algorithms: |
| 174 | + algorithm = algorithm_from_qgs_definition(alg) |
| 175 | + process.algorithms.append(algorithm) |
| 176 | + return process |
| 177 | + |
| 178 | + def run(self): |
| 179 | + job: QslJobParameterExecuteProcess = self.job_info.job |
| 180 | + algorithm = self.registry.algorithmById(job.process_id) |
| 181 | + if algorithm is None: |
| 182 | + return JobResult( |
| 183 | + id=self.job_info.id, |
| 184 | + data={"result": {}, "ok": False, "log": "Algorithm not found"}, |
| 185 | + content_type="application/json", |
| 186 | + ) |
21 | 187 |
|
22 | | - ProcessingAlgFactory() |
23 | | - providers = QgsProviderRegistry.instance().pluginList().split("\n") |
24 | | - logging.info("Found Providers:") |
25 | | - for provider in providers: |
26 | | - logging.info(f" - {provider}") |
| 188 | + for param, value in job.parameters.items(): |
| 189 | + if isinstance(value, QslJobLayer): |
| 190 | + job.parameters[param] = self._handle_layer_cache(value) |
27 | 191 |
|
28 | | - def load_providers(self, qgis: Qgis): |
29 | | - qgis.processingRegistry().addProvider(QgsNativeAlgorithms()) |
30 | | - qgis.processingRegistry().addProvider(QgsPdalAlgorithms()) |
| 192 | + context = QgsProcessingContext() |
| 193 | + feedback = QgsProcessingFeedback() |
| 194 | + result, ok = algorithm.run(job.parameters, context, feedback) |
| 195 | + return JobResult( |
| 196 | + id=self.job_info.id, |
| 197 | + data={"result": result, "ok": ok, "log": feedback.textLog()}, |
| 198 | + content_type="application/json", |
| 199 | + ) |
0 commit comments