From 6fac3ca53bd40c5b418533d34b3e44911d33c021 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Fri, 6 Mar 2020 10:40:10 +0100 Subject: [PATCH 01/31] [validation.py] Add Property Values Validation Prototype --- odml/validation.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/odml/validation.py b/odml/validation.py index 9b9561ff..6cf6603d 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -3,6 +3,8 @@ Generic odML validation framework. """ +from . import dtypes + LABEL_ERROR = 'error' LABEL_WARNING = 'warning' @@ -317,3 +319,28 @@ def property_dependency_check(prop): Validation.register_handler('property', property_dependency_check) + + +def property_values_check(prop): + """ + PROTOTYPE + + Tests that the values are of consistent dtype. + If dtype is not given, infer from first item in list. + + :param prop: property the validation is applied on. + """ + + if prop.dtype is not None and prop.dtype is not "": + dtype = prop.dtype + elif len(prop.values) != 0: + dtype = dtypes.infer_dtype(prop.values[0]) + else: + return + + for val in prop.values: + try: + dtypes.get(val, dtype) + except Exception: + msg = "Property values not of consistent dtype!" + yield ValidationError(prop, msg, LABEL_ERROR) From 865a6beabd22f4afa03d4c4deff7fc48b3e9d6cf Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Fri, 6 Mar 2020 10:46:45 +0100 Subject: [PATCH 02/31] [validation.py] Add Validation from odMl Attributes List If marked as mandatory in format, throw error. --- odml/validation.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/odml/validation.py b/odml/validation.py index 6cf6603d..ab17e88c 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -118,6 +118,26 @@ def __getitem__(self, obj): # ------------------------------------------------ # validation rules +def object_args_must_be_defined(obj): + """ + Tests that no Object has undefined attributes, given in format. + + :param obj: document, section or property. + """ + + args = obj.format().arguments + for arg in args: + if arg[1] == 1: + obj_arg = getattr(obj, arg[0]) + if obj_arg is None or obj_arg == '' or obj_arg == 'undefined': + yield ValidationError(obj, obj.format().name.capitalize() + ' ' + arg[0] + ' undefined', LABEL_WARNING) + + +Validation.register_handler('odML', object_args_must_be_defined) +Validation.register_handler('section', object_args_must_be_defined) +Validation.register_handler('property', object_args_must_be_defined) + + def section_type_must_be_defined(sec): """ Tests that no Section has an undefined type. From e45181fc7b6ad8efac02310524bab808dcbe4735 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Fri, 6 Mar 2020 10:49:02 +0100 Subject: [PATCH 03/31] [validation.py] Remove Section Type Definition Validation Handler Covered by import from formats list. --- odml/validation.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/odml/validation.py b/odml/validation.py index ab17e88c..36e8fed0 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -140,6 +140,8 @@ def object_args_must_be_defined(obj): def section_type_must_be_defined(sec): """ + DEPRECATED + Tests that no Section has an undefined type. :param sec: odml.Section. @@ -148,9 +150,6 @@ def section_type_must_be_defined(sec): yield ValidationError(sec, 'Section type undefined', LABEL_WARNING) -Validation.register_handler('section', section_type_must_be_defined) - - def section_repository_present(sec): """ 1. warn, if a section has no repository or From e8d1a990d201a752322018df01fb032291291f77 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Fri, 6 Mar 2020 10:50:03 +0100 Subject: [PATCH 04/31] [validation.py] Allow Standalone Property Validation --- odml/validation.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/odml/validation.py b/odml/validation.py index 36e8fed0..76bab92e 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -76,12 +76,17 @@ def register_handler(klass, handler): """ Validation._handlers.setdefault(klass, set()).add(handler) - def __init__(self, doc): - self.doc = doc # may also be a section + def __init__(self, obj): + self.doc = obj # may also be a section self.errors = [] - self.validate(doc) - for sec in doc.itersections(recursive=True): + if obj.format().name == "property": + self.validate(obj) + return + + self.validate(obj) + + for sec in obj.itersections(recursive=True): self.validate(sec) for prop in sec.properties: self.validate(prop) @@ -303,6 +308,9 @@ def property_terminology_check(prop): 2. warn, if there are multiple values with different units or the unit does not match the one in the terminology. """ + if not prop.parent: + return + tsec = prop.parent.get_terminology_equivalent() if tsec is None: return @@ -321,6 +329,9 @@ def property_dependency_check(prop): Produces a warning if the dependency attribute refers to a non-existent attribute or the dependency_value does not match. """ + if not prop.parent: + return + dep = prop.dependency if dep is None: return From 95a7f7cf576910d6bd2845d86945cec1f6b4ea75 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Fri, 6 Mar 2020 10:50:44 +0100 Subject: [PATCH 05/31] [section.py] Add Validation on Initialization --- odml/section.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/odml/section.py b/odml/section.py index 23fd2805..435e0bd7 100644 --- a/odml/section.py +++ b/odml/section.py @@ -12,6 +12,7 @@ from . import base from . import format as fmt from . import terminology +from . import validation from .doc import BaseDocument # this is supposedly ok, as we only use it for an isinstance check from .property import BaseProperty @@ -81,6 +82,8 @@ def __init__(self, name=None, type=None, parent=None, self.type = type self.parent = parent + validation.Validation(self) + def __repr__(self): return "Section[%d|%d] {name = %s, type = %s, id = %s}" % (len(self._sections), len(self._props), From b2d62aa60546265d437a444506025de31edd5726 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Fri, 6 Mar 2020 10:51:08 +0100 Subject: [PATCH 06/31] [property.py] Add Validation on Initialization --- odml/property.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/odml/property.py b/odml/property.py index 09443e6d..83ce3a7c 100644 --- a/odml/property.py +++ b/odml/property.py @@ -6,6 +6,7 @@ from . import base from . import dtypes +from . import validation from . import format as frmt from .tools.doc_inherit import inherit_docstring, allow_inherit_docstring @@ -128,6 +129,8 @@ def __init__(self, name=None, values=None, parent=None, unit=None, self.parent = parent + validation.Validation(self) + def __len__(self): return len(self._values) From 65ab50334fd36b07bf6e5cd564c3253944de7a3b Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Fri, 6 Mar 2020 10:52:26 +0100 Subject: [PATCH 07/31] [test_validation.py] Add Test for Standalone Section --- test/test_validation.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/test_validation.py b/test/test_validation.py index df616fe0..806f255b 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -126,3 +126,14 @@ def test_section_unique_ids(self): res = validate(doc) self.assertError(res, "Duplicate id in Section") + + def test_standalone_section(self): + """ + Test if standalone section is validated right. + """ + + sec_one = odml.Section("sec1") + sec_two = odml.Section("sec2", parent=sec_one) + prop = odml.Property("prop", parent=sec_one, values=[1, 2]) + + validate(sec_one) From af8860b4f3f6ca0b07e601645454841e2557f488 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Fri, 6 Mar 2020 10:53:21 +0100 Subject: [PATCH 08/31] [test_validation.py] Add Test for Standalone Property --- test/test_validation.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/test_validation.py b/test/test_validation.py index 806f255b..2e2584fe 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -137,3 +137,11 @@ def test_standalone_section(self): prop = odml.Property("prop", parent=sec_one, values=[1, 2]) validate(sec_one) + + def test_standalone_property(self): + """ + Test if standalone property is validated right. + """ + + prop = odml.Property("prop", dtype="int", values=[1, 2]) + validate(prop) From a68a1f2dd388e84dd681cea75686700302749a52 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 10 Mar 2020 12:25:29 +0100 Subject: [PATCH 09/31] [validation.py] Move Check For Standalone Property --- odml/validation.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/odml/validation.py b/odml/validation.py index 76bab92e..4990a753 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -80,12 +80,11 @@ def __init__(self, obj): self.doc = obj # may also be a section self.errors = [] + self.validate(obj) + if obj.format().name == "property": - self.validate(obj) return - self.validate(obj) - for sec in obj.itersections(recursive=True): self.validate(sec) for prop in sec.properties: From 74684c04f88c915aaadcb476be7023ec7542c76d Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 10 Mar 2020 12:26:34 +0100 Subject: [PATCH 10/31] [validation.py] Reintroduce Section Type Check --- odml/validation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/odml/validation.py b/odml/validation.py index 4990a753..f2818c35 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -144,8 +144,6 @@ def object_args_must_be_defined(obj): def section_type_must_be_defined(sec): """ - DEPRECATED - Tests that no Section has an undefined type. :param sec: odml.Section. @@ -154,6 +152,9 @@ def section_type_must_be_defined(sec): yield ValidationError(sec, 'Section type undefined', LABEL_WARNING) +Validation.register_handler('section', section_type_must_be_defined) + + def section_repository_present(sec): """ 1. warn, if a section has no repository or From 6d4a94a492dab8bdcc9fb95fd9107cfab305d1e0 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 10 Mar 2020 12:28:29 +0100 Subject: [PATCH 11/31] [validation.py] Adapt Required Attributes Check --- odml/validation.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/odml/validation.py b/odml/validation.py index f2818c35..24ca679e 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -122,7 +122,7 @@ def __getitem__(self, obj): # ------------------------------------------------ # validation rules -def object_args_must_be_defined(obj): +def object_required_attributes(obj): """ Tests that no Object has undefined attributes, given in format. @@ -132,14 +132,18 @@ def object_args_must_be_defined(obj): args = obj.format().arguments for arg in args: if arg[1] == 1: + if not hasattr(obj, arg[0]): + msg = "%s has no attribute %s" % (obj.format().name.capitalize(), arg[0]) + yield AttributeError(obj, msg, LABEL_WARNING) obj_arg = getattr(obj, arg[0]) - if obj_arg is None or obj_arg == '' or obj_arg == 'undefined': - yield ValidationError(obj, obj.format().name.capitalize() + ' ' + arg[0] + ' undefined', LABEL_WARNING) + if not obj_arg and not isinstance(obj_arg, bool): + msg = "%s %s undefined" % (obj.format().name.capitalize(), arg[0]) + yield ValidationError(obj, msg, LABEL_WARNING) -Validation.register_handler('odML', object_args_must_be_defined) -Validation.register_handler('section', object_args_must_be_defined) -Validation.register_handler('property', object_args_must_be_defined) +Validation.register_handler('odML', object_required_attributes) +Validation.register_handler('section', object_required_attributes) +Validation.register_handler('property', object_required_attributes) def section_type_must_be_defined(sec): From 8d05bd4ec7bddcc630050d9ffb9c8ed1d27152e8 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 10 Mar 2020 12:29:28 +0100 Subject: [PATCH 12/31] [validation.py] Minor Changes for Property Values Check Prototype --- odml/validation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/odml/validation.py b/odml/validation.py index 24ca679e..87c188f4 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -367,7 +367,7 @@ def property_values_check(prop): if prop.dtype is not None and prop.dtype is not "": dtype = prop.dtype - elif len(prop.values) != 0: + elif prop.values: dtype = dtypes.infer_dtype(prop.values[0]) else: return @@ -375,6 +375,6 @@ def property_values_check(prop): for val in prop.values: try: dtypes.get(val, dtype) - except Exception: + except ValueError: msg = "Property values not of consistent dtype!" yield ValidationError(prop, msg, LABEL_ERROR) From 18e2c199ccba6e85322b6d819e149ec0b73d780a Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 10 Mar 2020 12:30:28 +0100 Subject: [PATCH 13/31] [test_validation.py] Specify Test for Standalone Section --- test/test_validation.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/test_validation.py b/test/test_validation.py index 2e2584fe..9b72aa46 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -129,14 +129,15 @@ def test_section_unique_ids(self): def test_standalone_section(self): """ - Test if standalone section is validated right. + Test if standalone section does not return errors. """ sec_one = odml.Section("sec1") - sec_two = odml.Section("sec2", parent=sec_one) - prop = odml.Property("prop", parent=sec_one, values=[1, 2]) + odml.Section("sec2", parent=sec_one) + odml.Property("prop", parent=sec_one, values=[1, 2]) - validate(sec_one) + for err in validate(sec_one).errors: + assert("error" not in err.rank) def test_standalone_property(self): """ From 1c074b981f9792c728c80db8255b88b587cca651 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 10 Mar 2020 12:30:48 +0100 Subject: [PATCH 14/31] [test_validation.py] Specify Test for Standalone Property --- test/test_validation.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/test_validation.py b/test/test_validation.py index 9b72aa46..3081c34b 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -141,8 +141,10 @@ def test_standalone_section(self): def test_standalone_property(self): """ - Test if standalone property is validated right. + Test if standalone property does not return errors. """ prop = odml.Property("prop", dtype="int", values=[1, 2]) - validate(prop) + + for err in validate(prop).errors: + assert("error" not in err.rank) From 01504d3cdc6e51cd8c901adfd8c86fdd5c1c7be8 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 10 Mar 2020 12:31:25 +0100 Subject: [PATCH 15/31] [section.py] Print Validation Errors --- odml/section.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/odml/section.py b/odml/section.py index 435e0bd7..8b7623d2 100644 --- a/odml/section.py +++ b/odml/section.py @@ -82,7 +82,9 @@ def __init__(self, name=None, type=None, parent=None, self.type = type self.parent = parent - validation.Validation(self) + for err in validation.Validation(self).errors: + if err.rank == "error": + print("ERROR", err.obj, err.msg) def __repr__(self): return "Section[%d|%d] {name = %s, type = %s, id = %s}" % (len(self._sections), From c028491bcc2f8531188a7ac51d6e4055bb90a0a0 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 10 Mar 2020 12:31:48 +0100 Subject: [PATCH 16/31] [property.py] Print Validation Errors --- odml/property.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/odml/property.py b/odml/property.py index 83ce3a7c..4f9435ff 100644 --- a/odml/property.py +++ b/odml/property.py @@ -129,7 +129,9 @@ def __init__(self, name=None, values=None, parent=None, unit=None, self.parent = parent - validation.Validation(self) + for err in validation.Validation(self).errors: + if err.rank == "error": + print("ERROR", err.obj, err.msg) def __len__(self): return len(self._values) From 76a1c4fa5c5c6faf7062ebbdb0d1c87e05d968ec Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 17 Mar 2020 15:53:49 +0100 Subject: [PATCH 17/31] [property.py] Change Validation Error Messages Print --- odml/property.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/odml/property.py b/odml/property.py index 4f9435ff..761375dd 100644 --- a/odml/property.py +++ b/odml/property.py @@ -130,8 +130,9 @@ def __init__(self, name=None, values=None, parent=None, unit=None, self.parent = parent for err in validation.Validation(self).errors: - if err.rank == "error": - print("ERROR", err.obj, err.msg) + if err.is_error: + msg = "\n\t- %s %s: %s" % (err.obj, err.rank, err.msg) + print(msg) def __len__(self): return len(self._values) From b3409c0880a19d6c8dd2bd95166e6d0020c7f2fa Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 17 Mar 2020 15:54:22 +0100 Subject: [PATCH 18/31] [section.py] Change Validation Error Messages Print --- odml/section.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/odml/section.py b/odml/section.py index 8b7623d2..e37a7d8a 100644 --- a/odml/section.py +++ b/odml/section.py @@ -83,8 +83,9 @@ def __init__(self, name=None, type=None, parent=None, self.parent = parent for err in validation.Validation(self).errors: - if err.rank == "error": - print("ERROR", err.obj, err.msg) + if err.is_error: + msg = "\n\t- %s %s: %s" % (err.obj, err.rank, err.msg) + print(msg) def __repr__(self): return "Section[%d|%d] {name = %s, type = %s, id = %s}" % (len(self._sections), From 20f02f4611574c58058b3fa19a4ad0f3c69dc52d Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 17 Mar 2020 15:56:05 +0100 Subject: [PATCH 19/31] [validation.py] Adapt Object Has Attribute Check --- odml/validation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/odml/validation.py b/odml/validation.py index 87c188f4..2e611c56 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -133,8 +133,9 @@ def object_required_attributes(obj): for arg in args: if arg[1] == 1: if not hasattr(obj, arg[0]): - msg = "%s has no attribute %s" % (obj.format().name.capitalize(), arg[0]) - yield AttributeError(obj, msg, LABEL_WARNING) + msg = "Missing attribute %s for %s" % (obj.format().name.capitalize(), arg[0]) + yield ValidationError(obj, msg, LABEL_WARNING) + return obj_arg = getattr(obj, arg[0]) if not obj_arg and not isinstance(obj_arg, bool): msg = "%s %s undefined" % (obj.format().name.capitalize(), arg[0]) From 7946515f9491c32ba8125837d574d3f885cd719d Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 17 Mar 2020 15:57:47 +0100 Subject: [PATCH 20/31] [validation.py] Replace Empty String Statement --- odml/validation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/odml/validation.py b/odml/validation.py index 2e611c56..6e2b5b3f 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -366,7 +366,7 @@ def property_values_check(prop): :param prop: property the validation is applied on. """ - if prop.dtype is not None and prop.dtype is not "": + if prop.dtype is not None and prop.dtype != "": dtype = prop.dtype elif prop.values: dtype = dtypes.infer_dtype(prop.values[0]) From 5778db14f0ee214f479a7e76b40c8046a2699adf Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 17 Mar 2020 16:00:25 +0100 Subject: [PATCH 21/31] [validation.py] Set Property DType Error Label to Warning --- odml/validation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/odml/validation.py b/odml/validation.py index 6e2b5b3f..812306f1 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -378,4 +378,4 @@ def property_values_check(prop): dtypes.get(val, dtype) except ValueError: msg = "Property values not of consistent dtype!" - yield ValidationError(prop, msg, LABEL_ERROR) + yield ValidationError(prop, msg, LABEL_WARNING) From ca77e62785e3f517bc8ffcddbc40454814600f4c Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 17 Mar 2020 16:02:12 +0100 Subject: [PATCH 22/31] [validation.py] Add Check for Property Value Tuple Length --- odml/validation.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/odml/validation.py b/odml/validation.py index 812306f1..86fb3477 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -374,8 +374,14 @@ def property_values_check(prop): return for val in prop.values: - try: - dtypes.get(val, dtype) - except ValueError: - msg = "Property values not of consistent dtype!" - yield ValidationError(prop, msg, LABEL_WARNING) + if dtype.endswith("-tuple"): + tuple_len = int(dtype[:-6]) + if len(val) != tuple_len: + msg = "Tuple of length %s not consistent with dtype %s!" % (len(val), dtype) + yield ValidationError(prop, msg, LABEL_WARNING) + else: + try: + dtypes.get(val, dtype) + except ValueError: + msg = "Property values not of consistent dtype!" + yield ValidationError(prop, msg, LABEL_WARNING) From 6ff4cfb97bdc6a08856ab042c81e0469c163709b Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 17 Mar 2020 16:02:44 +0100 Subject: [PATCH 23/31] [validation.py] Register Handler for Property Value Check --- odml/validation.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/odml/validation.py b/odml/validation.py index 86fb3477..121690da 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -385,3 +385,6 @@ def property_values_check(prop): except ValueError: msg = "Property values not of consistent dtype!" yield ValidationError(prop, msg, LABEL_WARNING) + + +Validation.register_handler('property', property_values_check) From 6466e9dc99d77d64dea79b3473bcf1216983cc95 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 17 Mar 2020 16:03:50 +0100 Subject: [PATCH 24/31] [test_validation.py] Remove Property from Standalone Section Test --- test/test_validation.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/test_validation.py b/test/test_validation.py index 3081c34b..7c1bb2be 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -133,8 +133,6 @@ def test_standalone_section(self): """ sec_one = odml.Section("sec1") - odml.Section("sec2", parent=sec_one) - odml.Property("prop", parent=sec_one, values=[1, 2]) for err in validate(sec_one).errors: assert("error" not in err.rank) From bb34306b3184a5ca919688300c6d53a0663da74b Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 17 Mar 2020 16:04:53 +0100 Subject: [PATCH 25/31] [test_validation.py] Add Section Type Undefined Test to Standalone Section --- test/test_validation.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/test_validation.py b/test/test_validation.py index 7c1bb2be..8e8b3933 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -135,7 +135,11 @@ def test_standalone_section(self): sec_one = odml.Section("sec1") for err in validate(sec_one).errors: - assert("error" not in err.rank) + assert not err.is_error + + doc = samplefile.parse("""s1[undefined]""") + res = validate(doc) + self.assertError(res, "Section type undefined") def test_standalone_property(self): """ From a04147a9349991eb6b07297db77f9b0a9023b5db Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 17 Mar 2020 16:05:55 +0100 Subject: [PATCH 26/31] [test_validation.py] Change to Empty Property Type for Standalone Property Test --- test/test_validation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/test_validation.py b/test/test_validation.py index 8e8b3933..ec8bc967 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -146,7 +146,8 @@ def test_standalone_property(self): Test if standalone property does not return errors. """ - prop = odml.Property("prop", dtype="int", values=[1, 2]) + prop = odml.Property() + prop.type = "" for err in validate(prop).errors: - assert("error" not in err.rank) + assert not err.is_error From f7a2b2f004e9220d7b4ebe5120a522ac96b6add4 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Tue, 17 Mar 2020 16:06:35 +0100 Subject: [PATCH 27/31] [test_validation.py] Change Comments for Standalone Tests --- test/test_validation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/test_validation.py b/test/test_validation.py index ec8bc967..3026721d 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -129,7 +129,8 @@ def test_section_unique_ids(self): def test_standalone_section(self): """ - Test if standalone section does not return errors. + Test if standalone section does not return errors if required attributes are correct. + If type is undefined, check error message. """ sec_one = odml.Section("sec1") @@ -143,7 +144,7 @@ def test_standalone_section(self): def test_standalone_property(self): """ - Test if standalone property does not return errors. + Test if standalone property does not return errors if required attributes are correct. """ prop = odml.Property() From 426f1f4500ca9d58e723fcc382da0dbb3093ffd0 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Wed, 18 Mar 2020 11:26:47 +0100 Subject: [PATCH 28/31] [validation.py] Remove Prototype Comment --- odml/validation.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/odml/validation.py b/odml/validation.py index 121690da..b651a5f2 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -358,8 +358,6 @@ def property_dependency_check(prop): def property_values_check(prop): """ - PROTOTYPE - Tests that the values are of consistent dtype. If dtype is not given, infer from first item in list. From 009b3a25e5d8124fa76b215b8b095c285fbd1190 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Wed, 18 Mar 2020 11:28:39 +0100 Subject: [PATCH 29/31] [validation.py] Change Label and Return for Attribute Check --- odml/validation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/odml/validation.py b/odml/validation.py index b651a5f2..28278332 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -134,8 +134,8 @@ def object_required_attributes(obj): if arg[1] == 1: if not hasattr(obj, arg[0]): msg = "Missing attribute %s for %s" % (obj.format().name.capitalize(), arg[0]) - yield ValidationError(obj, msg, LABEL_WARNING) - return + yield ValidationError(obj, msg, LABEL_ERROR) + continue obj_arg = getattr(obj, arg[0]) if not obj_arg and not isinstance(obj_arg, bool): msg = "%s %s undefined" % (obj.format().name.capitalize(), arg[0]) From a920a4922438306c5f0ab50fba0c835fe7516ea0 Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Wed, 18 Mar 2020 12:01:58 +0100 Subject: [PATCH 30/31] [validation.py] Change Error Label --- odml/validation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/odml/validation.py b/odml/validation.py index 28278332..21498f15 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -139,7 +139,7 @@ def object_required_attributes(obj): obj_arg = getattr(obj, arg[0]) if not obj_arg and not isinstance(obj_arg, bool): msg = "%s %s undefined" % (obj.format().name.capitalize(), arg[0]) - yield ValidationError(obj, msg, LABEL_WARNING) + yield ValidationError(obj, msg, LABEL_ERROR) Validation.register_handler('odML', object_required_attributes) From 329588a747756df03b8929e22fd2120bd09b559d Mon Sep 17 00:00:00 2001 From: fschrader1992 Date: Wed, 18 Mar 2020 12:37:45 +0100 Subject: [PATCH 31/31] [test] Adapt Tests to Section Type Requirement --- test/test_doc_integration.py | 19 ++++++++++--------- test/test_dumper.py | 14 ++++++++------ test/test_section_integration.py | 26 ++++++++++++++------------ test/test_validation.py | 4 ++-- 4 files changed, 34 insertions(+), 29 deletions(-) diff --git a/test/test_doc_integration.py b/test/test_doc_integration.py index fec4fbd8..4b415f07 100644 --- a/test/test_doc_integration.py +++ b/test/test_doc_integration.py @@ -104,14 +104,15 @@ def test_children(self): """ This test checks the correct saving and loading of Section children of a Document. """ + s_type = "type" # Lvl 1 child Sections - sec_lvl_11 = odml.Section(name="sec_11", parent=self.doc) - _ = odml.Section(name="sec_12", parent=self.doc) + sec_lvl_11 = odml.Section(name="sec_11", type=s_type, parent=self.doc) + _ = odml.Section(name="sec_12", type=s_type, parent=self.doc) # Lvl 2 child Sections - sec_lvl_21 = odml.Section(name="sec_21", parent=sec_lvl_11) - _ = odml.Section(name="sec_22", parent=sec_lvl_11) - _ = odml.Section(name="sec_23", parent=sec_lvl_11) + sec_lvl_21 = odml.Section(name="sec_21", type=s_type, parent=sec_lvl_11) + _ = odml.Section(name="sec_22", type=s_type, parent=sec_lvl_11) + _ = odml.Section(name="sec_23", type=s_type, parent=sec_lvl_11) # Lvl 2 child Properties _ = odml.Property(name="prop_21", parent=sec_lvl_11) @@ -119,10 +120,10 @@ def test_children(self): _ = odml.Property(name="prop_23", parent=sec_lvl_11) # Lvl 3 child Sections - _ = odml.Section(name="sec_31", parent=sec_lvl_21) - _ = odml.Section(name="sec_32", parent=sec_lvl_21) - _ = odml.Section(name="sec_33", parent=sec_lvl_21) - _ = odml.Section(name="sec_34", parent=sec_lvl_21) + _ = odml.Section(name="sec_31", type=s_type, parent=sec_lvl_21) + _ = odml.Section(name="sec_32", type=s_type, parent=sec_lvl_21) + _ = odml.Section(name="sec_33", type=s_type, parent=sec_lvl_21) + _ = odml.Section(name="sec_34", type=s_type, parent=sec_lvl_21) # Lvl 3 child Properties _ = odml.Property(name="prop_31", parent=sec_lvl_21) diff --git a/test/test_dumper.py b/test/test_dumper.py index da879980..40476b6a 100644 --- a/test/test_dumper.py +++ b/test/test_dumper.py @@ -16,17 +16,19 @@ def setUp(self): self.captured_stdout = StringIO() sys.stdout = self.captured_stdout + s_type = "type" + self.doc = odml.Document(author='Rave', version='1.0') - s1 = odml.Section(name='Cell') + s1 = odml.Section(name='Cell', type=s_type) p1 = odml.Property(name='Type', values='Rechargeable') s1.append(p1) - s2 = odml.Section(name='Electrolyte') + s2 = odml.Section(name='Electrolyte', type=s_type) p2 = odml.Property(name='Composition', values='Ni-Cd') s2.append(p2) s1.append(s2) - s3 = odml.Section(name='Electrode') + s3 = odml.Section(name='Electrode', type=s_type) p3 = odml.Property(name='Material', values='Nickel') p4 = odml.Property(name='Models', values=['AA', 'AAA']) s3.append(p3) @@ -41,11 +43,11 @@ def test_dump_doc(self): odml.tools.dumper.dump_doc(self.doc) output = [x.strip() for x in self.captured_stdout.getvalue().split('\n') if x] expected_output = [] - expected_output.append("*Cell ()") + expected_output.append("*Cell (type='type')") expected_output.append(":Type (values=Rechargeable, dtype='string')") - expected_output.append("*Electrolyte ()") + expected_output.append("*Electrolyte (type='type')") expected_output.append(":Composition (values=Ni-Cd, dtype='string')") - expected_output.append("*Electrode ()") + expected_output.append("*Electrode (type='type')") expected_output.append(":Material (values=Nickel, dtype='string')") expected_output.append(":Models (values=[AA,AAA], dtype='string')") self.assertEqual(len(output), len(expected_output)) diff --git a/test/test_section_integration.py b/test/test_section_integration.py index f3e667db..899cc566 100644 --- a/test/test_section_integration.py +++ b/test/test_section_integration.py @@ -51,7 +51,8 @@ def save_load(self): def test_id(self): # Test correct save and load of generated id. sec_name = "empty_id" - sec = odml.Section(name=sec_name, parent=self.doc) + sec_type = "type" + sec = odml.Section(name=sec_name, type=sec_type, parent=self.doc) jdoc, xdoc, ydoc = self.save_load() @@ -62,7 +63,7 @@ def test_id(self): # Test correct save and load of assigned id. sec_name = "assigned_id" assigned_id = "79b613eb-a256-46bf-84f6-207df465b8f7" - _ = odml.Section(name=sec_name, oid=assigned_id, parent=self.doc) + _ = odml.Section(name=sec_name, oid=assigned_id, type=sec_type, parent=self.doc) jdoc, xdoc, ydoc = self.save_load() @@ -116,20 +117,21 @@ def test_children(self): This test checks correct writing and loading of Section and Property children of a Section. """ - root = odml.Section(name="root", parent=self.doc) + s_type = "type" + root = odml.Section(name="root", type=s_type, parent=self.doc) # Lvl 1 child Sections - sec_lvl_11 = odml.Section(name="sec_11", parent=root) - _ = odml.Section(name="sec_12", parent=root) + sec_lvl_11 = odml.Section(name="sec_11", type=s_type, parent=root) + _ = odml.Section(name="sec_12", type=s_type, parent=root) # Lvl 1 child Properties _ = odml.Property(name="prop_11", parent=root) _ = odml.Property(name="prop_12", parent=root) # Lvl 2 child Sections - sec_lvl_21 = odml.Section(name="sec_21", parent=sec_lvl_11) - _ = odml.Section(name="sec_22", parent=sec_lvl_11) - _ = odml.Section(name="sec_23", parent=sec_lvl_11) + sec_lvl_21 = odml.Section(name="sec_21", type=s_type, parent=sec_lvl_11) + _ = odml.Section(name="sec_22", type=s_type, parent=sec_lvl_11) + _ = odml.Section(name="sec_23", type=s_type, parent=sec_lvl_11) # Lvl 2 child Properties _ = odml.Property(name="prop_21", parent=sec_lvl_11) @@ -137,10 +139,10 @@ def test_children(self): _ = odml.Property(name="prop_23", parent=sec_lvl_11) # Lvl 3 child Sections - _ = odml.Section(name="sec_31", parent=sec_lvl_21) - _ = odml.Section(name="sec_32", parent=sec_lvl_21) - _ = odml.Section(name="sec_33", parent=sec_lvl_21) - _ = odml.Section(name="sec_34", parent=sec_lvl_21) + _ = odml.Section(name="sec_31", type=s_type, parent=sec_lvl_21) + _ = odml.Section(name="sec_32", type=s_type, parent=sec_lvl_21) + _ = odml.Section(name="sec_33", type=s_type, parent=sec_lvl_21) + _ = odml.Section(name="sec_34", type=s_type, parent=sec_lvl_21) # Lvl 3 child Properties _ = odml.Property(name="prop_31", parent=sec_lvl_21) diff --git a/test/test_validation.py b/test/test_validation.py index 3026721d..d020cd26 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -135,8 +135,8 @@ def test_standalone_section(self): sec_one = odml.Section("sec1") - for err in validate(sec_one).errors: - assert not err.is_error + res = validate(sec_one) + self.assertError(res, "Section type undefined") doc = samplefile.parse("""s1[undefined]""") res = validate(doc)