diff --git a/src/caosdb/apiutils.py b/src/caosdb/apiutils.py index 516603fceab1861100825a3d3eb9e0e0c94af56f..297a11f0cabffd3cbf6ed06f2e246fcb5b8577aa 100644 --- a/src/caosdb/apiutils.py +++ b/src/caosdb/apiutils.py @@ -720,10 +720,55 @@ def copy_entity(entity: Entity): return new +def merge_entities(entity_a: Entity, entity_b: Entity): + """ + Merge entity_b into entity_a such that they have the same parents and properties. + """ + + # Compare both entities: + diff_r1, diff_r2 = compare_entities(entity_a, entity_b) + + # Go through the comparison and try to apply changes to entity_a: + for key in diff_r2["parents"]: + entity_a.add_parent(entity_b.get_parent(key)) + + for key in diff_r2["properties"]: + if key in diff_r1["properties"]: + if ("importance" in diff_r1["properties"][key] and + "importance" in diff_r2["properties"][key]): + if (diff_r1["properties"][key]["importance"] != + diff_r2["properties"][key]["importance"]): + raise NotImplementedError() + elif ("importance" in diff_r1["properties"][key] or + "importance" in diff_r2["properties"][key]): + raise NotImplementedError() + + for attribute in ("datatype", "unit", "value"): + if diff_r1["properties"][key][attribute] is None: + setattr(entity_a.get_property(key), attribute, + diff_r2["properties"][key][attribute]) + else: + raise RuntimeError("Merge conflict.") + else: + entity_a.add_property( + entity_b.get_property(key), + importance=entity_b.get_importance(key)) + + for special_attribute in ("name", "description"): + sa_a = getattr(entity_a, special_attribute) + sa_b = getattr(entity_b, special_attribute) + if sa_a != sa_b: + if sa_a is None: + setattr(entity_a, special_attribute, sa_b) + else: + raise RuntimeError("Merge conflict.") + return entity_a + + def describe_diff(olddiff, newdiff, name=None, as_update=True): description = "" - for attr in list(set(list(olddiff.keys())+list(newdiff.keys()))): + for attr in list(set(list(olddiff.keys()) + list(newdiff.keys()))): if attr == "parents" or attr == "properties": continue description += "{} differs:\n".format(attr)