From 8565480c22789e2d8e26766275e1bf331ce999ec Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 13 Jun 2019 00:10:53 +0200 Subject: [PATCH 01/13] [version_converter] Automatically Add UUIDs For Properties Adding UUIDs, when converting from odML version 1.0 to 1.1. If an ID already exists, it stays the same, if it is compatible with the python uuid types. Otherwise (also if empty) a new ID is created for the property. --- odml/tools/version_converter.py | 43 ++++++++++++++++++++ test/test_version_converter.py | 69 ++++++++++++++++++++++++++++----- 2 files changed, 103 insertions(+), 9 deletions(-) diff --git a/odml/tools/version_converter.py b/odml/tools/version_converter.py index 3d842e89..28638eb6 100644 --- a/odml/tools/version_converter.py +++ b/odml/tools/version_converter.py @@ -9,6 +9,8 @@ from ..info import FORMAT_VERSION from ..terminology import Terminologies, REPOSITORY_BASE +import uuid + try: unicode = unicode except NameError: @@ -194,6 +196,8 @@ def _convert(self, tree): if e.tag == "repository": self._handle_repository(e) + tree = self._check_add_ids(tree) + return tree def _handle_include(self, element): @@ -410,6 +414,45 @@ def _change_entity_name(tree, elem_map, name): elem_map[named_path] += 1 name.text += "-" + str(elem_map[named_path]) + def _check_add_ids(self, tree): + """ + Checks, whether elements (properties) possess an UUID + and adds one in case of absence. + :param tree: ElementTree of the doc + :return: ElementTree + """ + root = tree.getroot() + for sec in root.iter("section"): + for prop in sec.iter("property"): + self._add_id(prop) + + return tree + + @staticmethod + def _add_id(element): + """ + Checks, whether element possesses ID. If yes, make sure, it has right format. + Otherwise a new UUID is created. + :param element: lxml element. + """ + oid = element.find("id") + new_id = ET.Element("id") + try: + if oid is not None: + try: + if oid.text is not None: + new_id.text = str(uuid.UUID(oid.text)) + except ValueError as e: + print(e) + new_id.text = str(uuid.uuid4()) + element.remove(oid) + else: + new_id.text = str(uuid.uuid4()) + except ValueError as e: + print(e) + new_id.text = str(uuid.uuid4()) + element.append(new_id) + def _log(self, msg): """ Adds the passed message to the conversion_log attribute and diff --git a/test/test_version_converter.py b/test/test_version_converter.py index 29c28ab3..51cb5a17 100644 --- a/test/test_version_converter.py +++ b/test/test_version_converter.py @@ -379,19 +379,21 @@ def test_convert_odml_file_property(self): self.assertEqual(sec[0].find("name").text, "Valid Property tags test") self.assertEqual(len(sec[0].findall("property")), 1) prop = sec[0].find("property") - self.assertEqual(len(prop), 5) + self.assertEqual(len(prop), 6) self.assertEqual(prop.find("name").text, "Property name") self.assertEqual(prop.find("type").text, "Property type") self.assertEqual(prop.find("definition").text, "Property definition") self.assertEqual(prop.find("dependency").text, "Property dependency") self.assertEqual(prop.find("dependencyvalue").text, "Property dependency value") + self.assertEqual(len(prop.findall("id")), 1) # Test non-import of Property w/o name self.assertEqual(len(sec[1].findall("property")), 1) # Test absence of non-Property tags prop = sec[1].find("property") - self.assertEqual(len(prop), 1) + self.assertEqual(len(prop), 2) self.assertEqual(len(prop.findall("name")), 1) + self.assertEqual(len(prop.findall("id")), 1) def test_convert_odml_file_value(self): """Test proper conversion of the odml.Value entity from @@ -511,6 +513,22 @@ def test_convert_odml_file_value(self): 3 int testIntListWhiteSpace + + + Single value with UUID + 1 + aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa + + + + Single value with none-UUID ID + 1 + + + + Single value with empty ID + + @@ -521,26 +539,29 @@ def test_convert_odml_file_value(self): conv_doc = vc._convert(vc._parse_xml()) root = conv_doc.getroot() sec = root.find("section") - self.assertEqual(len(sec), 14) + self.assertEqual(len(sec), 17) # Test single value export prop = sec.findall("property")[0] - self.assertEqual(len(prop), 2) + self.assertEqual(len(prop), 3) self.assertEqual(prop.find("value").text, "1") + self.assertEqual(len(prop.findall("id")), 1) # Test multiple value export prop = sec.findall("property")[1] - self.assertEqual(len(prop), 2) + self.assertEqual(len(prop), 3) self.assertEqual(prop.find("value").text, "[1,2,3]") + self.assertEqual(len(prop.findall("id")), 1) # Test empty value export prop = sec.findall("property")[2] - self.assertEqual(len(prop), 1) + self.assertEqual(len(prop), 2) self.assertEqual(prop.find("name").text, "Empty value export") + self.assertEqual(len(prop.findall("id")), 1) # Test valid Value tags prop = sec.findall("property")[3] - self.assertEqual(len(prop), 7) + self.assertEqual(len(prop), 8) self.assertEqual(prop.find("value").text, "0.1") self.assertEqual(prop.find("type").text, "float") self.assertEqual(prop.find("uncertainty").text, "0.05") @@ -548,58 +569,88 @@ def test_convert_odml_file_value(self): self.assertEqual(prop.find("value_origin").text, "raw.txt") self.assertEqual(prop.find("reference").text, "Value reference") self.assertEqual(len(prop.findall("filename")), 0) + self.assertEqual(len(prop.findall("id")), 1) # Test valid multiple Value tag export prop = sec.findall("property")[4] - self.assertEqual(len(prop), 7) + self.assertEqual(len(prop), 8) self.assertEqual(prop.find("value").text, "[0.1,0.2,3]") self.assertEqual(prop.find("type").text, "float") self.assertEqual(prop.find("uncertainty").text, "0.05") self.assertEqual(prop.find("unit").text, "mV") self.assertEqual(prop.find("value_origin").text, "raw.txt") self.assertEqual(prop.find("reference").text, "Value reference") + self.assertEqual(len(prop.findall("id")), 1) # Test non-export of invalid Value tags prop = sec.findall("property")[5] - self.assertEqual(len(prop), 1) + self.assertEqual(len(prop), 2) self.assertEqual(len(prop.findall("name")), 1) + self.assertEqual(len(prop.findall("id")), 1) # Test dtype 'binary' replacement prop = sec.findall("property")[6] self.assertEqual(prop.find("name").text, "Unsupported binary value type replace") self.assertEqual(prop.find("type").text, "text") + self.assertEqual(len(prop.findall("id")), 1) prop = sec.findall("property")[7] self.assertEqual(prop.find("name").text, "Unsupported binary value dtype replace") self.assertEqual(prop.find("type").text, "text") + self.assertEqual(len(prop.findall("id")), 1) # Test single string value with commata prop = sec.findall("property")[8] self.assertEqual(prop.find("name").text, "testSingleString") self.assertEqual(prop.find("value").text, "Single, string, value, with, many, commata.") + self.assertEqual(len(prop.findall("id")), 1) # Test string list import prop = sec.findall("property")[9] self.assertEqual(prop.find("name").text, "testStringList") self.assertEqual(prop.find("value").text, "[A,B,C]") + self.assertEqual(len(prop.findall("id")), 1) # Test single string values wrapping whitespace removal prop = sec.findall("property")[10] self.assertEqual(prop.find("name").text, "testStringWhiteSpace") self.assertEqual(prop.find("value").text, "Single string value with wrapping whitespace") + self.assertEqual(len(prop.findall("id")), 1) # Test multiple string values with wrapping whitespace removal prop = sec.findall("property")[11] self.assertEqual(prop.find("name").text, "testStringListWhiteSpace") self.assertEqual(prop.find("value").text, "[Multiple Strings,with wrapping,Whitespace]") + self.assertEqual(len(prop.findall("id")), 1) # Test multiple int values with wrapping whitespaces prop = sec.findall("property")[12] self.assertEqual(prop.find("name").text, "testIntListWhiteSpace") self.assertEqual(prop.find("type").text, "int") self.assertEqual(prop.find("value").text, "[1,2,3]") + self.assertEqual(len(prop.findall("id")), 1) + + # Test single value export + prop = sec.findall("property")[13] + self.assertEqual(len(prop), 3) + self.assertEqual(prop.find("value").text, "1") + self.assertEqual(len(prop.findall("id")), 1) + self.assertEqual(prop.find("id").text, "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa") + + # Test single value export + prop = sec.findall("property")[14] + self.assertEqual(len(prop), 2) + self.assertEqual(len(prop.findall("id")), 1) + self.assertNotEqual(prop.find("id").text, "1") + + # Test single value export + prop = sec.findall("property")[15] + self.assertEqual(len(prop), 2) + self.assertEqual(len(prop.findall("id")), 1) + self.assertNotEqual(prop.find("id").text, "1") + def test_parse_dict_document(self): # Test appending tags; not appending empty sections From 31f1aab02c19e430a1707e08429c9c75cd035327 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 13 Jun 2019 00:14:27 +0200 Subject: [PATCH 02/13] [version_converter] Automatically Add UUIDs For Sections Adding UUIDs, when converting from odML version 1.0 to 1.1. If an ID already exists, it stays the same, if it is compatible with the python uuid types. Otherwise (also if empty) a new ID is created for the section. --- odml/tools/version_converter.py | 1 + test/test_version_converter.py | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/odml/tools/version_converter.py b/odml/tools/version_converter.py index 28638eb6..75b334d3 100644 --- a/odml/tools/version_converter.py +++ b/odml/tools/version_converter.py @@ -423,6 +423,7 @@ def _check_add_ids(self, tree): """ root = tree.getroot() for sec in root.iter("section"): + self._add_id(sec) for prop in sec.iter("property"): self._add_id(prop) diff --git a/test/test_version_converter.py b/test/test_version_converter.py index 51cb5a17..fa81aab0 100644 --- a/test/test_version_converter.py +++ b/test/test_version_converter.py @@ -276,7 +276,7 @@ def test_convert_odml_file_section(self): self.assertEqual(len(sec), 2) # Test valid section tags. - self.assertEqual(len(sec[0]), 10) + self.assertEqual(len(sec[0]), 11) self.assertEqual(sec[0].find("name").text, "Section name") self.assertEqual(sec[0].find("type").text, "Section type") self.assertEqual(sec[0].find("definition").text, "Section definition") @@ -286,10 +286,11 @@ def test_convert_odml_file_section(self): self.assertEqual(sec[0].find("include").text, "Section include") self.assertEqual(len(sec[0].findall("property")), 2) self.assertEqual(len(sec[0].findall("section")), 1) + self.assertEqual(len(sec[0].findall("id")), 1) # Test valid subsection tags. subsec = sec[0].find("section") - self.assertEqual(len(subsec), 8) + self.assertEqual(len(subsec), 9) self.assertEqual(subsec.find("name").text, "SubSection name") self.assertEqual(subsec.find("type").text, "SubSection type") self.assertEqual(subsec.find("definition").text, "SubSection definition") @@ -298,10 +299,12 @@ def test_convert_odml_file_section(self): self.assertEqual(subsec.find("repository").text, local_url) self.assertEqual(subsec.find("include").text, "SubSection include") self.assertEqual(len(subsec.findall("property")), 1) + self.assertEqual(len(subsec.findall("id")), 1) # Test absence of non-Section tags - self.assertEqual(len(sec[1]), 1) + self.assertEqual(len(sec[1]), 2) self.assertEqual(len(sec[1].findall("name")), 1) + self.assertEqual(len(sec[1].findall("id")), 1) # Test presence of v1.0 repository tag and warning log entry doc = """ @@ -539,7 +542,8 @@ def test_convert_odml_file_value(self): conv_doc = vc._convert(vc._parse_xml()) root = conv_doc.getroot() sec = root.find("section") - self.assertEqual(len(sec), 17) + self.assertEqual(len(sec), 18) + self.assertEqual(len(sec.findall("id")), 1) # Test single value export prop = sec.findall("property")[0] From 34260a322e279cbfa7fe87ecadb71577abd49b4b Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 13 Jun 2019 00:19:05 +0200 Subject: [PATCH 03/13] [version_converter] Automatically Add UUIDs For Document Adding UUIDs, when converting from odML version 1.0 to 1.1. If an ID already exists, it stays the same, if it is compatible with the python uuid types. Otherwise (also if empty) a new ID is created for the document. --- odml/tools/version_converter.py | 1 + test/test_version_converter.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/odml/tools/version_converter.py b/odml/tools/version_converter.py index 75b334d3..570ad709 100644 --- a/odml/tools/version_converter.py +++ b/odml/tools/version_converter.py @@ -422,6 +422,7 @@ def _check_add_ids(self, tree): :return: ElementTree """ root = tree.getroot() + self._add_id(root) for sec in root.iter("section"): self._add_id(sec) for prop in sec.iter("property"): diff --git a/test/test_version_converter.py b/test/test_version_converter.py index fa81aab0..8b166e47 100644 --- a/test/test_version_converter.py +++ b/test/test_version_converter.py @@ -272,6 +272,8 @@ def test_convert_odml_file_section(self): conv_doc = vc._convert(vc._parse_xml()) root = conv_doc.getroot() + root_id = root.findall("id") + self.assertEqual(len(root_id), 1) sec = root.findall("section") self.assertEqual(len(sec), 2) @@ -541,6 +543,8 @@ def test_convert_odml_file_value(self): vc = self.VC(file) conv_doc = vc._convert(vc._parse_xml()) root = conv_doc.getroot() + root_id = root.findall("id") + self.assertEqual(len(root_id), 1) sec = root.find("section") self.assertEqual(len(sec), 18) self.assertEqual(len(sec.findall("id")), 1) From b0170a86b573274508c802b5192d86483926b98a Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 18 Jun 2019 14:44:38 +0200 Subject: [PATCH 04/13] [version_converter] Reduce Redundancy Reduce redundancy in _add_id. --- odml/tools/version_converter.py | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/odml/tools/version_converter.py b/odml/tools/version_converter.py index 570ad709..bad6dfca 100644 --- a/odml/tools/version_converter.py +++ b/odml/tools/version_converter.py @@ -432,27 +432,22 @@ def _check_add_ids(self, tree): @staticmethod def _add_id(element): + """ - Checks, whether element possesses ID. If yes, make sure, it has right format. - Otherwise a new UUID is created. + Checks, whether an element possesses an ID. If yes, make sure it has + the right format. Otherwise a new UUID is created. :param element: lxml element. """ oid = element.find("id") new_id = ET.Element("id") - try: - if oid is not None: - try: - if oid.text is not None: - new_id.text = str(uuid.UUID(oid.text)) - except ValueError as e: - print(e) - new_id.text = str(uuid.uuid4()) - element.remove(oid) - else: - new_id.text = str(uuid.uuid4()) - except ValueError as e: - print(e) - new_id.text = str(uuid.uuid4()) + new_id.text = str(uuid.uuid4()) + if oid is not None: + try: + if oid.text is not None: + new_id.text = str(uuid.UUID(oid.text)) + except ValueError as e: + print(e) + element.remove(oid) element.append(new_id) def _log(self, msg): From 9915a72d5c763227bc6abaa49831974284544d37 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 18 Jun 2019 15:56:14 +0200 Subject: [PATCH 05/13] [doc] Add Pretty Print Add pprint method showing document information and section/ property tree. Related to issue #319. --- odml/doc.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/odml/doc.py b/odml/doc.py index 279a9b2c..4a33ccea 100644 --- a/odml/doc.py +++ b/odml/doc.py @@ -141,3 +141,21 @@ def get_terminology_equivalent(self): return None term = terminology.load(self.repository) return term +def pprint(self, indent=2, max_depth=1, max_length=80, current_depth=0): + """ + Pretty print method to visualize Document-Section trees. + + :param indent: number of leading spaces for every child Section or Property. + :param max_depth: maximum number of hierarchical levels printed from the + starting Section. + :param max_length: maximum number of characters printed in one line. + :param current_depth: number of hierarchical levels printed from the + starting Section. + """ + doc_str = "[{} [{}] {}, sections: {}, repository: {}]".format(self.author, self.version, + self.date, len(self._sections), self.repository) + print(doc_str) + + for s in self._sections: + s.pprint(current_depth=current_depth+1, max_depth=max_depth, + indent=indent, max_length=max_length) From 45d2b98f7f82bb191195fcb9a87b75dc6d93ae0b Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 18 Jun 2019 16:06:58 +0200 Subject: [PATCH 06/13] [property] Add Value 0 as Int Allow value = 0 set as int, not as empty value. Fixing issue #314. --- odml/property.py | 2 +- test/test_property.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/odml/property.py b/odml/property.py index 5da97893..ba698e38 100644 --- a/odml/property.py +++ b/odml/property.py @@ -82,7 +82,7 @@ def __init__(self, name=None, values=None, parent=None, unit=None, self._values = [] self.values = values - if not values and (value or isinstance(value, bool)): + if not values and (value or isinstance(value, bool) or isinstance(value, int)): self.values = value self.parent = parent diff --git a/test/test_property.py b/test/test_property.py index 80a67d61..fb218c19 100644 --- a/test/test_property.py +++ b/test/test_property.py @@ -183,6 +183,10 @@ def test_value_append(self): self.assertEqual(len(p5), 2) self.assertRaises(ValueError, p5.append, "[a, b, c]") + p6 = Property('myprop', value=0, dtype=DType.int) + self.assertEqual(p6.value, [0]) + self.assertEqual(p6.values, [0]) + def test_value_extend(self): prop = Property(name="extend") From 4d598c8a7283ada409ced357a5b7c2898a45853c Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 18 Jun 2019 16:17:58 +0200 Subject: [PATCH 07/13] [property] Change DType Confirmation Changing dtype confirmation, adding exceptions for dtypes possessing string type values to allow appending with new values. Fixing issue #318. --- odml/property.py | 7 +++++-- test/test_property.py | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/odml/property.py b/odml/property.py index ba698e38..96af7533 100644 --- a/odml/property.py +++ b/odml/property.py @@ -617,9 +617,12 @@ def append(self, obj, strict=True): if len(new_value) > 1: raise ValueError("odml.property.append: Use extend to add a list of values!") + special_dtypes = ["url", "person", "text"] if len(new_value) > 0 and strict and dtypes.infer_dtype(new_value[0]) != self.dtype: - raise ValueError("odml.Property.append: " - "passed value data type does not match dtype!") + + if not (dtypes.infer_dtype(new_value[0]) == "string" and self.dtype in special_dtypes): + raise ValueError("odml.Property.append: " + "passed value data type does not match dtype!") if not self._validate_values(new_value): raise ValueError("odml.Property.append: passed value(s) cannot be converted " diff --git a/test/test_property.py b/test/test_property.py index fb218c19..15c06c1a 100644 --- a/test/test_property.py +++ b/test/test_property.py @@ -187,6 +187,27 @@ def test_value_append(self): self.assertEqual(p6.value, [0]) self.assertEqual(p6.values, [0]) + p7 = Property(name="prop", value=["A Abraham", "B Barnes", "C Clark"], dtype=DType.person) + p7.append("D Dickins") + self.assertEqual(len(p7), 4) + self.assertRaises(ValueError, p7.append, 1) + self.assertRaises(ValueError, p7.append, 1.3) + self.assertRaises(ValueError, p7.append, True) + + p8 = Property(name="prop", value=["https://en.wikipedia.org/wiki/Earth"], dtype=DType.url) + p8.append("https://en.wikipedia.org/wiki/Mars") + self.assertEqual(len(p8), 2) + self.assertRaises(ValueError, p8.append, 1) + self.assertRaises(ValueError, p8.append, 1.3) + self.assertRaises(ValueError, p8.append, True) + + p9 = Property(name="prop", value=["Earth is No. 3."], dtype=DType.text) + p9.append("Mars is No. 4.") + self.assertEqual(len(p9), 2) + self.assertRaises(ValueError, p9.append, 1) + self.assertRaises(ValueError, p9.append, 1.3) + self.assertRaises(ValueError, p9.append, True) + def test_value_extend(self): prop = Property(name="extend") From 70ebb0d4fcb3a0cb1bbf1a113cbd4c64323cbd7d Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 18 Jun 2019 16:27:16 +0200 Subject: [PATCH 08/13] [property] Change DType Confirmation for Extend Changing dtype confirmation, adding exceptions for dtypes possessing string type values to allow expending with new values. Related to issue #318. --- odml/property.py | 7 +++++-- test/test_property.py | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/odml/property.py b/odml/property.py index 96af7533..5793927c 100644 --- a/odml/property.py +++ b/odml/property.py @@ -587,9 +587,12 @@ def extend(self, obj, strict=True): return new_value = self._convert_value_input(obj) + special_dtypes = ["url", "person", "text"] if len(new_value) > 0 and strict and dtypes.infer_dtype(new_value[0]) != self.dtype: - raise ValueError("odml.Property.extend: " - "passed value data type does not match dtype!") + + if not (dtypes.infer_dtype(new_value[0]) == "string" and self.dtype in special_dtypes): + raise ValueError("odml.Property.extend: " + "passed value data type does not match dtype!") if not self._validate_values(new_value): raise ValueError("odml.Property.extend: passed value(s) cannot be converted " diff --git a/test/test_property.py b/test/test_property.py index 15c06c1a..555ddf70 100644 --- a/test/test_property.py +++ b/test/test_property.py @@ -285,6 +285,27 @@ def test_value_extend(self): with self.assertRaises(ValueError): prop.extend([6, "some text"]) + p1 = Property(name="prop", value=["A Abraham", "B Barnes", "C Clark"], dtype=DType.person) + p1.extend("D Dickins") + self.assertEqual(len(p1), 4) + self.assertRaises(ValueError, p1.extend, 1) + self.assertRaises(ValueError, p1.extend, 1.3) + self.assertRaises(ValueError, p1.extend, True) + + p2 = Property(name="prop", value=["https://en.wikipedia.org/wiki/Earth"], dtype=DType.url) + p2.extend("https://en.wikipedia.org/wiki/Mars") + self.assertEqual(len(p2), 2) + self.assertRaises(ValueError, p2.append, 1) + self.assertRaises(ValueError, p2.append, 1.3) + self.assertRaises(ValueError, p2.append, True) + + p3 = Property(name="prop", value=["Earth is No. 3."], dtype=DType.text) + p3.extend("Mars is No. 4.") + self.assertEqual(len(p3), 2) + self.assertRaises(ValueError, p3.append, 1) + self.assertRaises(ValueError, p3.append, 1.3) + self.assertRaises(ValueError, p3.append, True) + def test_get_set_value(self): values = [1, 2, 3, 4, 5] p = Property("property", value=values) From 387049b4b43c5220babd8452da42abdaaaa1b89d Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 18 Jun 2019 16:46:26 +0200 Subject: [PATCH 09/13] [property] Move special_dtypes Definition to dtypes.py Related to issue #318. --- odml/dtypes.py | 2 ++ odml/property.py | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/odml/dtypes.py b/odml/dtypes.py index c6e27c3d..69cae553 100644 --- a/odml/dtypes.py +++ b/odml/dtypes.py @@ -62,6 +62,8 @@ def default_values(dtype): _dtype_map = {'str': 'string', 'bool': 'boolean'} +special_dtypes = ["url", "person", "text"] + def infer_dtype(value): dtype = (type(value)).__name__ diff --git a/odml/property.py b/odml/property.py index 5793927c..4266096c 100644 --- a/odml/property.py +++ b/odml/property.py @@ -587,10 +587,9 @@ def extend(self, obj, strict=True): return new_value = self._convert_value_input(obj) - special_dtypes = ["url", "person", "text"] if len(new_value) > 0 and strict and dtypes.infer_dtype(new_value[0]) != self.dtype: - if not (dtypes.infer_dtype(new_value[0]) == "string" and self.dtype in special_dtypes): + if not (dtypes.infer_dtype(new_value[0]) == "string" and self.dtype in dtypes.special_dtypes): raise ValueError("odml.Property.extend: " "passed value data type does not match dtype!") @@ -620,10 +619,9 @@ def append(self, obj, strict=True): if len(new_value) > 1: raise ValueError("odml.property.append: Use extend to add a list of values!") - special_dtypes = ["url", "person", "text"] if len(new_value) > 0 and strict and dtypes.infer_dtype(new_value[0]) != self.dtype: - if not (dtypes.infer_dtype(new_value[0]) == "string" and self.dtype in special_dtypes): + if not (dtypes.infer_dtype(new_value[0]) == "string" and self.dtype in dtypes.special_dtypes): raise ValueError("odml.Property.append: " "passed value data type does not match dtype!") From 7df7b9289d5bb8791755e6a1308b028bec404775 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 18 Jun 2019 17:05:03 +0200 Subject: [PATCH 10/13] [property_test] Move Value Test --- test/test_property.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/test_property.py b/test/test_property.py index 555ddf70..d0811ccc 100644 --- a/test/test_property.py +++ b/test/test_property.py @@ -103,6 +103,10 @@ def test_value(self): with self.assertRaises(ValueError): _ = Property(name="Public-Key", value='(5689; 1254; 687)', dtype='2-tuple') + p3 = Property('myprop', value=0, dtype=DType.int) + self.assertEqual(p3.value, [0]) + self.assertEqual(p3.values, [0]) + def test_value_append(self): # Test append w/o Property value or dtype prop = Property(name="append") @@ -183,31 +187,27 @@ def test_value_append(self): self.assertEqual(len(p5), 2) self.assertRaises(ValueError, p5.append, "[a, b, c]") - p6 = Property('myprop', value=0, dtype=DType.int) - self.assertEqual(p6.value, [0]) - self.assertEqual(p6.values, [0]) + p6 = Property(name="prop", value=["A Abraham", "B Barnes", "C Clark"], dtype=DType.person) + p6.append("D Dickins") + self.assertEqual(len(p6), 4) + self.assertRaises(ValueError, p6.append, 1) + self.assertRaises(ValueError, p6.append, 1.3) + self.assertRaises(ValueError, p6.append, True) - p7 = Property(name="prop", value=["A Abraham", "B Barnes", "C Clark"], dtype=DType.person) - p7.append("D Dickins") - self.assertEqual(len(p7), 4) + p7 = Property(name="prop", value=["https://en.wikipedia.org/wiki/Earth"], dtype=DType.url) + p7.append("https://en.wikipedia.org/wiki/Mars") + self.assertEqual(len(p7), 2) self.assertRaises(ValueError, p7.append, 1) self.assertRaises(ValueError, p7.append, 1.3) self.assertRaises(ValueError, p7.append, True) - p8 = Property(name="prop", value=["https://en.wikipedia.org/wiki/Earth"], dtype=DType.url) - p8.append("https://en.wikipedia.org/wiki/Mars") + p8 = Property(name="prop", value=["Earth is No. 3."], dtype=DType.text) + p8.append("Mars is No. 4.") self.assertEqual(len(p8), 2) self.assertRaises(ValueError, p8.append, 1) self.assertRaises(ValueError, p8.append, 1.3) self.assertRaises(ValueError, p8.append, True) - p9 = Property(name="prop", value=["Earth is No. 3."], dtype=DType.text) - p9.append("Mars is No. 4.") - self.assertEqual(len(p9), 2) - self.assertRaises(ValueError, p9.append, 1) - self.assertRaises(ValueError, p9.append, 1.3) - self.assertRaises(ValueError, p9.append, True) - def test_value_extend(self): prop = Property(name="extend") From 55a99b730f1dbbed14b791bd6b390670c474d321 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 9 Jul 2019 23:10:27 +0200 Subject: [PATCH 11/13] [tools/version_converter] Remove Blank Line --- odml/tools/version_converter.py | 1 - 1 file changed, 1 deletion(-) diff --git a/odml/tools/version_converter.py b/odml/tools/version_converter.py index bad6dfca..c7b22ab4 100644 --- a/odml/tools/version_converter.py +++ b/odml/tools/version_converter.py @@ -432,7 +432,6 @@ def _check_add_ids(self, tree): @staticmethod def _add_id(element): - """ Checks, whether an element possesses an ID. If yes, make sure it has the right format. Otherwise a new UUID is created. From 09dc84e5c2389cf6add0b0104c538fd32dfa1747 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 9 Jul 2019 23:20:56 +0200 Subject: [PATCH 12/13] [test_property] Add Values Test for Boolean DType --- test/test_property.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/test_property.py b/test/test_property.py index d0811ccc..80f6c1cc 100644 --- a/test/test_property.py +++ b/test/test_property.py @@ -107,6 +107,14 @@ def test_value(self): self.assertEqual(p3.value, [0]) self.assertEqual(p3.values, [0]) + p4 = Property('myprop', value=0, dtype=DType.boolean) + self.assertEqual(p4.value, [False]) + self.assertEqual(p4.values, [False]) + + p5 = Property('myprop', value=0) + self.assertEqual(p5.value, [0]) + self.assertEqual(p5.values, [0]) + def test_value_append(self): # Test append w/o Property value or dtype prop = Property(name="append") From b754b3c2e9346440349b2f8482a61e2225c62642 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 9 Jul 2019 23:43:50 +0200 Subject: [PATCH 13/13] [property] Add DType Failure Information For append and extend methods, inferred and expected dtype are listed. --- odml/property.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/odml/property.py b/odml/property.py index 4266096c..a120ab38 100644 --- a/odml/property.py +++ b/odml/property.py @@ -590,8 +590,8 @@ def extend(self, obj, strict=True): if len(new_value) > 0 and strict and dtypes.infer_dtype(new_value[0]) != self.dtype: if not (dtypes.infer_dtype(new_value[0]) == "string" and self.dtype in dtypes.special_dtypes): - raise ValueError("odml.Property.extend: " - "passed value data type does not match dtype!") + raise ValueError("odml.Property.extend: passed value data type found (\"%s\") " + "does not match expected dtype \"%s\"!" % (dtypes.infer_dtype(new_value[0]), self._dtype)) if not self._validate_values(new_value): raise ValueError("odml.Property.extend: passed value(s) cannot be converted " @@ -622,8 +622,8 @@ def append(self, obj, strict=True): if len(new_value) > 0 and strict and dtypes.infer_dtype(new_value[0]) != self.dtype: if not (dtypes.infer_dtype(new_value[0]) == "string" and self.dtype in dtypes.special_dtypes): - raise ValueError("odml.Property.append: " - "passed value data type does not match dtype!") + raise ValueError("odml.Property.append: passed value data type found (\"%s\") " + "does not match expected dtype \"%s\"!" % (dtypes.infer_dtype(new_value[0]), self._dtype)) if not self._validate_values(new_value): raise ValueError("odml.Property.append: passed value(s) cannot be converted "