Skip to content
Snippets Groups Projects
Select Git revision
  • 4ad2435bf7df73eead9618cbfda8b97f3b8ca89b
  • main default protected
  • dev protected
  • f-remove-dropoffbox
  • f-sss4grpc
  • f-refactor-compose
  • f-real-id
  • f-doip
  • f-filesystem-import
  • henrik-tmp
  • f-filesystem-link
  • f-filesystem-directory
  • f-filesystem-core
  • f-filesystem-cleanup
  • f-string-ids
  • f-filesystem-main
  • f-linkahead-rename-before
  • f-linkahead-rename
  • f-rename-li
  • f-experiment-trino
  • f-no-has
  • v0.13.0 protected
  • v0.12.3 protected
  • v0.12.2 protected
  • v0.12.1 protected
  • v0.12.0 protected
  • v0.11.0 protected
  • v0.10.0 protected
  • v0.9.0 protected
  • v0.8.1 protected
  • v0.8.0 protected
  • v0.7.3 protected
  • v0.7.2 protected
  • v0.7.1 protected
  • v0.6.0 protected
  • v0.5.0 protected
  • v0.4.0 protected
  • v0.3.0 protected
  • working_sss protected
  • v0.1 protected
40 results

server.conf

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    test_property.py 8.22 KiB
    # -*- encoding: utf-8 -*-
    #
    # 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) 2020 - 2023 IndiScale GmbH <info@indiscale.com>
    # Copyright (C) 2023 Florian Spreckelsen <f.spreckelsen@indiscale.com>
    # Copyright (C) 2020 Timm Fitschen <t.fitschen@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 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/>.
    #
    """Tests for the Property class."""
    import os
    
    import caosdb as db
    from caosdb import Entity, Property, Record
    # pylint: disable=missing-docstring
    from lxml import etree
    
    parser = etree.XMLParser(remove_comments=True)
    testrecord = Record._from_xml(
        Record(),
        etree.parse(os.path.join(os.path.dirname(__file__), "test_record.xml"),
                    parser).getroot())
    
    
    def test_is_entity():
        prop = Property()
        assert isinstance(prop, Entity)
    
    
    def test_instance_variables():
        prop = Property()
        assert hasattr(prop, "datatype")
        assert hasattr(prop, "unit")
        assert hasattr(prop, "value")
    
    
    def test_null_empty_text_value_1():
        assert testrecord.get_property("LISTofTEXT").value == ["One", "Two",
                                                               "Three", None, ""]
    
    
    def test_null_empty_text_value_2():
        assert testrecord.get_property("NULLTEXT1").value is None
    
    
    def test_null_empty_text_value_3():
        assert testrecord.get_property("NULLTEXT2").value is None
    
    
    def test_null_empty_text_value_4():
        assert testrecord.get_property("EMPTYTEXT1").value == ""
    
    
    def test_null_empty_text_value_5():
        assert testrecord.get_property("EMPTYTEXT2").value == ""
    
    
    def test_list_of_references_with_null():
        assert testrecord.get_property("MultiRecRecording").value[0] is None
        assert testrecord.get_property("MultiRecRecording").value[1] == 170651
    
    
    def test_role():
        prop = Property()
        assert prop.role == "Property"
    
    
    def test_get_property_with_entity():
        p = Property(name="Prop")
        r = Record().add_property("Prop", "blub")
        assert r.get_property(p).value == "blub"
    
        p = Property(id=1234)
        r.add_property(id=1234, value="bla")
        assert r.get_property(p).value == "bla"
    
    
    def test_selected_reference_list():
        assert len(testrecord.get_property("Conductor").value) == 1
        assert isinstance(testrecord.get_property("Conductor").value[0], Entity)
    
    
    def test_is_reference():
        PROPS = {
            10:  db.INTEGER,
            20:  db.REFERENCE,
            30:  "SomeRT",
        }
    
        def dummy_retrieve(self):
            self.datatype = PROPS[self.id]
            self.is_valid = lambda: True
        # replace retrieve function by dummy
        real_retrieve = Entity.retrieve
        Entity.retrieve = dummy_retrieve
    
        p1 = Property(id=1, datatype=db.INTEGER)
        p2 = Property(id=2, datatype=db.DOUBLE)
        p3 = Property(id=3, datatype=db.TEXT)
        p4 = Property(id=4, datatype=db.DATETIME)
        p5 = Property(id=5, datatype=db.BOOLEAN)
        p6 = Property(id=6, datatype=db.REFERENCE)
        assert p1.is_reference() is False
        assert p2.is_reference() is False
        assert p3.is_reference() is False
        assert p4.is_reference() is False
        assert p5.is_reference() is False
        assert p6.is_reference() is True
    
        p7 = Property(id=7)
        p8 = Property(id=8, value=db.RecordType(id=1000))
        p8.is_valid = lambda: True
        assert p7.is_reference() is None  # cannot be resolved without calling a server
        assert p8.is_reference() is True
    
        p10 = Property(id=10)
        p20 = Property(id=20)
        p30 = Property(id=30)
        assert p10.is_reference(server_retrieval=True) is False
        assert p20.is_reference(server_retrieval=True) is True
        assert p30.is_reference(server_retrieval=True) is True
    
        # restore retrieve function with original
        Entity.retrieve = real_retrieve
    
    
    def test_remove_value_from_property():
    
        rec = Record()
        names_values_dtypes = [
            ("testListProp1", [1, 2, 3], db.LIST(db.INTEGER)),
            ("testListProp2", ["a", "b", "a"], db.LIST(db.TEXT)),
            ("testScalarProp1", "bla", db.TEXT),
            ("testScalarProp2", False, db.BOOLEAN),
            ("testEmptyProp", None, db.REFERENCE),
            ("testNoneListProp", [None, None], db.REFERENCE),
        ]
        for name, value, dtype in names_values_dtypes:
            rec.add_property(name=name, value=value, datatype=dtype)
    
        # property doesn't exist, so do nothing
        returned = rec.remove_value_from_property("nonexisting", "some_value")
        assert returned is rec
        for name, value, dtype in names_values_dtypes:
            assert rec.get_property(name).value == value
            assert rec.get_property(name).datatype == dtype
    
        # value doesn't exist so nothing changes either
        rec.remove_value_from_property("testListProp1", 0)
        assert rec.get_property("testListProp1").value == [1, 2, 3]
        assert rec.get_property("testListProp1").datatype == db.LIST(db.INTEGER)
    
        returned = rec.remove_value_from_property("testScalarProp2", True)
        assert returned is rec
        assert rec.get_property("testScalarProp2").value is False
        assert rec.get_property("testScalarProp2").datatype == db.BOOLEAN
    
        # Simple removals from lists without emptying them
        rec.remove_value_from_property("testListProp1", 1)
        assert rec.get_property("testListProp1").value == [2, 3]
    
        rec.remove_value_from_property("testListProp1", 2)
        assert rec.get_property("testListProp1").value == [3]
    
        # similarly to Python's `list.remove()`, only remove first occurrance
        rec.remove_value_from_property("testListProp2", "a")
        assert rec.get_property("testListProp2").value == ["b", "a"]
    
        # default is to remove an empty property:
        rec.remove_value_from_property("testListProp1", 3)
        assert rec.get_property("testListProp1") is None
    
        rec.remove_value_from_property("testScalarProp1", "bla")
        assert rec.get_property("testScalarProp1") is None
    
        # don't remove if `remove_if_empty_afterwards=False`
        rec.remove_value_from_property("testListProp2", "b")
        rec.remove_value_from_property("testListProp2", "a", remove_if_empty_afterwards=False)
        assert rec.get_property("testListProp2") is not None
        assert rec.get_property("testListProp2").value is None
        assert rec.get_property("testListProp2").datatype == db.LIST(db.TEXT)
    
        rec.remove_value_from_property("testScalarProp2", False, remove_if_empty_afterwards=False)
        assert rec.get_property("testScalarProp2") is not None
        assert rec.get_property("testScalarProp2").value is None
        assert rec.get_property("testScalarProp2").datatype == db.BOOLEAN
    
        # Special case of an already empty property: It is not empty because a value
        # was removed by `remove_value_from_property` but never had a value in the
        # first place. So even `remove_if_empty_afterwards=True` should not lead to
        # its removal.
        rec.remove_value_from_property("testEmptyProp", 1234, remove_if_empty_afterwards=True)
        assert rec.get_property("testEmptyProp") is not None
        assert rec.get_property("testEmptyProp").value is None
        assert rec.get_property("testEmptyProp").datatype == db.REFERENCE
    
        # Corner case of corner case: remove with `value=None` and
        # `remove_if_empty_afterwards=True` keeps the empty property.
        rec.remove_value_from_property("testEmptyProp", None, remove_if_empty_afterwards=True)
        assert rec.get_property("testEmptyProp") is not None
        assert rec.get_property("testEmptyProp").value is None
        assert rec.get_property("testEmptyProp").datatype == db.REFERENCE
    
        # Remove `None` from list `[None, None]`
        rec.remove_value_from_property("testNoneListProp", None, remove_if_empty_afterwards=True)
        assert rec.get_property("testNoneListProp") is not None
        assert rec.get_property("testNoneListProp").value == [None]
        assert rec.get_property("testNoneListProp").datatype == db.REFERENCE