From 56e12fee1153bd1c87a1073a911a99fc015af386 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:27:21 +0100 Subject: [PATCH 01/16] [validation.py] Fix Wrong Error Message Variables Order for hasattr Check --- odml/validation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/odml/validation.py b/odml/validation.py index 7ea1492b..d007944c 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -134,7 +134,7 @@ def object_required_attributes(obj): for arg in args: if arg[1] == 1: if not hasattr(obj, arg[0]): - msg = "Missing attribute %s for %s" % (obj.format().name.capitalize(), arg[0]) + msg = "Missing attribute %s for %s" % (arg[0], obj.format().name.capitalize()) yield ValidationError(obj, msg, LABEL_ERROR) continue obj_arg = getattr(obj, arg[0]) From aaac7778b77be60b887245d835d62e97722bdf63 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:31:29 +0100 Subject: [PATCH 02/16] [validation.py] Add Object Name Readability Check For Section and Property. --- odml/validation.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/odml/validation.py b/odml/validation.py index d007944c..eb2fd05d 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -308,6 +308,20 @@ def property_unique_names(obj): Validation.register_handler('section', property_unique_names) +def object_name_readable(obj): + """ + Tests if object name is easily readable, so not equal to id. + + :param obj: odml.Section or odml.Property. + """ + if obj.name == obj.id: + yield ValidationError(obj, 'Name should be readable', LABEL_WARNING) + + +Validation.register_handler('section', object_name_readable) +Validation.register_handler('property', object_name_readable) + + def property_terminology_check(prop): """ 1. warn, if there are properties that do not occur in the terminology. From 13a51c8a46aa1f2f112a5dd81e47dcb5e43f7dee Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:32:25 +0100 Subject: [PATCH 03/16] [test_validation.py] Add Test for Section Name Readability --- test/test_validation.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/test_validation.py b/test/test_validation.py index 7f4a170e..dcf2bf0d 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -129,6 +129,16 @@ def test_section_unique_ids(self): res = validate(doc) self.assertError(res, "Duplicate id in Section") + def test_section_name_readable(self): + """ + Test if section name is not uuid and thus more readable. + """ + doc = odml.Document() + sec = odml.Section("sec", parent=doc) + sec.name = sec.id + res = validate(doc) + self.assertError(res, "Name should be readable") + def test_standalone_section(self): """ Test if standalone section does not return errors if required attributes are correct. From 206b274d5a0e22b47060ce304869401263fe81e0 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:33:06 +0100 Subject: [PATCH 04/16] [test_validation.py] Add Test for Property Name Readability --- test/test_validation.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/test_validation.py b/test/test_validation.py index dcf2bf0d..b1253737 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -139,6 +139,17 @@ def test_section_name_readable(self): res = validate(doc) self.assertError(res, "Name should be readable") + def test_property_name_readable(self): + """ + Test if property name is not uuid and thus more readable. + """ + doc = odml.Document() + sec = odml.Section("sec", parent=doc) + prop = odml.Property("prop", parent=sec) + prop.name = prop.id + res = validate(doc) + self.assertError(res, "Name should be readable") + def test_standalone_section(self): """ Test if standalone section does not return errors if required attributes are correct. From 69511842aea32ba18569e1f54459c64ccb5badeb Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:35:49 +0100 Subject: [PATCH 05/16] [test_validation.py] Fix Bad Continuation and Whitespace --- test/test_validation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_validation.py b/test/test_validation.py index b1253737..33d02f34 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -193,8 +193,8 @@ def test_prop_string_values(self): prop2 = odml.Property(name='potential', dtype="string", values=['-4.8', '10.0', '-11.9', '-10.0', '18.0']) - self.assertError(validate(prop2),'Dtype of property "potential" currently is "string", ' - 'but might fit dtype "float"!') + self.assertError(validate(prop2), 'Dtype of property "potential" currently is "string", ' + 'but might fit dtype "float"!') prop3 = odml.Property(name='dates', dtype="string", values=['1997-12-14', '00-12-14', '89-07-04']) From d3faa1fc7edb458d923424b5dd2a21b74fdd4cea Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:37:25 +0100 Subject: [PATCH 06/16] [test_validation.py] Change Error Assertion for Load Section Tests For xml, json and yaml. --- test/test_validation.py | 51 +++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/test/test_validation.py b/test/test_validation.py index 33d02f34..cb8ecb6f 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -240,17 +240,12 @@ def test_load_section_xml(self): path = os.path.join(self.dir_path, "resources", "validation_section.xml") doc = odml.load(path) - sec_type_undefined_err = False - sec_type_empty_err = False - - for err in validate(doc).errors: - if err.msg == "Section type undefined" and err.obj.name == "sec_type_undefined": - sec_type_undefined_err = True - elif err.msg == "Section type undefined" and err.obj.name == "sec_type_empty": - sec_type_empty_err = True - - assert sec_type_undefined_err - assert sec_type_empty_err + assert len(list(filter( + lambda x: x.msg == "Section type undefined" and x.obj.name == "sec_type_undefined", + validate(doc).errors))) > 0 + assert len(list(filter( + lambda x: x.msg == "Section type undefined" and x.obj.name == "sec_type_empty", + validate(doc).errors))) > 0 def test_load_dtypes_xml(self): """ @@ -319,17 +314,12 @@ def test_load_section_json(self): path = os.path.join(self.dir_path, "resources", "validation_section.json") doc = odml.load(path, "JSON") - sec_type_undefined_err = False - sec_type_empty_err = False - - for err in validate(doc).errors: - if err.msg == "Section type undefined" and err.obj.name == "sec_type_undefined": - sec_type_undefined_err = True - elif err.msg == "Section type undefined" and err.obj.name == "sec_type_empty": - sec_type_empty_err = True - - assert sec_type_undefined_err - assert sec_type_empty_err + assert len(list(filter( + lambda x: x.msg == "Section type undefined" and x.obj.name == "sec_type_undefined", + validate(doc).errors))) > 0 + assert len(list(filter( + lambda x: x.msg == "Section type undefined" and x.obj.name == "sec_type_empty", + validate(doc).errors))) > 0 def test_load_dtypes_json(self): """ @@ -398,17 +388,12 @@ def test_load_section_yaml(self): path = os.path.join(self.dir_path, "resources", "validation_section.yaml") doc = odml.load(path, "YAML") - sec_type_undefined_err = False - sec_type_empty_err = False - - for err in validate(doc).errors: - if err.msg == "Section type undefined" and err.obj.name == "sec_type_undefined": - sec_type_undefined_err = True - elif err.msg == "Section type undefined" and err.obj.name == "sec_type_empty": - sec_type_empty_err = True - - assert sec_type_undefined_err - assert sec_type_empty_err + assert len(list(filter( + lambda x: x.msg == "Section type undefined" and x.obj.name == "sec_type_undefined", + validate(doc).errors))) > 0 + assert len(list(filter( + lambda x: x.msg == "Section type undefined" and x.obj.name == "sec_type_empty", + validate(doc).errors))) > 0 def test_load_dtypes_yaml(self): """ From 89a5536912ff3564eda8063ea833ab6f6f63db31 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:38:56 +0100 Subject: [PATCH 07/16] [test_validation.py] Add Test for Section Init Validation Stdout --- test/test_validation.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/test_validation.py b/test/test_validation.py index cb8ecb6f..4d67c498 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -1,10 +1,16 @@ import unittest import odml import os +import sys import odml.validation import odml.terminology from . import test_samplefile as samplefile +try: + from StringIO import StringIO +except ImportError: + from io import StringIO + validate = odml.validation.Validation @@ -176,6 +182,19 @@ def test_standalone_property(self): for err in validate(prop).errors: assert not err.is_error + def test_section_init(self): + """ + Test validation errors printed to stdout on section init. + """ + val_errs = StringIO() + + old_stdout = sys.stdout + sys.stdout = val_errs + odml.Section(name="sec", type=None) + sys.stdout = old_stdout + + assert "Section type undefined" in val_errs.getvalue() + def test_prop_string_values(self): """ Test if property values set as dtype string but could be of different dtype From 8a58ce174a283857f419151e430482bbcbb3b52f Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:40:29 +0100 Subject: [PATCH 08/16] [test_validation.py] Replace For Loop by Filter --- test/test_validation.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/test_validation.py b/test/test_validation.py index 4d67c498..1dc8a330 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -179,8 +179,7 @@ def test_standalone_property(self): prop = odml.Property() prop.type = "" - for err in validate(prop).errors: - assert not err.is_error + assert len(list(filter(lambda x: x.is_error, validate(prop).errors))) == 0 def test_section_init(self): """ From cd5084a36eebe7fdd902f16ee4c2f4db30f1ee7b Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:43:31 +0100 Subject: [PATCH 09/16] [test_fileio.py] Change Test File Path to example.odml Change to more robust way to access file location and use file from within test dir. Otherwise might not be found during local testing. --- test/test_fileio.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test_fileio.py b/test/test_fileio.py index 02c4ab50..c89ecc8d 100644 --- a/test/test_fileio.py +++ b/test/test_fileio.py @@ -13,7 +13,8 @@ class TestTypes(unittest.TestCase): # TODO :- Write tests for JSONParser once it's completed. def setUp(self): - self.file = 'doc/example_odMLs/THGTTG.odml' + self.dir_path = os.path.dirname(os.path.realpath(__file__)) + self.file = os.path.join(self.dir_path, 'resources', 'example.odml') # Do not allow anything to be printed on STDOUT self.captured_stdout = StringIO() sys.stdout = self.captured_stdout From 957dcdab14478be21a2781142b165653533a7f57 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:46:00 +0100 Subject: [PATCH 10/16] [property.py] Fix Tuple Extend Error Because dtype always inferred as string. --- odml/property.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/odml/property.py b/odml/property.py index 761375dd..1ccdf8ca 100644 --- a/odml/property.py +++ b/odml/property.py @@ -688,7 +688,8 @@ def extend(self, obj, strict=True): dtypes.infer_dtype(new_value[0]) != self.dtype: type_check = dtypes.infer_dtype(new_value[0]) - if not (type_check == "string" and self.dtype in dtypes.special_dtypes): + if not (type_check == "string" and self.dtype in dtypes.special_dtypes) \ + and not self.dtype.endswith("-tuple"): msg = "odml.Property.extend: passed value data type found " msg += "(\"%s\") does not match expected dtype \"%s\"!" % (type_check, self._dtype) From 543dcd4517e054aba37ab91f5cc0deb6daf27b1e Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:46:31 +0100 Subject: [PATCH 11/16] [property.py] Fix Tuple Append Error Because dtype always inferred as string. --- odml/property.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/odml/property.py b/odml/property.py index 1ccdf8ca..6c5caf0e 100644 --- a/odml/property.py +++ b/odml/property.py @@ -725,7 +725,8 @@ def append(self, obj, strict=True): dtypes.infer_dtype(new_value[0]) != self.dtype: type_check = dtypes.infer_dtype(new_value[0]) - if not (type_check == "string" and self.dtype in dtypes.special_dtypes): + if not (type_check == "string" and self.dtype in dtypes.special_dtypes) \ + and not self.dtype.endswith("-tuple"): msg = "odml.Property.append: passed value data type found " msg += "(\"%s\") does not match expected dtype \"%s\"!" % (type_check, self._dtype) From 132bcd1e8e56891f3ba12d3959619e7dde244908 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:48:50 +0100 Subject: [PATCH 12/16] [test_property.py] Add Tuple Extend Test --- test/test_property.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/test_property.py b/test/test_property.py index 95048f17..6ada7612 100644 --- a/test/test_property.py +++ b/test/test_property.py @@ -329,6 +329,11 @@ def test_value_extend(self): self.assertRaises(ValueError, p3.append, 1.3) self.assertRaises(ValueError, p3.append, True) + prop = Property(name="tuple-test", dtype="3-tuple", values="(1; 2; 3)") + prop.extend(["(7; 8; 9)", "(10; 11; 12)"]) + self.assertEqual(len(prop), 3) + self.assertRaises(ValueError, prop.extend, "(10; 11)") + def test_get_set_value(self): values = [1, 2, 3, 4, 5] p = Property("property", value=values) From e468a1f391f69eb1aa7e899358d6f8bab435e535 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:49:15 +0100 Subject: [PATCH 13/16] [test_property.py] Add Tuple Append Test --- test/test_property.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/test_property.py b/test/test_property.py index 6ada7612..e31142cf 100644 --- a/test/test_property.py +++ b/test/test_property.py @@ -231,6 +231,11 @@ def test_value_append(self): self.assertRaises(ValueError, p8.append, 1.3) self.assertRaises(ValueError, p8.append, True) + prop = Property(name="tuple-test", dtype="3-tuple", values="(1; 2; 3)") + prop.append("(7; 8; 9)") + self.assertEqual(len(prop), 2) + self.assertRaises(ValueError, prop.append, "(10; 11)") + def test_value_extend(self): prop = Property(name="extend") From a11fda9d9ea6fbddb02be3f74efde1b68ac2a733 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:49:40 +0100 Subject: [PATCH 14/16] [test_property.py] Fix Whitespace --- 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 e31142cf..8ef2c411 100644 --- a/test/test_property.py +++ b/test/test_property.py @@ -279,7 +279,7 @@ def test_value_extend(self): prop.extend(ext_prop) self.assertEqual(prop.values, ["a", "b", "c", "d", "e"]) - ext_prop = Property(name="value extend", value=[1, 2 ,3]) + ext_prop = Property(name="value extend", value=[1, 2, 3]) with self.assertRaises(ValueError): prop.extend(ext_prop) self.assertEqual(prop.values, ["a", "b", "c", "d", "e"]) From b902a518413a5ee405b415d9960e85b971c57534 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:50:05 +0100 Subject: [PATCH 15/16] [test_property.py] Fix Bad Line Continuation --- test/test_property.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_property.py b/test/test_property.py index 8ef2c411..11dee4d0 100644 --- a/test/test_property.py +++ b/test/test_property.py @@ -746,12 +746,12 @@ def test_comparison(self): p_val = ["a", "b"] prop_a = Property(name=p_name, value_origin=p_origin, unit=p_unit, - uncertainty=p_uncertainty, reference=p_ref, definition=p_def, - dependency=p_dep, dependency_value=p_dep_val, value=p_val) + uncertainty=p_uncertainty, reference=p_ref, definition=p_def, + dependency=p_dep, dependency_value=p_dep_val, value=p_val) prop_b = Property(name=p_name, value_origin=p_origin, unit=p_unit, - uncertainty=p_uncertainty, reference=p_ref, definition=p_def, - dependency=p_dep, dependency_value=p_dep_val, value=p_val) + uncertainty=p_uncertainty, reference=p_ref, definition=p_def, + dependency=p_dep, dependency_value=p_dep_val, value=p_val) self.assertEqual(prop_a, prop_b) From 1d8e0557953ae85ad928ac9aeae0470d312a213d Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Thu, 26 Mar 2020 17:52:01 +0100 Subject: [PATCH 16/16] [test_property.py] Replace Append in Extend Test --- test/test_property.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/test_property.py b/test/test_property.py index 11dee4d0..ac9dd96d 100644 --- a/test/test_property.py +++ b/test/test_property.py @@ -323,16 +323,16 @@ def test_value_extend(self): 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) + self.assertRaises(ValueError, p2.extend, 1) + self.assertRaises(ValueError, p2.extend, 1.3) + self.assertRaises(ValueError, p2.extend, 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) + self.assertRaises(ValueError, p3.extend, 1) + self.assertRaises(ValueError, p3.extend, 1.3) + self.assertRaises(ValueError, p3.extend, True) prop = Property(name="tuple-test", dtype="3-tuple", values="(1; 2; 3)") prop.extend(["(7; 8; 9)", "(10; 11; 12)"])