From 81d7cf39035523ba1d312ddeffba0d49f4337af1 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 9 Jan 2020 00:11:43 +0100 Subject: [PATCH 01/15] [property] Add Leaf-Export Method to export single leaf of odml document, starting at specified property. --- odml/property.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/odml/property.py b/odml/property.py index a120ab38..d4d1b031 100644 --- a/odml/property.py +++ b/odml/property.py @@ -662,3 +662,19 @@ def pprint(self, indent=2, max_length=80, current_depth=-1): else: print(("{}{} {}: {}".format(property_spaces, prefix, self.name, value_string))) + + def export_leaf(self): + """ + Export leaf, start at property. + """ + orig = self.parent + child = self.clone(keep_id=True) + par = child + + while orig is not None: + par = orig.clone(children=False, keep_id=True) + par.append(child) + child = par + orig = orig.parent + + return par From a16515342d02bef89416a1e5ba01bb8eb5652da4 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 9 Jan 2020 00:13:42 +0100 Subject: [PATCH 02/15] [section] Add Leaf-Export Method to export single leaf of odml document, starting at specified section. Includes properties of selected section, but no subsections. --- odml/section.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/odml/section.py b/odml/section.py index f27c724b..40e7f228 100644 --- a/odml/section.py +++ b/odml/section.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 import collections import uuid +from copy import deepcopy from . import base from . import format @@ -638,3 +639,23 @@ def pprint(self, indent=2, max_depth=1, max_length=80, current_depth=0): print("{} {} [{}]\n{}[...]".format(child_sec_indent, s.name, s.type, more_indent)) + + def export_leaf(self): + """ + Export leaf, start at section. Includes section properties, not subsections. + """ + curr = self.parent + child = self.clone(children=False, keep_id=True) + + for prop in self.properties: + child.append(prop.clone(keep_id=True)) + + par = child + + while curr is not None: + par = curr.clone(children=False, keep_id=True) + par.append(child) + child = par + curr = curr.parent + + return par From 77df9c4f8868ecc21f8d4fe478b6abc0fac5944b Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 9 Jan 2020 00:14:22 +0100 Subject: [PATCH 03/15] [test-property] Add Test for Leaf-Export --- test/test_property.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/test_property.py b/test/test_property.py index 80f6c1cc..60ae3345 100644 --- a/test/test_property.py +++ b/test/test_property.py @@ -733,6 +733,34 @@ def test_comparison(self): prop_b.name = 'newPropertyName' self.assertNotEqual(prop_a, prop_b) + def test_export_leaf(self): + doc = Document() + first = doc.create_section("first") + second = first.create_section("second") + first.create_section("third") + + name = "prop1" + values = [1.3] + first.create_property(name, value=values) + + name = "prop2" + values = ["words"] + second.create_property(name, value=values) + + name = "prop3" + values = ["a", "b"] + second.create_property(name, value=values) + + name = "prop4" + values = [3] + second.create_property(name, value=values) + + ex = second.properties["prop2"].export_leaf() + self.assertEqual(len(ex.sections), 1) + self.assertEqual(len(ex['first'].properties), 0) + self.assertEqual(len(ex['first'].sections), 1) + self.assertEqual(len(ex['first']['second'].properties), 1) + if __name__ == "__main__": print("TestProperty") From 1231d2f22590d3e3a4dd92c6991ece12b184e6bb Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 9 Jan 2020 00:14:45 +0100 Subject: [PATCH 04/15] [test-section] Add Test for Leaf-Export --- test/test_section.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/test_section.py b/test/test_section.py index ba4e3743..c2a9d908 100644 --- a/test/test_section.py +++ b/test/test_section.py @@ -943,6 +943,41 @@ def test_create_property(self): prop = root.create_property(name, dtype=dtype) self.assertIsNone(prop.dtype) + def test_export_leaf(self): + doc = Document() + first = doc.create_section("first") + second = first.create_section("second") + third = first.create_section("third") + + name = "prop1" + values = [1.3] + first.create_property(name, value=values) + + name = "prop2" + values = ["words"] + first.create_property(name, value=values) + + name = "prop3" + values = ["a", "b"] + second.create_property(name, value=values) + + ex1 = first.export_leaf() + self.assertEqual(len(ex1.sections), 1) + self.assertEqual(len(ex1['first'].properties), 2) + self.assertEqual(len(ex1['first'].sections), 0) + + ex2 = second.export_leaf() + self.assertEqual(len(ex2.sections), 1) + self.assertEqual(len(ex2['first'].properties), 0) + self.assertEqual(len(ex2['first'].sections), 1) + self.assertEqual(len(ex2['first']['second'].properties), 1) + + ex3 = third.export_leaf() + self.assertEqual(len(ex3.sections), 1) + self.assertEqual(len(ex3['first'].properties), 0) + self.assertEqual(len(ex3['first'].sections), 1) + self.assertEqual(len(ex3['first']['third']), 0) + def test_link(self): pass From 82ed96cc740e6b4a85d3beed87db04c241511819 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 9 Jan 2020 17:29:29 +0100 Subject: [PATCH 05/15] [property] Specify ValueError Message If format of value is wrong, e.g. with date, more info is given. --- odml/property.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/odml/property.py b/odml/property.py index d4d1b031..7bfa219e 100644 --- a/odml/property.py +++ b/odml/property.py @@ -247,6 +247,9 @@ def _validate_values(self, values): try: dtypes.get(v, self.dtype) except Exception: + raise ValueError("odml.Property.values: passed value \'%s\' are not of " + "consistent type \'%s\'! Format should be \'%s\'." % + (v, self._dtype, dtypes.default_values(self._dtype))) return False return True @@ -327,9 +330,7 @@ def values(self, new_value): if self._dtype is None: self._dtype = dtypes.infer_dtype(new_value[0]) - if not self._validate_values(new_value): - raise ValueError("odml.Property.values: passed values are not of " - "consistent type!") + self._validate_values(new_value) self._values = [dtypes.get(v, self.dtype) for v in new_value] @property From c6f5617dffb8cb96f4c5c003b5605be3ef453aaa Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 9 Jan 2020 17:30:39 +0100 Subject: [PATCH 06/15] [test-property] Add Tests for Wrong Value Formats --- test/test_property.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/test_property.py b/test/test_property.py index 60ae3345..717e7dde 100644 --- a/test/test_property.py +++ b/test/test_property.py @@ -1,5 +1,7 @@ import unittest +import datetime + from odml import Property, Section, Document, DType from odml.property import BaseProperty from odml.section import BaseSection @@ -115,6 +117,19 @@ def test_value(self): self.assertEqual(p5.value, [0]) self.assertEqual(p5.values, [0]) + with self.assertRaises(ValueError): + Property(name="dateprop", dtype=DType.time, value=['20190707']) + + with self.assertRaises(ValueError): + Property(name="timeprop", dtype=DType.time, value=['11.11.11']) + + with self.assertRaises(ValueError): + Property(name="datetimeprop", dtype=DType.datetime, value=['20190707']) + + with self.assertRaises(ValueError): + Property(name="intprop", dtype=DType.int, value=[2, "Hello!", 4]) + + def test_value_append(self): # Test append w/o Property value or dtype prop = Property(name="append") From 4c007c406dc8a5e147d8aeb3c3bc505537ad8c7a Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Fri, 17 Jan 2020 22:20:06 +0100 Subject: [PATCH 07/15] [section] Include Parent Properties in Leaf Export --- odml/section.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/odml/section.py b/odml/section.py index 40e7f228..e8a47fa3 100644 --- a/odml/section.py +++ b/odml/section.py @@ -644,17 +644,17 @@ def export_leaf(self): """ Export leaf, start at section. Includes section properties, not subsections. """ - curr = self.parent - child = self.clone(children=False, keep_id=True) - - for prop in self.properties: - child.append(prop.clone(keep_id=True)) - - par = child + curr = self + par = self + child = self while curr is not None: par = curr.clone(children=False, keep_id=True) - par.append(child) + if curr != self: + par.append(child) + if hasattr(curr, 'properties'): + for prop in curr.properties: + par.append(prop.clone(keep_id=True)) child = par curr = curr.parent From 724d8a49cf70391bcef1c205168f39671e8916b6 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Fri, 17 Jan 2020 22:21:03 +0100 Subject: [PATCH 08/15] [test_section] Adapt Test for Leaf Export Parent Properties --- test/test_section.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_section.py b/test/test_section.py index c2a9d908..ae990199 100644 --- a/test/test_section.py +++ b/test/test_section.py @@ -968,13 +968,13 @@ def test_export_leaf(self): ex2 = second.export_leaf() self.assertEqual(len(ex2.sections), 1) - self.assertEqual(len(ex2['first'].properties), 0) + self.assertEqual(len(ex2['first'].properties), 2) self.assertEqual(len(ex2['first'].sections), 1) self.assertEqual(len(ex2['first']['second'].properties), 1) ex3 = third.export_leaf() self.assertEqual(len(ex3.sections), 1) - self.assertEqual(len(ex3['first'].properties), 0) + self.assertEqual(len(ex3['first'].properties), 2) self.assertEqual(len(ex3['first'].sections), 1) self.assertEqual(len(ex3['first']['third']), 0) From d0d5d9ce829c3be1cf071989556233aa72b6dfd4 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Fri, 17 Jan 2020 22:21:31 +0100 Subject: [PATCH 09/15] [property] Include Parent Properties in Leaf Export --- odml/property.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/odml/property.py b/odml/property.py index 7bfa219e..f3313cb4 100644 --- a/odml/property.py +++ b/odml/property.py @@ -668,14 +668,21 @@ def export_leaf(self): """ Export leaf, start at property. """ - orig = self.parent - child = self.clone(keep_id=True) - par = child - - while orig is not None: - par = orig.clone(children=False, keep_id=True) - par.append(child) + curr = self.parent + par = self.parent + child = self.parent + + while curr is not None: + par = curr.clone(children=False, keep_id=True) + if curr != self.parent: + par.append(child) + if hasattr(curr, 'properties'): + if curr == self.parent: + par.append(self.clone(keep_id=True)) + else: + for prop in curr.properties: + par.append(prop.clone(keep_id=True)) child = par - orig = orig.parent + curr = curr.parent - return par + return par \ No newline at end of file From 537703e6f512f96e7874c5eab94f5a09b2ec8032 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Fri, 17 Jan 2020 22:22:03 +0100 Subject: [PATCH 10/15] [test_property] Adapt Test for Leaf Export Parent Properties --- test/test_property.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/test/test_property.py b/test/test_property.py index 717e7dde..5de60fad 100644 --- a/test/test_property.py +++ b/test/test_property.py @@ -770,11 +770,19 @@ def test_export_leaf(self): values = [3] second.create_property(name, value=values) - ex = second.properties["prop2"].export_leaf() - self.assertEqual(len(ex.sections), 1) - self.assertEqual(len(ex['first'].properties), 0) - self.assertEqual(len(ex['first'].sections), 1) - self.assertEqual(len(ex['first']['second'].properties), 1) + name = "prop5" + values = ["abc"] + first.create_property(name, value=values) + + ex1 = first.properties["prop1"].export_leaf() + self.assertEqual(len(ex1['first'].properties), 1) + self.assertEqual(len(ex1['first'].sections), 0) + + ex2 = second.properties["prop2"].export_leaf() + self.assertEqual(len(ex2.sections), 1) + self.assertEqual(len(ex2['first'].properties), 2) + self.assertEqual(len(ex2['first'].sections), 1) + self.assertEqual(len(ex2['first']['second'].properties), 1) if __name__ == "__main__": From f35a534b3d46ada7ca9f9021d500374da91d4cf4 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Fri, 17 Jan 2020 23:12:12 +0100 Subject: [PATCH 11/15] [section] Remove Unused Import --- odml/section.py | 1 - 1 file changed, 1 deletion(-) diff --git a/odml/section.py b/odml/section.py index e8a47fa3..ac5a0e18 100644 --- a/odml/section.py +++ b/odml/section.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 import collections import uuid -from copy import deepcopy from . import base from . import format From 23a3d452f5cae5c27349b24fcfddc919b645c771 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Fri, 17 Jan 2020 23:22:20 +0100 Subject: [PATCH 12/15] [section] Change export_leaf Comment --- odml/section.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/odml/section.py b/odml/section.py index ac5a0e18..c195f4be 100644 --- a/odml/section.py +++ b/odml/section.py @@ -641,7 +641,8 @@ def pprint(self, indent=2, max_depth=1, max_length=80, current_depth=0): def export_leaf(self): """ - Export leaf, start at section. Includes section properties, not subsections. + Export only the path from this section to the root. + Include all properties for all sections, but no other subsections. """ curr = self par = self From 5797d20f6bab4184e61c7df95f1d96b610feba88 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Fri, 17 Jan 2020 23:24:38 +0100 Subject: [PATCH 13/15] [property] Change export_leaf Comment and Newline --- odml/property.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/odml/property.py b/odml/property.py index f3313cb4..35e4648c 100644 --- a/odml/property.py +++ b/odml/property.py @@ -666,7 +666,8 @@ def pprint(self, indent=2, max_length=80, current_depth=-1): def export_leaf(self): """ - Export leaf, start at property. + Export only the path from this property to the root. + Include all properties of parent sections. """ curr = self.parent par = self.parent @@ -685,4 +686,4 @@ def export_leaf(self): child = par curr = curr.parent - return par \ No newline at end of file + return par From f30bb0474ae55b1388649ed7c887d00201027828 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 21 Jan 2020 18:03:52 +0100 Subject: [PATCH 14/15] [property] Change values Validation Error Message Move from _validate_values and check only for dtypes "date", "time" and "datetime". --- odml/property.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/odml/property.py b/odml/property.py index 35e4648c..8801325d 100644 --- a/odml/property.py +++ b/odml/property.py @@ -247,9 +247,6 @@ def _validate_values(self, values): try: dtypes.get(v, self.dtype) except Exception: - raise ValueError("odml.Property.values: passed value \'%s\' are not of " - "consistent type \'%s\'! Format should be \'%s\'." % - (v, self._dtype, dtypes.default_values(self._dtype))) return False return True @@ -330,7 +327,14 @@ def values(self, new_value): if self._dtype is None: self._dtype = dtypes.infer_dtype(new_value[0]) - self._validate_values(new_value) + if not self._validate_values(new_value): + if self._dtype in ("date", "time", "datetime"): + raise ValueError("odml.Property.values: passed values are not of " + "consistent type \'%s\'! Format should be \'%s\'." % + (self._dtype, dtypes.default_values(self._dtype))) + else: + raise ValueError("odml.Property.values: passed values are not of " + "consistent type!") self._values = [dtypes.get(v, self.dtype) for v in new_value] @property From 9095664d6a7995eff17357114bc61e57b54c63fc Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 21 Jan 2020 18:04:46 +0100 Subject: [PATCH 15/15] [test_property] Fix Wrong Test Dtype --- test/test_property.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_property.py b/test/test_property.py index 5de60fad..95048f17 100644 --- a/test/test_property.py +++ b/test/test_property.py @@ -118,7 +118,7 @@ def test_value(self): self.assertEqual(p5.values, [0]) with self.assertRaises(ValueError): - Property(name="dateprop", dtype=DType.time, value=['20190707']) + Property(name="dateprop", dtype=DType.date, value=['20190707']) with self.assertRaises(ValueError): Property(name="timeprop", dtype=DType.time, value=['11.11.11'])