Skip to content
Snippets Groups Projects

F merge id with resolved entity

Merged Florian Spreckelsen requested to merge f-merge-id-with-resolved-entity into dev
1 unresolved thread
3 files
+ 103
16
Compare changes
  • Side-by-side
  • Inline

Files

+ 53
16
@@ -354,7 +354,7 @@ def empty_diff(old_entity: Entity, new_entity: Entity, compare_referenced_record
@@ -354,7 +354,7 @@ def empty_diff(old_entity: Entity, new_entity: Entity, compare_referenced_record
def merge_entities(entity_a: Entity, entity_b: Entity, merge_references_with_empty_diffs=True,
def merge_entities(entity_a: Entity, entity_b: Entity, merge_references_with_empty_diffs=True,
force=False):
force=False, merge_id_with_resolved_entity: bool = False):
"""Merge entity_b into entity_a such that they have the same parents and properties.
"""Merge entity_b into entity_a such that they have the same parents and properties.
datatype, unit, value, name and description will only be changed in entity_a
datatype, unit, value, name and description will only be changed in entity_a
@@ -372,16 +372,22 @@ def merge_entities(entity_a: Entity, entity_b: Entity, merge_references_with_emp
@@ -372,16 +372,22 @@ def merge_entities(entity_a: Entity, entity_b: Entity, merge_references_with_emp
Parameters
Parameters
----------
----------
entity_a, entity_b : Entity
entity_a, entity_b : Entity
The entities to be merged. entity_b will be merged into entity_a in place
The entities to be merged. entity_b will be merged into entity_a in place
merge_references_with_empty_diffs : bool, optional
merge_references_with_empty_diffs : bool, optional
Whether the merge is performed if entity_a and entity_b both reference
Whether the merge is performed if entity_a and entity_b both reference
record(s) that may be different Python objects but have empty diffs. If
record(s) that may be different Python objects but have empty diffs. If
set to `False` a merge conflict will be raised in this case
set to `False` a merge conflict will be raised in this case
instead. Default is True.
instead. Default is True.
force : bool, optional
force : bool, optional
If True, in case `entity_a` and `entity_b` have the same properties, the
If True, in case `entity_a` and `entity_b` have the same properties, the
values of `entity_a` are replaced by those of `entity_b` in the merge.
values of `entity_a` are replaced by those of `entity_b` in the
If `False`, an EntityMergeConflictError is raised instead. Default is False.
merge. If `False`, an EntityMergeConflictError is raised
 
instead. Default is False.
 
merge_id_with_resolved_entity : bool, optional
 
If true, the values of two reference properties will be considered the
 
same if one is an integer id and the other is a db.Entity with this
 
id. I.e., a value 123 is identified with a value ``<Record
 
id=123/>``. Default is False.
Returns
Returns
-------
-------
@@ -427,13 +433,31 @@ def merge_entities(entity_a: Entity, entity_b: Entity, merge_references_with_emp
@@ -427,13 +433,31 @@ def merge_entities(entity_a: Entity, entity_b: Entity, merge_references_with_emp
setattr(entity_a.get_property(key), attribute,
setattr(entity_a.get_property(key), attribute,
diff_r2["properties"][key][attribute])
diff_r2["properties"][key][attribute])
else:
else:
raise EntityMergeConflictError(
raise_error = True
f"Entity a ({entity_a.id}, {entity_a.name}) "
if merge_id_with_resolved_entity is True and attribute == "value":
f"has a Property '{key}' with {attribute}="
# Do a special check for the case of an id value on the
f"{diff_r2['properties'][key][attribute]}\n"
# one hand, and a resolved entity on the other side.
f"Entity b ({entity_b.id}, {entity_b.name}) "
this = entity_a.get_property(key).value
f"has a Property '{key}' with {attribute}="
that = entity_b.get_property(key).value
f"{diff_r1['properties'][key][attribute]}")
same = False
 
if isinstance(this, list) and isinstance(that, list):
 
if len(this) == len(that):
 
same = all([_same_id_as_resolved_entity(a, b)
 
for a, b in zip(this, that)])
 
else:
 
same = _same_id_as_resolved_entity(this, that)
 
if same is True:
 
setattr(entity_a.get_property(key), attribute,
 
diff_r2["properties"][key][attribute])
 
raise_error = False
 
if raise_error is True:
 
raise EntityMergeConflictError(
 
f"Entity a ({entity_a.id}, {entity_a.name}) "
 
f"has a Property '{key}' with {attribute}="
 
f"{diff_r2['properties'][key][attribute]}\n"
 
f"Entity b ({entity_b.id}, {entity_b.name}) "
 
f"has a Property '{key}' with {attribute}="
 
f"{diff_r1['properties'][key][attribute]}")
else:
else:
# TODO: This is a temporary FIX for
# TODO: This is a temporary FIX for
# https://gitlab.indiscale.com/caosdb/src/caosdb-pylib/-/issues/105
# https://gitlab.indiscale.com/caosdb/src/caosdb-pylib/-/issues/105
@@ -586,3 +610,16 @@ def create_flat_list(ent_list: List[Entity], flat: List[Entity]):
@@ -586,3 +610,16 @@ def create_flat_list(ent_list: List[Entity], flat: List[Entity]):
flat.append(p.value)
flat.append(p.value)
# TODO: move inside if block?
# TODO: move inside if block?
create_flat_list([p.value], flat)
create_flat_list([p.value], flat)
 
 
 
def _same_id_as_resolved_entity(this, that):
 
"""Checks whether ``this`` and ``that`` either are the same or whether one
 
is an id and the other is a db.Entity with this id.
 
 
"""
 
if isinstance(this, Entity) and not isinstance(that, Entity):
Please register or sign in to reply
 
# this is an Entity with an id, that is not
 
return this.id is not None and this.id == that
 
if not isinstance(this, Entity) and isinstance(that, Entity):
 
return that.id is not None and that.id == this
 
return this == that
Loading