linkahead.apiutils module

API-Utils: Some simplified functions for generation of records etc.

exception linkahead.apiutils.EntityMergeConflictError(msg)

Bases: LinkAheadException

An error that is raised in case of an unresolvable conflict when merging two entities.

linkahead.apiutils.apply_to_ids(entities, func)

Apply a function to all ids.

All ids means the ids of the entities themselves but also to all parents, properties and referenced entities.

Parameters:
  • entities (list of Entity)

  • func (function with one parameter.)

linkahead.apiutils.compare_entities(entity0: Entity | None = None, entity1: Entity | None = None, compare_referenced_records: bool = False, entity_name_id_equivalency: bool = False, old_entity: Entity | None = None, new_entity: Entity | None = None) tuple[dict[str, Any], dict[str, Any]]

Compare two entities.

Returns two dicts listing the differences between the two entities. The order of the two returned dicts corresponds to the two input entities. The dicts contain two keys, ‘parents’ and ‘properties’. The list saved under the ‘parents’ key contains those parents of the respective entity that are missing in the other entity, and the ‘properties’ dict contains properties and SPECIAL_ATTRIBUTES if they are missing or different from their counterparts in the other entity.

The value of the properties dict for each listed property is again a dict detailing the differences between this property and its counterpart. The characteristics that are checked to determine whether two properties match are the following:

  • datatype

  • importance

  • value

If any of these characteristics differ for a property, the respective string (datatype, importance, value) is added as a key to the dict of the property with its value being the characteristics value, e.g. {“prop”: {“value”: 6, ‘importance’: ‘SUGGESTED’}}. Except: None as value is not added to the dict. If a property is of type LIST, the comparison is order-sensitive.

Comparison of multi-properties is not yet supported, so should either entity have several instances of one Property, the comparison is aborted and an error is raised.

Two parents match if their name and id are the same, any further differences are ignored.

Should records referenced in the value field not be checked for equality between the entities but for equivalency, this is possible by setting the parameter compare_referenced_records.

Params

entity0Entity

First entity to be compared.

entity1Entity

Second entity to be compared.

compare_referenced_records: bool, default: False

If set to True, values with referenced records are not checked for equality but for equivalency using this function. compare_referenced_records is set to False for these recursive calls, so references of references need to be equal. If set to False, only the Python objects are compared, which may lead to unexpected behavior.

entity_name_id_equivalency: bool, default: False

If set to True, the comparison between an entity and an int or str also checks whether the int/str matches the name or id of the entity, so Entity(id=100) == 100 == “100”.

linkahead.apiutils.create_flat_list(ent_list: list[Entity], flat: list[Entity])

Recursively adds all properties contained in entities from ent_list to the output list flat. Each element will only be added once to the list.

TODO: Currently this function is also contained in newcrawler module crawl.

We are planning to permanently move it to here.

linkahead.apiutils.create_id_query(ids: list[int]) str
linkahead.apiutils.describe_diff(entity0_diff: dict[str, Any], entity1_diff: dict[str, Any], name: str | None = None, as_update: bool | None = None, label_e0: str = 'first version', label_e1: str = 'second version', olddiff: Any | None = None, newdiff: Any | None = None) str

Generate a textual description of the differences between two entities. These can be generated using compare_entities() and used within this function like this:

describe_diff(*compare_entities(…))

Arguments:

entity0_diff: dict[str, Any]

First element of the tuple output of compare_entities(). This is referred to as the “first” version.

entity1_diff: dict[str, Any]

Second element of the tuple output of compare_entities(). This is referred to as the “second” version.

name: Optional[str]

Default None. Name of the entity that will be shown in the output text.

as_update: Optional[bool]

Default None. Not used anymore.

label_e0: str

Can be used to set a custom label for the diff that is associated with the first entity.

label_e1: str

Can be used to set a custom label for the diff that is associated with the second entity.

olddiff: Any

Deprecated. Replaced by entity0_diff.

newdiff: Any

Deprecated. Replaced by entity1_diff.

Returns:

A text description of the differences.

linkahead.apiutils.empty_diff(entity0: Entity, entity1: Entity, compare_referenced_records: bool = False, entity_name_id_equivalency: bool = False, old_entity: Entity | None = None, new_entity: Entity | None = None) bool

Check whether the compare_entities found any differences between entity0 and entity1.

Parameters:
  • entity0 (Entity) – Entities to be compared

  • entity1 (Entity) – Entities to be compared

  • compare_referenced_records (bool, optional) – Whether to compare referenced records in case of both, entity0 and entity1, have the same reference properties and both have a Record object as value.

  • entity_name_id_equivalency (bool, optional) – If set to True, the comparison between an entity and an int or str also checks whether the int/str matches the name or id of the entity, so Entity(id=100) == 100 == “100”.

linkahead.apiutils.getBranchIn(folder)
linkahead.apiutils.getCommitIn(folder)
linkahead.apiutils.getDiffIn(folder, save_dir=None)
linkahead.apiutils.getOriginUrlIn(folder)
linkahead.apiutils.get_type_of_entity_with(id_: int)
linkahead.apiutils.id_query(ids: list[int]) Container
linkahead.apiutils.merge_entities(entity_a: Entity, entity_b: Entity, merge_references_with_empty_diffs=True, force=False, merge_id_with_resolved_entity: bool = False) Entity

Merge entity_b into entity_a such that they have the same parents and properties.

The attributes datatype, unit, value, name and description will only be changed in entity_a if they are None for entity_a and set for entity_b. If one of those attributes is set in both entities and they differ, then an EntityMergeConflictError will be raised to inform about an unresolvable merge conflict.

The merge operation is done in place.

Returns entity_a.

Parameters:
  • entity_a (Entity) – The entities to be merged. entity_b will be merged into entity_a in place

  • entity_b (Entity) – The entities to be merged. entity_b will be merged into entity_a in place

  • merge_references_with_empty_diffs (bool, optional) – 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 set to False a merge conflict will be raised in this case instead. Default is True.

  • force (bool, optional) – 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. 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:

entity_a – The initial entity_a after the in-place merge

Return type:

Entity

Raises:

EntityMergeConflictError – In case of an unresolvable merge conflict.

linkahead.apiutils.new_record(record_type: str, name: str | None = None, description: str | None = None, tempid: int | None = None, insert: bool = False, **kwargs) Record

Function to simplify the creation of Records.

record_type: The name of the RecordType to use for this record. name: Name of the new Record. kwargs: Key-value-pairs for the properties of this Record.

Returns: The newly created Record.

Of course this functions requires an open database connection!

linkahead.apiutils.resolve_reference(prop: Property)

resolves the value of a reference property

The integer value is replaced with the entity object. If the property is not a reference, then the function returns without change.

linkahead.apiutils.retrieve_entities_with_ids(entities: list) Container
linkahead.apiutils.retrieve_entity_with_id(eid: int)