diff --git a/CHANGELOG.md b/CHANGELOG.md index 5aa592990ce2b80b9fde674959246c38c4278bb2..09bd51835c93bf18eb3644e296082bacf0a9c043 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,12 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added ### +* extended apiutils with `resolve_reference(Property)` * is_reference function for Properties ### Changed ### ### Deprecated ### +* `id_query(ids)` in apiutils + ### Removed ### ### Fixed ### diff --git a/src/caosdb/apiutils.py b/src/caosdb/apiutils.py index 73074efc3057e0548c5abfd56ef3cf1ac9e9bf47..9192289a0b6518a2d6ec3abcdeca9d1d2c063d6d 100644 --- a/src/caosdb/apiutils.py +++ b/src/caosdb/apiutils.py @@ -31,6 +31,7 @@ Some simplified functions for generation of records etc. import sys import tempfile from collections.abc import Iterable +import warnings from subprocess import call from caosdb.common.datatype import (BOOLEAN, DATETIME, DOUBLE, FILE, INTEGER, @@ -86,9 +87,19 @@ def new_record(record_type, name=None, description=None, def id_query(ids): - q = "FIND Entity with " + " OR ".join(["id={}".format(id) for id in ids]) + warnings.warn("Please use 'create_id_query', which only creates" + "the string.", DeprecationWarning) - return execute_query(q) + return execute_query(create_id_query(ids)) + + +def create_id_query(ids): + return "FIND ENTITY WITH " + " OR ".join( + ["ID={}".format(id) for id in ids]) + + +def retrieve_entity_with_id(eid): + return execute_query("FIND ENTITY WITH ID={}".format(eid), unique=True) def retrieve_entities_with_ids(entities): @@ -96,7 +107,9 @@ def retrieve_entities_with_ids(entities): step = 20 for i in range(len(entities)//step+1): - collection.extend(id_query(entities[i*step:(i+1)*step])) + collection.extend( + execute_query( + create_id_query(entities[i*step:(i+1)*step]))) return collection @@ -707,3 +720,28 @@ def _apply_to_ids_of_entity(entity, func): else: if prop.value is not None: prop.value = func(prop.value) + + +def 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. + """ + + if not prop.is_reference(server_retrieval=True): + return + + if isinstance(prop.value, list): + referenced = [] + + for val in prop.value: + if isinstance(val, int): + referenced.append(retrieve_entity_with_id(val)) + else: + referenced.append(val) + prop.value = referenced + else: + if isinstance(prop.value, int): + prop.value = retrieve_entity_with_id(prop.value) diff --git a/unittests/test_apiutils.py b/unittests/test_apiutils.py index c560b5e3c7c424b762bc8381c7cc9f42617288d0..264b4c880022e6fd135426864bf9c5084c047eca 100644 --- a/unittests/test_apiutils.py +++ b/unittests/test_apiutils.py @@ -29,7 +29,8 @@ import caosdb as db import pickle import tempfile -from caosdb.apiutils import apply_to_ids +from caosdb.apiutils import apply_to_ids, create_id_query, resolve_reference +import caosdb.apiutils from .test_property import testrecord @@ -62,3 +63,42 @@ def test_apply_to_ids(): assert rec.parents[0].id == -3456 assert rec.properties[0].id == -23345 assert rec.id == -23 + + +def test_id_query(): + ids = [1, 2, 3, 4, 5] + assert create_id_query(ids) == 'FIND ENTITY WITH ID=1 OR ID=2 OR ID=3 OR ID=4 OR ID=5' + + +def test_resolve_reference(): + original_retrieve_entity_with_id = caosdb.apiutils.retrieve_entity_with_id + caosdb.apiutils.retrieve_entity_with_id = lambda eid: db.Record(id=eid) + + prop = db.Property(id=1, datatype=db.REFERENCE, value=100) + prop.is_valid = lambda: True + items = [200, 300, 400] + prop_list = db.Property(datatype=db.LIST(db.REFERENCE), value=items) + prop_list2 = db.Property(datatype=db.LIST(db.REFERENCE), value=[db.Record(id=500)]) + resolve_reference(prop) + resolve_reference(prop_list) + resolve_reference(prop_list2) + assert prop.value.id == 100 + assert isinstance(prop.value, db.Entity) + + prop_list_ids = [] + for i in prop_list.value: + prop_list_ids.append(i.id) + assert isinstance(i, db.Entity) + assert prop_list_ids == items + + for i in prop_list2.value: + assert i.id == 500 + assert isinstance(i, db.Entity) + + no_reference = db.Property(id=5000, datatype=db.INTEGER, value=2) + resolve_reference(no_reference) + assert no_reference.value == 2 + assert no_reference.datatype is db.INTEGER + + # restore retrive_entity_with_id + caosdb.apiutils.retrieve_entity_with_id = original_retrieve_entity_with_id