From 72aa0fb16b0f9de1f8df349c56e12e9dda7dc469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20tom=20W=C3=B6rden?= <h.tomwoerden@indiscale.com> Date: Tue, 13 Jul 2021 11:35:18 +0000 Subject: [PATCH] ENH: Add is_reference to db.Property --- CHANGELOG.md | 2 ++ src/caosdb/common/models.py | 37 +++++++++++++++++++++++++++++ unittests/test_property.py | 47 ++++++++++++++++++++++++++++++++++++- 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6255ff1c..5aa59299 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added ### +* is_reference function for Properties + ### Changed ### ### Deprecated ### diff --git a/src/caosdb/common/models.py b/src/caosdb/common/models.py index 0142b044..57b07bd6 100644 --- a/src/caosdb/common/models.py +++ b/src/caosdb/common/models.py @@ -31,6 +31,7 @@ from __future__ import print_function, unicode_literals import re import sys from builtins import str +from copy import deepcopy from functools import cmp_to_key from hashlib import sha512 from os import listdir @@ -1504,6 +1505,42 @@ class Property(Entity): return super(Property, self).to_xml(xml, add_properties) + def is_reference(self, server_retrieval=False): + """Returns whether this Property is a reference + + Parameters + ---------- + server_retrieval : bool, optional + If True and the datatype is not set, the Property is retrieved from the server, by default False + + Returns + ------- + bool, NoneType + Returns whether this Property is a reference or None if a server call is needed to + check correctly, but server_retrieval is set to False. + + """ + + if self.datatype is None: + + if not self.is_valid(): + # this is a workaround to prevent side effects + # since retrieve currently changes the object + + if server_retrieval: + tmp_prop = deepcopy(self) + tmp_prop.retrieve() + + return tmp_prop.is_reference() + else: + return None + else: + # a valid property without datatype has to be an RT + + return True + else: + return is_reference(self.datatype) + class Message(object): diff --git a/unittests/test_property.py b/unittests/test_property.py index 752ee01f..834b1be5 100644 --- a/unittests/test_property.py +++ b/unittests/test_property.py @@ -24,9 +24,10 @@ # ** end header # """Tests for the Property class.""" +import caosdb as db +from caosdb import Entity, Property, Record # pylint: disable=missing-docstring from lxml import etree -from caosdb import Entity, Property, Record parser = etree.XMLParser(remove_comments=True) testrecord = Record._from_xml(Record(), @@ -89,3 +90,47 @@ def test_get_property_with_entity(): 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 -- GitLab