diff --git a/src/caosdb/high_level_api.py b/src/caosdb/high_level_api.py index 87c0fc28790c78eab58772f5acbf997532a4f880..5d1f1160da30e200916679264ac6fc3b035a2619 100644 --- a/src/caosdb/high_level_api.py +++ b/src/caosdb/high_level_api.py @@ -93,15 +93,18 @@ def high_level_type_for_role(role: str): def high_level_type_for_standard_type(standard_record: db.Entity): - if type(standard_record) == db.Record: + if not isinstance(standard_record, db.Entity): + raise ValueError() + role = standard_record.role + if role == "Record" or type(standard_record) == db.Record: return CaosDBPythonRecord - elif type(standard_record) == db.File: + elif role == "File" or type(standard_record) == db.File: return CaosDBPythonFile - elif type(standard_record) == db.Property: + elif role == "Property" or type(standard_record) == db.Property: return CaosDBPythonProperty - elif type(standard_record) == db.RecordType: + elif role == "RecordType" or type(standard_record) == db.RecordType: return CaosDBPythonRecordType - elif type(standard_record) == db.Entity: + elif role == "Entity" or type(standard_record) == db.Entity: return CaosDBPythonEntity raise RuntimeError("Incompatible type.") @@ -531,6 +534,14 @@ class CaosDBPythonEntity(object): # don't do the lookup in the references container return visited[propval.id] + if references is None: + ent = db.Entity(id=propval.id).retrieve() + obj = convert_to_python_object(ent, references) + visited[propval.id] = obj + if deep: + obj.resolve_references(deep, references, visited) + return obj + # lookup in container: for ent in references: # Entities in container without an ID will be skipped: @@ -556,6 +567,8 @@ class CaosDBPythonEntity(object): references: Optional[db.Container] A container with references that might be resolved. + If None is passed as the container, this function tries to resolve entities from a running + CaosDB instance directly. """ # This parameter is used in the recursion to keep track of already visited @@ -613,8 +626,14 @@ class CaosDBPythonEntity(object): for parent in serialization["parents"]: if "unresolved" in parent: + id = None + name = None + if "id" in parent: + id = parent["id"] + if "name" in parent: + name = parent["name"] entity.add_parent(CaosDBPythonUnresolvedParent( - id=parent["id"], name=parent["name"])) + id=id, name=name)) else: raise NotImplementedError() @@ -756,9 +775,11 @@ class CaosDBMultiProperty: class CaosDBPythonFile(CaosDBPythonEntity): - def get_File(self, target=None): - f = db.File(id=self._id).retrieve() - self._file = f.download(target) + def download(self, target=None): + if self.id is None: + raise RuntimeError("Cannot download file when id is missing.") + f = db.File(id=self.id).retrieve() + return f.download(target) BASE_ATTRIBUTES = ( @@ -974,3 +995,13 @@ def create_entity_container(record: CaosDBPythonEntity): return db.Container().extend(lse) +def query(query: str, resolve_references: bool = True, references: db.Container = None): + """ + + """ + res = db.execute_query(query) + objects = convert_to_python_object(res) + if resolve_references: + for obj in objects: + obj.resolve_references(True, references) + return objects diff --git a/unittests/test_high_level_api.py b/unittests/test_high_level_api.py index 6e8a5ac9b3c9b024a496a6f06907ecca75eec29e..f00d3cc0e80a3dade09c7e276f632ae3d41fd22d 100644 --- a/unittests/test_high_level_api.py +++ b/unittests/test_high_level_api.py @@ -532,9 +532,14 @@ def test_type_conversion(): with pytest.raises(RuntimeError, match="Incompatible type."): standard_type_for_high_level_type(42, True) - with pytest.raises(RuntimeError, match="Incompatible type."): + with pytest.raises(ValueError): high_level_type_for_standard_type("ajsdkfjasfkj") + with pytest.raises(RuntimeError, match="Incompatible type."): + class IncompatibleType(db.Entity): + pass + high_level_type_for_standard_type(IncompatibleType()) + def test_deserialization(): r = db.Record(id=17, name="test") @@ -585,3 +590,7 @@ def test_deserialization(): serial = obj.serialize() obj_des = CaosDBPythonEntity.deserialize(serial) assert obj.serialize() == obj_des.serialize() + + +def test_recursion(): + pass