From f948f7ea7b7a960ee2870cc93b0435d95511b007 Mon Sep 17 00:00:00 2001 From: Ivan Ivanov Date: Wed, 13 Mar 2024 10:21:17 +0200 Subject: [PATCH] Reduce the code duplication about project loading --- docker-qgis/entrypoint.py | 48 +++++---------------------------- docker-qgis/qfc_worker/utils.py | 32 +++++++++++++++++++--- 2 files changed, 35 insertions(+), 45 deletions(-) diff --git a/docker-qgis/entrypoint.py b/docker-qgis/entrypoint.py index 9e2b22c77..f80ecd791 100755 --- a/docker-qgis/entrypoint.py +++ b/docker-qgis/entrypoint.py @@ -11,7 +11,6 @@ from libqfieldsync.offline_converter import ExportType, OfflineConverter from libqfieldsync.offliners import OfflinerType, PythonMiniOffliner, QgisCoreOffliner from libqfieldsync.project import ProjectConfiguration -from libqfieldsync.utils.bad_layer_handler import set_bad_layer_handler from libqfieldsync.utils.file_utils import get_project_in_folder from qfc_worker.utils import ( Step, @@ -20,8 +19,9 @@ Workflow, get_layers_data, layers_data_to_string, + open_qgis_project, ) -from qgis.core import QgsCoordinateTransform, QgsProject, QgsRectangle, QgsVectorLayer +from qgis.core import QgsCoordinateTransform, QgsRectangle, QgsVectorLayer PGSERVICE_FILE_CONTENTS = os.environ.get("PGSERVICE_FILE_CONTENTS") @@ -35,17 +35,7 @@ def _call_libqfieldsync_packager( """Call `libqfieldsync` to package a project for QField""" logger.info("Preparing QGIS project for packaging…") - if not project_filename.exists(): - raise FileNotFoundError(project_filename) - - project = QgsProject.instance() - - project_filename_string = str(project_filename) - if project.fileName() != project_filename_string: - with set_bad_layer_handler(project): - if not project.read(project_filename_string): - project.setFileName("") - raise Exception(f"Unable to open file with QGIS: {project_filename}") + project = open_qgis_project(str(project_filename)) layers = project.mapLayers() project_config = ProjectConfiguration(project) @@ -146,14 +136,7 @@ def _call_libqfieldsync_packager( def _extract_layer_data(project_filename: Union[str, Path]) -> dict: logger.info("Extracting QGIS project layer data…") - project = QgsProject.instance() - - if project.fileName() != str(project_filename): - with set_bad_layer_handler(project): - if not project.read(str(project_filename)): - project.setFileName("") - raise Exception(f"Unable to open file with QGIS: {project_filename}") - + project = open_qgis_project(str(project_filename)) layers_by_id: dict = get_layers_data(project) logger.info( @@ -164,16 +147,7 @@ def _extract_layer_data(project_filename: Union[str, Path]) -> dict: def _open_project(project_filename: Union[str, Path]): - logger.info("Loading QGIS project…") - - project = QgsProject.instance() - - with set_bad_layer_handler(project): - if not project.read(str(project_filename)): - project.setFileName("") - raise Exception(f"Unable to open project with QGIS: {project_filename}") - - logger.info("Project loaded.") + open_qgis_project(str(project_filename), force_reload=True) def cmd_package_project(args: argparse.Namespace): @@ -199,17 +173,9 @@ def cmd_package_project(args: argparse.Namespace): method=qfc_worker.utils.download_project, return_names=["tmp_project_dir"], ), - Step( - id="qgis_open_project", - name="Open Project", - arguments={ - "project_filename": WorkDirPath("files", args.project_file), - }, - method=_open_project, - ), Step( id="qgis_layers_data", - name="Original Project Layers Data", + name="QGIS Layers Data", arguments={ "project_filename": WorkDirPath("files", args.project_file), }, @@ -230,7 +196,7 @@ def cmd_package_project(args: argparse.Namespace): ), Step( id="qfield_layer_data", - name="Packaged Project Layers Data", + name="Packaged Layers Data", arguments={ "project_filename": StepOutput( "package_project", "qfield_project_filename" diff --git a/docker-qgis/qfc_worker/utils.py b/docker-qgis/qfc_worker/utils.py index ff9a949ef..f948c0236 100644 --- a/docker-qgis/qfc_worker/utils.py +++ b/docker-qgis/qfc_worker/utils.py @@ -18,7 +18,7 @@ from typing import IO, Any, Callable, NamedTuple, Optional from libqfieldsync.layer import LayerSource -from libqfieldsync.utils.bad_layer_handler import bad_layer_handler +from libqfieldsync.utils.bad_layer_handler import set_bad_layer_handler from qfieldcloud_sdk import sdk from qgis.core import ( Qgis, @@ -182,9 +182,6 @@ def exitQgis(): logging.info("QGIS app started!") - # we set the `bad_layer_handler` and assume we always have only one single `QgsProject` instance within the job's life - QgsProject.instance().setBadLayerHandler(bad_layer_handler) - return QGISAPP @@ -206,6 +203,33 @@ def stop_app(): del QGISAPP +def open_qgis_project(project_filename: str, force_reload: bool = False) -> QgsProject: + logging.info(f'Loading QGIS project "{project_filename}"…') + + if not Path(project_filename).exists(): + raise FileNotFoundError(project_filename) + + project = QgsProject.instance() + + if project.fileName() == str(project_filename) and not force_reload: + logging.info( + f'Skip loading QGIS project "{project_filename}", it is already loaded' + ) + return project + + with set_bad_layer_handler(project): + if not project.read(str(project_filename)): + logging.error(f'Failed to load QGIS project "{project_filename}"!') + + project.setFileName("") + + raise Exception(f"Unable to open project with QGIS: {project_filename}") + + logging.info("Project loaded.") + + return project + + def download_project( project_id: str, destination: Path = None, skip_attachments: bool = True ) -> Path: