diff --git a/src/caosdb/apiutils.py b/src/caosdb/apiutils.py index 5558f649f5ff06401273ce5059b9114e421df930..e6bd80fb6807315a04eab8718b5b808b8fdf9b9a 100644 --- a/src/caosdb/apiutils.py +++ b/src/caosdb/apiutils.py @@ -480,3 +480,26 @@ def resolve_reference(prop: Property): else: if isinstance(prop.value, int): prop.value = retrieve_entity_with_id(prop.value) + + +def 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. + """ + for ent in ent_list: + for p in ent.properties: + # For lists append each element that is of type Entity to flat: + if isinstance(p.value, list): + for el in p.value: + if isinstance(el, Entity): + if el not in flat: + flat.append(el) + create_flat_list([el], flat) # TODO: move inside if block? + elif isinstance(p.value, Entity): + if p.value not in flat: + flat.append(p.value) + create_flat_list([p.value], flat) # TODO: move inside if block? diff --git a/src/caosdb/high_level_api.py b/src/caosdb/high_level_api.py index f323589402656e21bf9a9bfd12bcabc8c7f8a906..3daf9f2faf942f86dd0cebc606613b97bf050b4e 100644 --- a/src/caosdb/high_level_api.py +++ b/src/caosdb/high_level_api.py @@ -37,7 +37,7 @@ from caosdb.common.datatype import (BOOLEAN, DATETIME, DOUBLE, FILE, INTEGER, is_reference) import caosdb as db -from .apiutils import get_type_of_entity_with +from .apiutils import get_type_of_entity_with, create_flat_list from typing import Any, Optional, List, Union, Dict @@ -806,11 +806,9 @@ def convert_to_python_object(entity: Union[db.Container, db.Entity], high_level_type_for_standard_type(entity)(), entity, references) -def new_high_level_entity_for_record_type(entity: db.RecordType, - importance_level: str, - name: str = None, - deep: bool = True, - references: Optional[db.Container] = None): +def new_high_level_entity(entity: db.RecordType, + importance_level: str, + name: str = None): """ Create an new record in high level format based on a record type in standard format. @@ -840,9 +838,45 @@ def new_high_level_entity_for_record_type(entity: db.RecordType, r.add_property(prop) - if deep: - raise NotImplementedError("Recursive creation is not possible at the moment.") - return convert_to_python_object(r) +def create_record(rtname: str, name: str = None, **kwargs): + """ + Create a new record based on the name of a record type. The new record is returned. + + rtname: str + The name of the record type. + + name: str + This is optional. A name for the new record. + + kwargs: + Additional arguments are used to set attributes of the + new record. + """ + obj = new_high_level_entity( + db.RecordType(name=rtname).retrieve(), "SUGGESTED", name) + for key, value in kwargs.items(): + obj.__setattr__(key, value) + return obj + + +def load_external_record(record_name: str): + """ + Retrieve a record by name and convert it to the high level API format. + """ + return convert_to_python_object(db.Record(name=record_name).retrieve()) + + +def create_entity_container(record: CaosDBPythonEntity): + """ + Convert this record into an entity container in standard format that can be used + to insert or update entities in a running CaosDB instance. + """ + ent = convert_to_entity(record) + lse: List[db.Entity] = [ent] + create_flat_list([ent], lse) + return db.Container().extend(lse) + +