diff --git a/docker-qgis/apply_deltas.py b/docker-qgis/apply_deltas.py index 05b5947f3..00b6b5107 100755 --- a/docker-qgis/apply_deltas.py +++ b/docker-qgis/apply_deltas.py @@ -162,11 +162,19 @@ def __init__( self.descr = descr +class FeatureNotFoundError(Exception): + ... + + +class DoublicateFeatureError(Exception): + ... + + # /EXCEPTION DEFINITIONS BACKUP_SUFFIX = ".qfieldcloudbackup" -delta_log = [] +DELTA_LOG = [] def project_decorator(f): @@ -254,7 +262,7 @@ def delta_apply( inverse: bool, overwrite_conflicts: bool, ): - del delta_log[:] + DELTA_LOG.clear() project = QgsProject.instance() logging.info(f'Loading project file "{project_filename}"...') @@ -275,8 +283,8 @@ def delta_apply( if not all_applied: logger.info("Some deltas have not been applied") - delta_log_copy = [*delta_log] - del delta_log[:] + delta_log_copy = [*DELTA_LOG] + DELTA_LOG.clear() return delta_log_copy @@ -288,7 +296,7 @@ def cmd_delta_apply(project: QgsProject, opts: DeltaOptions) -> bool: has_uncaught_errors = False try: - del delta_log[:] + del DELTA_LOG[:] deltas = load_delta_file(opts) if opts["transaction"]: @@ -329,12 +337,12 @@ def cmd_delta_apply(project: QgsProject, opts: DeltaOptions) -> bool: ) print("Delta log file contents:") print("========================") - print(json.dumps(delta_log, indent=2, sort_keys=True, default=str)) + print(json.dumps(DELTA_LOG, indent=2, sort_keys=True, default=str)) print("========================") if opts.get("delta_log"): with open(opts["delta_log"], "w") as f: - json.dump(delta_log, f, indent=2, sort_keys=True, default=str) + json.dump(DELTA_LOG, f, indent=2, sort_keys=True, default=str) return has_uncaught_errors @@ -592,7 +600,7 @@ def committed_features_added_cb(layer_id, features): f'The returned modified feature is invalid in "{layer_id}"' ) - delta_log.append( + DELTA_LOG.append( { "msg": "Successfully applied delta!", "status": delta_status, @@ -628,7 +636,7 @@ def committed_features_added_cb(layer_id, features): logger.error(f'Failed to rollback layer "{layer_id}": {err}') has_applied_all_deltas = False - delta_log.append( + DELTA_LOG.append( { "msg": str(err), "status": delta_status, @@ -646,7 +654,7 @@ def committed_features_added_cb(layer_id, features): ) except Exception as err: delta_status = DeltaStatus.UnknownError - delta_log.append( + DELTA_LOG.append( { "msg": str(err), "status": delta_status, @@ -1028,16 +1036,14 @@ def get_feature( QgsExpression.quotedValue(source_pk), ) - feature = QgsFeature() - has_feature = False - for f in layer.getFeatures(expr): - if has_feature: - raise Exception("More than one feature match the feature select query") - - feature = f - has_feature = True - - return feature + features = list(layer.getFeatures(expr)) + if not features: + raise FeatureNotFoundError(f"Could not find feature source_pk={source_pk}") + if len(features) < 1: + raise DoublicateFeatureError( + f"More than one feature match the feature select query source_pk={source_pk}" + ) + return features[0] def create_feature( @@ -1112,10 +1118,10 @@ def patch_feature( """ new_feature_delta = delta["new"] old_feature_delta = delta["old"] - old_feature = get_feature(layer, delta, client_pks) - - if not old_feature.isValid(): - raise DeltaException("Unable to find feature") + try: + old_feature = get_feature(layer, delta, client_pks) + except (FeatureNotFoundError, DoublicateFeatureError) as exc: + raise DeltaException("Could not get feature", method=delta["method"]) from exc conflicts = compare_feature(old_feature, old_feature_delta, True) @@ -1198,10 +1204,10 @@ def delete_feature( DeltaException: whenever the feature cannot be deleted """ old_feature_delta = delta["old"] - old_feature = get_feature(layer, delta, client_pks) - - if not old_feature.isValid(): - raise DeltaException("Unable to find feature") + try: + old_feature = get_feature(layer, delta, client_pks) + except (FeatureNotFoundError, DoublicateFeatureError) as exc: + raise DeltaException("Could not get feature", method=delta["method"]) from exc conflicts = compare_feature(old_feature, old_feature_delta) @@ -1302,7 +1308,7 @@ def get_backup_path(path: Path) -> Path: Returns: Path -- suffixed path """ - return Path(str(path) + BACKUP_SUFFIX) + return path.with_suffix(BACKUP_SUFFIX) def is_layer_file_based(layer: QgsMapLayer) -> bool: