diff --git a/CHANGELOG.md b/CHANGELOG.md index e5a7f8f6690bd134422255d43d0b7e3bfba7c347..04b5981bb221e749619aa11b018d495e395eff37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed ### +- [#40](https://gitlab.com/caosdb/caosdb-advanced-user-tools/-/issues/40) + `assure_object_is_in_list` now handles adding objects to an initially empty list correctly. + ### Security ### ## [0.4.0] - 2022-04-05 ## diff --git a/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_v0.1/README.md b/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_v0.1/README.md index d844a2ddf0d87d303c69b9107a366f2e34b6d03c..2057703d18dad94127037e05b3180603e9e37380 100644 --- a/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_v0.1/README.md +++ b/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_v0.1/README.md @@ -1,6 +1,6 @@ --- responsible: Responsible, Only -description: A description of this example analysis. +description: A description of another example analysis. sources: - file: "/ExperimentalData/2010_TestProject/2019-02-03/*.dat" diff --git a/integrationtests/extroot/Software/2020NewProject0X/2020-02-03/README.md b/integrationtests/extroot/Software/2020NewProject0X/2020-02-03/README.md index a47ea6e105c20d050ddf2fdc8cd29d4685ba30bf..bd57ffe2c43fe6406672db2dd18902b8269569d4 100644 --- a/integrationtests/extroot/Software/2020NewProject0X/2020-02-03/README.md +++ b/integrationtests/extroot/Software/2020NewProject0X/2020-02-03/README.md @@ -1,7 +1,7 @@ --- responsible: - Only Responsible MPI DS -description: A description of this example analysis. +description: A description of another example analysis. sources: - file: "/ExperimentalData/2010_TestProject/2019-02-03/*.dat" diff --git a/integrationtests/extroot/Software/2020NewProject0X/2020-02-04/README.md b/integrationtests/extroot/Software/2020NewProject0X/2020-02-04/README.md index 97b7137af372c127ee01458c9844b5ff10fd464b..b55907aaa2bb3794dbe04484c025146c3c7cd101 100644 --- a/integrationtests/extroot/Software/2020NewProject0X/2020-02-04/README.md +++ b/integrationtests/extroot/Software/2020NewProject0X/2020-02-04/README.md @@ -2,7 +2,7 @@ responsible: - Some Responsible - Responsible, No, MPI DS -description: A description of this example analysis. +description: A description of another example analysis. sources: - file: "/ExperimentalData/2010_TestProject/2019-02-03/*.dat" diff --git a/integrationtests/test.sh b/integrationtests/test.sh index a142d917215eb7469faab9c66a581539ce867e4e..5bb013db6e70a3a8393e7e3b7c7993a6da6bf9b9 100755 --- a/integrationtests/test.sh +++ b/integrationtests/test.sh @@ -35,14 +35,17 @@ echo "Testing the crawler database" python3 -m pytest test_crawler_with_cfoods.py echo "make a change" cd extroot -egrep -liRZ 'A description of another example' . | xargs -0 -l sed -i -e 's/A description of another example/A description of this example/g' +egrep -liRZ 'A description of another example' . \ + | xargs -0 -l sed -i -e 's/A description of another example/A description of this example/g' # remove a file to check that this does not lead to a crawler crash -mv DataAnalysis/2010_TestProject/2019-02-03_something/README.xlsx DataAnalysis/2010_TestProject/2019-02-03_something/README.xlsx_back +mv DataAnalysis/2010_TestProject/2019-02-03_something/README.xlsx \ + DataAnalysis/2010_TestProject/2019-02-03_something/README.xlsx_back cd .. echo "run crawler" ./crawl.py / | tee $OUT # rename the moved file -mv extroot/DataAnalysis/2010_TestProject/2019-02-03_something/README.xlsx_back extroot/DataAnalysis/2010_TestProject/2019-02-03_something/README.xlsx +mv extroot/DataAnalysis/2010_TestProject/2019-02-03_something/README.xlsx_back \ + extroot/DataAnalysis/2010_TestProject/2019-02-03_something/README.xlsx # check whether there was something UNAUTHORIZED grep "There where unauthorized changes" $OUT # get the id of the run which is the last field of the output string @@ -59,7 +62,8 @@ fi set -e echo "Undoing previous changes to extroot content..." cd extroot -egrep -liRZ 'A description of this example' . | xargs -0 -l sed -i -e 's/A description of this example/A description of another example/g' +egrep -liRZ 'A description of this example' . \ + | xargs -0 -l sed -i -e 's/A description of this example/A description of another example/g' cd .. echo "Done." python3 test_table.py diff --git a/integrationtests/test_assure_functions.py b/integrationtests/test_assure_functions.py index 9f4e387d52f25382d18cfb21372a06346d2b5465..b1c731dbbf25f33b54fc3a005402f292525d2d05 100644 --- a/integrationtests/test_assure_functions.py +++ b/integrationtests/test_assure_functions.py @@ -1,26 +1,25 @@ #!/usr/bin/env python # encoding: utf-8 # -# ** header v3.0 # This file is a part of the CaosDB Project. # +# Copyright (C) 2022 IndiScale GmbH <info@indiscale.com> # Copyright (C) 2021 University Medical Center Göttingen, Institute for Medical Informatics # Copyright (C) 2021 Florian Spreckelsen <florian.spreckelsen@med.uni-goettingen.de> +# Copyright (C) 2022 Florian Spreckelsen <f.spreckelsen@indiscale.com> # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. # -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see <https://www.gnu.org/licenses/>. -# -# ** end header +# You should have received a copy of the GNU Affero General Public License along +# with this program. If not, see <https://www.gnu.org/licenses/>. """Integration tests for the `assure_...` functions from `caosadvancedtools.cfood`. They mainly test the in-place updates when no `to_be_updated` is specified. @@ -90,3 +89,29 @@ def test_assure_list_in_place(): assert len(rec2.get_property(ref_rt.name).value) == 3 assert ref_rec2.id in rec2.get_property(ref_rt.name).value assert ref_rec3.id in rec2.get_property(ref_rt.name).value + + +def test_add_to_empty_list(): + """See https://gitlab.com/caosdb/caosdb-advanced-user-tools/-/issues/40.""" + # @author Florian Spreckelsen + # @date 2022-04-19 + referenced_rt = db.RecordType(name="TestReferencedType").insert() + list_prop = db.Property(name="TestListProp", + datatype=db.LIST(referenced_rt)).insert() + referencing_rt = db.RecordType( + name="TestReferencingType").add_property(list_prop).insert() + + db.Record(name="TestReferencedRecord").add_parent(referenced_rt).insert() + db.Record(name="TestReferencingRecord").add_parent( + referencing_rt).add_property(list_prop, value=[]).insert() + + referenced_rec = db.execute_query("FIND TestReferencedRecord", unique=True) + referencing_rec = db.execute_query( + "FIND TestReferencingRecord", unique=True) + + assure_object_is_in_list(referenced_rec, referencing_rec, list_prop.name) + + referencing_rec = db.execute_query( + "FIND TestReferencingRecord", unique=True) + assert referencing_rec.get_property(list_prop.name).value == [ + referenced_rec.id] diff --git a/src/caosadvancedtools/cfood.py b/src/caosadvancedtools/cfood.py index 4500664031af55e92f5f1c2856e0531be06482f3..4a9f955a17fc429deb6cdd10c3645700e579b4df 100644 --- a/src/caosadvancedtools/cfood.py +++ b/src/caosadvancedtools/cfood.py @@ -1,14 +1,13 @@ #!/usr/bin/env python # encoding: utf-8 # -# ** header v3.0 # This file is a part of the CaosDB Project. # # Copyright (C) 2018 Research Group Biomedical Physics, # Max-Planck-Institute for Dynamics and Self-Organization Göttingen -# Copyright (C) 2019,2020 IndiScale GmbH <info@indiscale.com> +# Copyright (C) 2019-2022 IndiScale GmbH <info@indiscale.com> # Copyright (C) 2019,2020 Henrik tom Wörden -# Copyright (C) 2020 Florian Spreckelsen <f.spreckelsen@indiscale.com> +# Copyright (C) 2020-2022 Florian Spreckelsen <f.spreckelsen@indiscale.com> # Copyright (C) 2021 University Medical Center Göttingen, Institute for Medical Informatics # Copyright (C) 2021 Florian Spreckelsen <florian.spreckelsen@med.uni-goettingen.de> # @@ -24,8 +23,6 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. -# -# ** end header """ Defines how something that shall be inserted into CaosDB is treated. CaosDB can automatically be filled with Records based on some structure, a file @@ -415,11 +412,13 @@ def assure_object_is_in_list(obj, containing_object, property_name, datatype=datatype) # TODO: case where multiple times the same property exists is not treated - if not isinstance(containing_object.get_property(property_name).value, list): - containing_object.get_property(property_name).value = [ - containing_object.get_property(property_name).value] - containing_object.get_property(property_name).datatype = datatype - current_list = containing_object.get_property(property_name).value + list_prop = containing_object.get_property(property_name) + if list_prop.value is None: + list_prop.value = [] + elif not isinstance(list_prop.value, list): + list_prop.value = [list_prop.value] + list_prop.datatype = datatype + current_list = list_prop.value if not isinstance(obj, list): objects = [obj] @@ -674,7 +673,8 @@ def assure_has_property(entity, name, value, to_be_updated=None, tmp_value = el.value.id if isinstance(tmp_value, list): - tmp_value = [i.id if isinstance(i, db.Entity) else i for i in tmp_value] + tmp_value = [i.id if isinstance( + i, db.Entity) else i for i in tmp_value] if tmp_value == value: contained = True