diff --git a/src/cal_tools/tools.py b/src/cal_tools/tools.py index 0760d48a70145ab5ae5237a8a9088e8290af624c..e0eb543da3838af1a09ff985084a93236f726c40 100644 --- a/src/cal_tools/tools.py +++ b/src/cal_tools/tools.py @@ -813,13 +813,23 @@ def module_index_to_qm(index: int, total_modules: int = 16): def recursive_update(target: dict, source: dict): + """Recursively merge source into target, checking for conflicts + + Conflicting entries will not be copied to target. Returns True if any + conflicts were found. + """ + conflict = False for k, v2 in source.items(): v1 = target.get(k, None) if isinstance(v1, dict) and isinstance(v2, dict): - recursive_update(v1, v2) + conflict = recursive_update(v1, v2) or conflict + elif (v1 is not None) and (v1 != v2): + conflict = True else: target[k] = v2 + return conflict + class CalibrationMetadata(dict): """Convenience class: dictionary stored in metadata YAML file @@ -868,14 +878,19 @@ class CalibrationMetadata(dict): def gather_fragments(self): """Merge in fragments saved by add_fragment(), then delete them""" frag_files = list(self._yaml_fn.parent.glob('metadata_frag_*.yml')) + to_delete = [] for fn in frag_files: with fn.open("r") as fd: data = yaml.safe_load(fd) - recursive_update(self, data) + if recursive_update(self, data): + print(f"{fn} contained conflicting metadata. " + f"This file will be left for debugging") + else: + to_delete.append(fn) self.save() - for fn in frag_files: + for fn in to_delete: fn.unlink()