From c31148e883c0c531735d1b9398b4dc887c5ece36 Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Tue, 6 Nov 2018 14:24:59 -0800 Subject: [PATCH 01/24] [Section] Add nix '__repr__' style --- odml/section.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/odml/section.py b/odml/section.py index bdea5674..73e4eef3 100644 --- a/odml/section.py +++ b/odml/section.py @@ -57,7 +57,9 @@ def __init__(self, name=None, type=None, parent=None, self.parent = parent def __repr__(self): - return "
" % (self._name, self.type, len(self._sections)) + return "Section {name = %s, type = %s, id = %s (%d)>" % (self._name, self.type, + self.id, + len(self._sections)) def __iter__(self): """ From d4c5d909d437988bf7fcdffefec2436587df4582 Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Tue, 6 Nov 2018 14:29:32 -0800 Subject: [PATCH 02/24] [Section] Add property count to __repr__ --- odml/section.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/odml/section.py b/odml/section.py index 73e4eef3..658b318b 100644 --- a/odml/section.py +++ b/odml/section.py @@ -57,9 +57,11 @@ def __init__(self, name=None, type=None, parent=None, self.parent = parent def __repr__(self): - return "Section {name = %s, type = %s, id = %s (%d)>" % (self._name, self.type, - self.id, - len(self._sections)) + return "Section[%d/%d] {name = %s, type = %s, id = %s}" % (len(self._sections), + len(self._props), + self._name, + self.type, + self.id) def __iter__(self): """ From a22bea00241897cf50b853e5e55823a7a9dddc0f Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Tue, 6 Nov 2018 14:37:06 -0800 Subject: [PATCH 03/24] [Property] Add nix '__repr__' style --- odml/property.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/odml/property.py b/odml/property.py index 74787dd3..87ffcb8e 100644 --- a/odml/property.py +++ b/odml/property.py @@ -144,7 +144,7 @@ def name(self, new_name): self._name = new_name def __repr__(self): - return "" % self._name + return "Property: {name = %s}" % self._name @property def dtype(self): From 31ce79af3c575946070780e821bd82847a8cb522 Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Tue, 20 Nov 2018 14:44:11 +0100 Subject: [PATCH 04/24] [Property] Change attribute from _value to _values --- odml/property.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/odml/property.py b/odml/property.py index 87ffcb8e..971afc3a 100644 --- a/odml/property.py +++ b/odml/property.py @@ -78,16 +78,16 @@ def __init__(self, name=None, value=None, parent=None, unit=None, else: print("Warning: Unknown dtype '%s'." % dtype) - self._value = [] + self._values = [] self.value = value self.parent = parent def __len__(self): - return len(self._value) + return len(self._values) def __getitem__(self, key): - return self._value[key] + return self._values[key] def __setitem__(self, key, item): if int(key) < 0 or int(key) > self.__len__(): @@ -95,7 +95,7 @@ def __setitem__(self, key, item): "array of length %i" % (int(key), self.__len__())) try: val = dtypes.get(item, self.dtype) - self._value[int(key)] = val + self._values[int(key)] = val except Exception: raise ValueError("odml.Property.__setitem__: passed value cannot be " "converted to data type \'%s\'!" % self._dtype) @@ -166,7 +166,7 @@ def dtype(self, new_type): raise AttributeError("'%s' is not a valid type." % new_type) # we convert the value if possible old_type = self._dtype - old_values = self._value + old_values = self._values try: self._dtype = new_type self.value = old_values @@ -237,14 +237,14 @@ def value(self): 2 3 """ - return list(self._value) + return list(self._values) def value_str(self, index=0): """ Used to access typed data of the value at a specific index position as a string. """ - return dtypes.set(self._value[index], self._dtype) + return dtypes.set(self._values[index], self._dtype) def _validate_values(self, values): """ @@ -297,7 +297,7 @@ def value(self, new_value): # Make sure boolean value 'False' gets through as well... if new_value is None or \ (isinstance(new_value, (list, tuple, str)) and len(new_value) == 0): - self._value = [] + self._values = [] return new_value = self._convert_value_input(new_value) @@ -308,7 +308,7 @@ def value(self, new_value): if not self._validate_values(new_value): raise ValueError("odml.Property.value: passed values are not of " "consistent type!") - self._value = [dtypes.get(v, self.dtype) for v in new_value] + self._values = [dtypes.get(v, self.dtype) for v in new_value] @property def value_origin(self): @@ -394,8 +394,8 @@ def remove(self, value): occurrence of the passed in value is removed from the properties list of values. """ - if value in self._value: - self._value.remove(value) + if value in self._values: + self._values.remove(value) def get_path(self): """ @@ -417,7 +417,7 @@ def clone(self, keep_id=False): """ obj = super(BaseProperty, self).clone() obj._parent = None - obj.value = self._value + obj.value = self._values if not keep_id: obj.new_id() @@ -512,7 +512,7 @@ def merge(self, other, strict=True): if self.unit is None and other.unit is not None: self.unit = other.unit - to_add = [v for v in other.value if v not in self._value] + to_add = [v for v in other.value if v not in self._values] self.extend(to_add, strict=strict) def unmerge(self, other): @@ -572,7 +572,7 @@ def extend(self, obj, strict=True): if not self._validate_values(new_value): raise ValueError("odml.Property.extend: passed value(s) cannot be converted " "to data type \'%s\'!" % self._dtype) - self._value.extend([dtypes.get(v, self.dtype) for v in new_value]) + self._values.extend([dtypes.get(v, self.dtype) for v in new_value]) def append(self, obj, strict=True): """ @@ -603,4 +603,4 @@ def append(self, obj, strict=True): raise ValueError("odml.Property.append: passed value(s) cannot be converted " "to data type \'%s\'!" % self._dtype) - self._value.append(dtypes.get(new_value[0], self.dtype)) + self._values.append(dtypes.get(new_value[0], self.dtype)) From eb4887649ff9ce1cbd8dbcde4cb53e60238f58fc Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Tue, 20 Nov 2018 14:53:50 +0100 Subject: [PATCH 05/24] [Property] Add 'values' accessor methods --- odml/property.py | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/odml/property.py b/odml/property.py index 971afc3a..a9f7e403 100644 --- a/odml/property.py +++ b/odml/property.py @@ -310,6 +310,64 @@ def value(self, new_value): "consistent type!") self._values = [dtypes.get(v, self.dtype) for v in new_value] + @property + def values(self): + """ + Returns the value(s) stored in this property. Method always returns a list + that is a copy (!) of the stored value. Changing this list will NOT change + the property. + For manipulation of the stored values use the append, extend, and direct + access methods (using brackets). + + For example: + >>> p = odml.Property("prop", values=[1, 2, 3]) + >>> print(p.values) + [1, 2, 3] + >>> p.values.append(4) + >>> print(p.values) + [1, 2, 3] + + Individual values can be accessed and manipulated like this: + >>> print(p[0]) + [1] + >>> p[0] = 4 + >>> print(p[0]) + [4] + + The values can be iterated e.g. with a loop: + >>> for v in p.values: + >>> print(v) + 4 + 2 + 3 + """ + return list(self._values) + + @values.setter + def values(self, new_value): + """ + Set the values of the property discarding any previous information. + Method will try to convert the passed value to the dtype of + the property and raise a ValueError if not possible. + + :param new_value: a single value or list of values. + """ + # Make sure boolean value 'False' gets through as well... + if new_value is None or \ + (isinstance(new_value, (list, tuple, str)) and len(new_value) == 0): + self._values = [] + return + + new_value = self._convert_value_input(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.value: passed values are not of " + "consistent type!") + self._values = [dtypes.get(v, self.dtype) for v in new_value] + @property def value_origin(self): return self._value_origin From 13d1f64b2ba7986bc37e3666f5f8c3d020df4cf4 Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Tue, 20 Nov 2018 15:30:06 +0100 Subject: [PATCH 06/24] [Property] Add 'value' deprecation warnings --- odml/property.py | 64 +++++++++--------------------------------------- 1 file changed, 12 insertions(+), 52 deletions(-) diff --git a/odml/property.py b/odml/property.py index a9f7e403..952c34cb 100644 --- a/odml/property.py +++ b/odml/property.py @@ -209,35 +209,20 @@ def _validate_parent(new_parent): @property def value(self): """ - Returns the value(s) stored in this property. Method always returns a list - that is a copy (!) of the stored value. Changing this list will NOT change - the property. - For manipulation of the stored values use the append, extend, and direct - access methods (using brackets). - - For example: - >>> p = odml.Property("prop", value=[1, 2, 3]) - >>> print(p.value) - [1, 2, 3] - >>> p.value.append(4) - >>> print(p.value) - [1, 2, 3] + Deprecated alias of 'values'. Will be removed with the next minor release. + """ + print("The attribute 'value' is deprecated. Please use 'values' instead.") + return self.values - Individual values can be accessed and manipulated like this: - >>> print(p[0]) - [1] - >>> p[0] = 4 - >>> print(p[0]) - [4] + @value.setter + def value(self, new_value): + """ + Deprecated alias of 'values'. Will be removed with the next minor release. - The values can be iterated e.g. with a loop: - >>> for v in p.value: - >>> print(v) - 4 - 2 - 3 + :param new_value: a single value or list of values. """ - return list(self._values) + print("The attribute 'value' is deprecated. Please use 'values' instead.") + self.values = new_value def value_str(self, index=0): """ @@ -285,31 +270,6 @@ def _convert_value_input(self, new_value): "unsupported data type for values: %s" % type(new_value)) return new_value - @value.setter - def value(self, new_value): - """ - Set the value of the property discarding any previous information. - Method will try to convert the passed value to the dtype of - the property and raise an ValueError if not possible. - - :param new_value: a single value or list of values. - """ - # Make sure boolean value 'False' gets through as well... - if new_value is None or \ - (isinstance(new_value, (list, tuple, str)) and len(new_value) == 0): - self._values = [] - return - - new_value = self._convert_value_input(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.value: passed values are not of " - "consistent type!") - self._values = [dtypes.get(v, self.dtype) for v in new_value] - @property def values(self): """ @@ -364,7 +324,7 @@ def values(self, new_value): self._dtype = dtypes.infer_dtype(new_value[0]) if not self._validate_values(new_value): - raise ValueError("odml.Property.value: passed values are not of " + raise ValueError("odml.Property.values: passed values are not of " "consistent type!") self._values = [dtypes.get(v, self.dtype) for v in new_value] From 73e230eb0b5f114413692d3f85cefe49fbeb420f Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Tue, 20 Nov 2018 15:38:00 +0100 Subject: [PATCH 07/24] [Property] Use 'values' instead of 'value' --- odml/property.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/odml/property.py b/odml/property.py index 952c34cb..b7fe22d0 100644 --- a/odml/property.py +++ b/odml/property.py @@ -79,7 +79,7 @@ def __init__(self, name=None, value=None, parent=None, unit=None, print("Warning: Unknown dtype '%s'." % dtype) self._values = [] - self.value = value + self.values = value self.parent = parent @@ -169,7 +169,7 @@ def dtype(self, new_type): old_values = self._values try: self._dtype = new_type - self.value = old_values + self.values = old_values except: self._dtype = old_type # If conversion failed, restore old dtype raise ValueError("cannot convert from '%s' to '%s'" % @@ -435,7 +435,7 @@ def clone(self, keep_id=False): """ obj = super(BaseProperty, self).clone() obj._parent = None - obj.value = self._values + obj.values = self._values if not keep_id: obj.new_id() @@ -459,7 +459,7 @@ def merge_check(self, source, strict=True): # Catch unmerge-able values at this point to avoid # failing Section tree merges which cannot easily be rolled back. - new_value = self._convert_value_input(source.value) + new_value = self._convert_value_input(source.values) if not self._validate_values(new_value): raise ValueError("odml.Property.merge: passed value(s) cannot " "be converted to data type '%s'!" % self._dtype) @@ -530,7 +530,7 @@ def merge(self, other, strict=True): if self.unit is None and other.unit is not None: self.unit = other.unit - to_add = [v for v in other.value if v not in self._values] + to_add = [v for v in other.values if v not in self._values] self.extend(to_add, strict=strict) def unmerge(self, other): @@ -575,11 +575,11 @@ def extend(self, obj, strict=True): if obj.unit != self.unit: raise ValueError("odml.Property.extend: src and dest units (%s, %s) " "do not match!" % (obj.unit, self.unit)) - self.extend(obj.value) + self.extend(obj.values) return if self.__len__() == 0: - self.value = obj + self.values = obj return new_value = self._convert_value_input(obj) @@ -605,8 +605,8 @@ def append(self, obj, strict=True): if obj in [None, "", [], {}]: return - if not self.value: - self.value = obj + if not self.values: + self.values = obj return new_value = self._convert_value_input(obj) From 35bc91c5d6c3a94f1ba4570c0f94d5e107f4f1a1 Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Tue, 20 Nov 2018 15:39:16 +0100 Subject: [PATCH 08/24] [tools/dumper] Use 'values' instead of 'value' --- odml/tools/dumper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/odml/tools/dumper.py b/odml/tools/dumper.py index dfb34a7c..4f8e1b21 100644 --- a/odml/tools/dumper.py +++ b/odml/tools/dumper.py @@ -21,7 +21,7 @@ def get_props(obj, props): def dumpProperty(property, indent=1): # TODO : (PEP8) Find a better way to split the following line print("%*s:%s (%s)" % (indent, " ", property.name, - get_props(property, ["definition", "value", "uncertainty", "unit", + get_props(property, ["definition", "values", "uncertainty", "unit", "dtype", "value_reference", "dependency", "dependencyValue"]))) From 73edc26424d0e79ba6096154b6c3d89857b74fe8 Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Tue, 20 Nov 2018 15:42:11 +0100 Subject: [PATCH 09/24] [validation] Use prop 'values' instead of 'value' --- odml/validation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/odml/validation.py b/odml/validation.py index 0940f33e..2e9852d7 100644 --- a/odml/validation.py +++ b/odml/validation.py @@ -291,7 +291,7 @@ def property_dependency_check(prop): LABEL_WARNING) return - if prop.dependency_value not in dep_obj.value[0]: + if prop.dependency_value not in dep_obj.values[0]: yield ValidationError(prop, "Dependency-value is not equal to value of" " the property's dependency", LABEL_WARNING) From 398658130eec007ce12ff38836b466d1509ade22 Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Tue, 20 Nov 2018 15:46:44 +0100 Subject: [PATCH 10/24] [tools/dictparser] Prop 'values' replaces 'value' --- odml/tools/dict_parser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/odml/tools/dict_parser.py b/odml/tools/dict_parser.py index 2da96fc1..9151dac7 100644 --- a/odml/tools/dict_parser.py +++ b/odml/tools/dict_parser.py @@ -88,8 +88,8 @@ def get_properties(props_list): # Custom odML tuples require special handling # for save loading from file. if attr == "value" and prop.dtype and \ - prop.dtype.endswith("-tuple") and len(prop.value) > 0: - prop_dict["value"] = "(%s)" % ";".join(prop.value[0]) + prop.dtype.endswith("-tuple") and len(prop.values) > 0: + prop_dict["value"] = "(%s)" % ";".join(prop.values[0]) else: # Always use the arguments key attribute name when saving prop_dict[i] = tag From 8fb442280e3bc8f89c2e036a11d35fdf93ab8e29 Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Tue, 20 Nov 2018 15:49:31 +0100 Subject: [PATCH 11/24] [base] Use prop 'values' instead of 'value' --- odml/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/odml/base.py b/odml/base.py index 4cb674a7..0891da20 100644 --- a/odml/base.py +++ b/odml/base.py @@ -357,8 +357,8 @@ def itervalues(self, max_depth=None, filter_func=lambda x: True): :type filter_func: function """ for prop in [p for p in self.iterproperties(max_depth=max_depth)]: - if filter_func(prop.value): - yield prop.value + if filter_func(prop.values): + yield prop.values def contains(self, obj): """ From ac7e0f7408918b88f9bd563b388e8908bc18a8ae Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Wed, 21 Nov 2018 15:18:38 +0100 Subject: [PATCH 12/24] [Property] Provide 'values' and 'value' on init --- odml/property.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/odml/property.py b/odml/property.py index b7fe22d0..08cb1db5 100644 --- a/odml/property.py +++ b/odml/property.py @@ -13,10 +13,10 @@ class BaseProperty(base.BaseObject): """An odML Property""" _format = frmt.Property - def __init__(self, name=None, value=None, parent=None, unit=None, + def __init__(self, name=None, values=None, parent=None, unit=None, uncertainty=None, reference=None, definition=None, dependency=None, dependency_value=None, dtype=None, - value_origin=None, oid=None): + value_origin=None, oid=None, value=None): """ Create a new Property. If a value without an explicitly stated dtype has been provided, the method will try to infer the value's dtype. @@ -31,8 +31,8 @@ def __init__(self, name=None, value=None, parent=None, unit=None, >>> p.dtype >>> int :param name: The name of the property. - :param value: Some data value, it can be a single value or - a list of homogeneous values. + :param values: Some data value, it can be a single value or + a list of homogeneous values. :param unit: The unit of the stored data. :param uncertainty: The uncertainty (e.g. the standard deviation) associated with a measure value. @@ -48,6 +48,8 @@ def __init__(self, name=None, value=None, parent=None, unit=None, :param oid: object id, UUID string as specified in RFC 4122. If no id is provided, an id will be generated and assigned. An id has to be unique within an odML Document. + :param value: Legacy code to the 'values' attribute. If 'values' is provided, + any data provided via 'value' will be ignored. """ try: if oid is not None: @@ -79,7 +81,9 @@ def __init__(self, name=None, value=None, parent=None, unit=None, print("Warning: Unknown dtype '%s'." % dtype) self._values = [] - self.values = value + self.values = values + if not values and (value or isinstance(value, bool)): + self.values = value self.parent = parent From b0a0b25bbed40cbca8636bb4949e4399e5162a40 Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Wed, 21 Nov 2018 15:19:11 +0100 Subject: [PATCH 13/24] [format] Add Property values to value mapping --- odml/format.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/odml/format.py b/odml/format.py index c0ae3342..1cbfcb4d 100644 --- a/odml/format.py +++ b/odml/format.py @@ -109,7 +109,8 @@ class Property(Format): _map = { 'dependencyvalue': 'dependency_value', 'type': 'dtype', - 'id': 'oid' + 'id': 'oid', + 'value': 'values' } _rdf_map = { 'id': _ns.hasId, From 7a3a5b054d48c40077eb2d3f3986063712a0d069 Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Wed, 21 Nov 2018 15:20:28 +0100 Subject: [PATCH 14/24] [tools/xmlreader] Proper 'values' handling on load --- odml/tools/xmlparser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/odml/tools/xmlparser.py b/odml/tools/xmlparser.py index c6d08cc3..70b3bb3d 100644 --- a/odml/tools/xmlparser.py +++ b/odml/tools/xmlparser.py @@ -293,7 +293,7 @@ def parse_tag(self, root, fmt, insert_children=True): # Special handling of values; curr_text = node.text.strip() if node.text else None - if tag == "value" and curr_text: + if tag == "values" and curr_text: content = from_csv(node.text) arguments[tag] = content else: From 8156605ebc36ff55aab53260adcd7451a6e9cbcd Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Wed, 21 Nov 2018 15:21:56 +0100 Subject: [PATCH 15/24] [tools/dictparser] Proper 'values' handling on save Closes #308 --- odml/tools/dict_parser.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/odml/tools/dict_parser.py b/odml/tools/dict_parser.py index 9151dac7..f10a77a9 100644 --- a/odml/tools/dict_parser.py +++ b/odml/tools/dict_parser.py @@ -84,10 +84,9 @@ def get_properties(props_list): tag = getattr(prop, attr) if isinstance(tag, tuple): prop_dict[attr] = list(tag) - elif (tag == []) or tag: # Even if 'value' is empty, allow '[]' - # Custom odML tuples require special handling - # for save loading from file. - if attr == "value" and prop.dtype and \ + elif (tag == []) or tag: # Even if 'values' is empty, allow '[]' + # Custom odML tuples require special handling. + if attr == "values" and prop.dtype and \ prop.dtype.endswith("-tuple") and len(prop.values) > 0: prop_dict["value"] = "(%s)" % ";".join(prop.values[0]) else: From 2d1a796e6a6c867c2015dd6aa21fb15aff2a3bcf Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Wed, 21 Nov 2018 15:22:48 +0100 Subject: [PATCH 16/24] [test] Adapt tests to new Property.values --- test/test_dtypes_integration.py | 96 +++++++++++----------- test/test_dumper.py | 16 ++-- test/test_infer_type.py | 42 +++++----- test/test_property.py | 96 +++++++++++----------- test/test_samplefile.py | 16 ++-- test/test_section.py | 10 +-- test/test_version_converter_integration.py | 6 +- 7 files changed, 141 insertions(+), 141 deletions(-) diff --git a/test/test_dtypes_integration.py b/test/test_dtypes_integration.py index aaaf6b5a..6550124a 100644 --- a/test/test_dtypes_integration.py +++ b/test/test_dtypes_integration.py @@ -48,12 +48,12 @@ def test_time(self): jdoc = odml.load(self.json_file, "JSON") self.assertEqual(jdoc.sections[0].properties[0].dtype, odml.dtypes.DType.time) - self.assertIsInstance(jdoc.sections[0].properties[0].value[0], dt.time) + self.assertIsInstance(jdoc.sections[0].properties[0].values[0], dt.time) self.assertEqual(jdoc.sections[0].properties[1].dtype, odml.dtypes.DType.time) for val in jdoc.sections[0].properties[1].value: self.assertIsInstance(val, dt.time) - self.assertEqual(jdoc.sections[0].properties[1].value[2], time) - self.assertEqual(jdoc.sections[0].properties[1].value[3], time) + self.assertEqual(jdoc.sections[0].properties[1].values[2], time) + self.assertEqual(jdoc.sections[0].properties[1].values[3], time) self.assertEqual(self.doc, jdoc) # Test correct xml save and load. @@ -61,12 +61,12 @@ def test_time(self): xdoc = odml.load(self.xml_file) self.assertEqual(xdoc.sections[0].properties[0].dtype, odml.dtypes.DType.time) - self.assertIsInstance(xdoc.sections[0].properties[0].value[0], dt.time) + self.assertIsInstance(xdoc.sections[0].properties[0].values[0], dt.time) self.assertEqual(xdoc.sections[0].properties[1].dtype, odml.dtypes.DType.time) for val in xdoc.sections[0].properties[1].value: self.assertIsInstance(val, dt.time) - self.assertEqual(xdoc.sections[0].properties[1].value[2], time) - self.assertEqual(xdoc.sections[0].properties[1].value[2], time) + self.assertEqual(xdoc.sections[0].properties[1].values[2], time) + self.assertEqual(xdoc.sections[0].properties[1].values[2], time) self.assertEqual(self.doc, xdoc) # Test correct yaml save and load. @@ -74,12 +74,12 @@ def test_time(self): ydoc = odml.load(self.yaml_file, "YAML") self.assertEqual(ydoc.sections[0].properties[0].dtype, odml.dtypes.DType.time) - self.assertIsInstance(ydoc.sections[0].properties[0].value[0], dt.time) + self.assertIsInstance(ydoc.sections[0].properties[0].values[0], dt.time) self.assertEqual(ydoc.sections[0].properties[1].dtype, odml.dtypes.DType.time) for val in ydoc.sections[0].properties[1].value: self.assertIsInstance(val, dt.time) - self.assertEqual(ydoc.sections[0].properties[1].value[2], time) - self.assertEqual(ydoc.sections[0].properties[1].value[2], time) + self.assertEqual(ydoc.sections[0].properties[1].values[2], time) + self.assertEqual(ydoc.sections[0].properties[1].values[2], time) self.assertEqual(self.doc, ydoc) def test_date(self): @@ -98,12 +98,12 @@ def test_date(self): jdoc = odml.load(self.json_file, "JSON") self.assertEqual(jdoc.sections[0].properties[0].dtype, odml.dtypes.DType.date) - self.assertIsInstance(jdoc.sections[0].properties[0].value[0], dt.date) + self.assertIsInstance(jdoc.sections[0].properties[0].values[0], dt.date) self.assertEqual(jdoc.sections[0].properties[1].dtype, odml.dtypes.DType.date) for val in jdoc.sections[0].properties[1].value: self.assertIsInstance(val, dt.date) - self.assertEqual(jdoc.sections[0].properties[1].value[2], date) - self.assertEqual(jdoc.sections[0].properties[1].value[3], date) + self.assertEqual(jdoc.sections[0].properties[1].values[2], date) + self.assertEqual(jdoc.sections[0].properties[1].values[3], date) self.assertEqual(self.doc, jdoc) # Test correct xml save and load. @@ -111,12 +111,12 @@ def test_date(self): xdoc = odml.load(self.xml_file) self.assertEqual(xdoc.sections[0].properties[0].dtype, odml.dtypes.DType.date) - self.assertIsInstance(xdoc.sections[0].properties[0].value[0], dt.date) + self.assertIsInstance(xdoc.sections[0].properties[0].values[0], dt.date) self.assertEqual(xdoc.sections[0].properties[1].dtype, odml.dtypes.DType.date) for val in xdoc.sections[0].properties[1].value: self.assertIsInstance(val, dt.date) - self.assertEqual(xdoc.sections[0].properties[1].value[2], date) - self.assertEqual(xdoc.sections[0].properties[1].value[2], date) + self.assertEqual(xdoc.sections[0].properties[1].values[2], date) + self.assertEqual(xdoc.sections[0].properties[1].values[2], date) self.assertEqual(self.doc, xdoc) # Test correct yaml save and load. @@ -124,12 +124,12 @@ def test_date(self): ydoc = odml.load(self.yaml_file, "YAML") self.assertEqual(ydoc.sections[0].properties[0].dtype, odml.dtypes.DType.date) - self.assertIsInstance(ydoc.sections[0].properties[0].value[0], dt.date) + self.assertIsInstance(ydoc.sections[0].properties[0].values[0], dt.date) self.assertEqual(ydoc.sections[0].properties[1].dtype, odml.dtypes.DType.date) for val in ydoc.sections[0].properties[1].value: self.assertIsInstance(val, dt.date) - self.assertEqual(ydoc.sections[0].properties[1].value[2], date) - self.assertEqual(ydoc.sections[0].properties[1].value[2], date) + self.assertEqual(ydoc.sections[0].properties[1].values[2], date) + self.assertEqual(ydoc.sections[0].properties[1].values[2], date) self.assertEqual(self.doc, ydoc) def test_datetime(self): @@ -148,12 +148,12 @@ def test_datetime(self): jdoc = odml.load(self.json_file, "JSON") self.assertEqual(jdoc.sections[0].properties[0].dtype, odml.dtypes.DType.datetime) - self.assertIsInstance(jdoc.sections[0].properties[0].value[0], dt.datetime) + self.assertIsInstance(jdoc.sections[0].properties[0].values[0], dt.datetime) self.assertEqual(jdoc.sections[0].properties[1].dtype, odml.dtypes.DType.datetime) for val in jdoc.sections[0].properties[1].value: self.assertIsInstance(val, dt.datetime) - self.assertEqual(jdoc.sections[0].properties[1].value[2], date_time) - self.assertEqual(jdoc.sections[0].properties[1].value[3], date_time) + self.assertEqual(jdoc.sections[0].properties[1].values[2], date_time) + self.assertEqual(jdoc.sections[0].properties[1].values[3], date_time) self.assertEqual(self.doc, jdoc) # Test correct xml save and load. @@ -161,12 +161,12 @@ def test_datetime(self): xdoc = odml.load(self.xml_file) self.assertEqual(xdoc.sections[0].properties[0].dtype, odml.dtypes.DType.datetime) - self.assertIsInstance(xdoc.sections[0].properties[0].value[0], dt.datetime) + self.assertIsInstance(xdoc.sections[0].properties[0].values[0], dt.datetime) self.assertEqual(xdoc.sections[0].properties[1].dtype, odml.dtypes.DType.datetime) for val in xdoc.sections[0].properties[1].value: self.assertIsInstance(val, dt.datetime) - self.assertEqual(xdoc.sections[0].properties[1].value[2], date_time) - self.assertEqual(xdoc.sections[0].properties[1].value[2], date_time) + self.assertEqual(xdoc.sections[0].properties[1].values[2], date_time) + self.assertEqual(xdoc.sections[0].properties[1].values[2], date_time) self.assertEqual(self.doc, xdoc) # Test correct yaml save and load. @@ -174,12 +174,12 @@ def test_datetime(self): ydoc = odml.load(self.yaml_file, "YAML") self.assertEqual(ydoc.sections[0].properties[0].dtype, odml.dtypes.DType.datetime) - self.assertIsInstance(ydoc.sections[0].properties[0].value[0], dt.datetime) + self.assertIsInstance(ydoc.sections[0].properties[0].values[0], dt.datetime) self.assertEqual(ydoc.sections[0].properties[1].dtype, odml.dtypes.DType.datetime) for val in ydoc.sections[0].properties[1].value: self.assertIsInstance(val, dt.datetime) - self.assertEqual(ydoc.sections[0].properties[1].value[2], date_time) - self.assertEqual(ydoc.sections[0].properties[1].value[2], date_time) + self.assertEqual(ydoc.sections[0].properties[1].values[2], date_time) + self.assertEqual(ydoc.sections[0].properties[1].values[2], date_time) self.assertEqual(self.doc, ydoc) def test_int(self): @@ -193,7 +193,7 @@ def test_int(self): jdoc = odml.load(self.json_file, "JSON") self.assertEqual(jdoc.sections[0].properties[0].dtype, odml.dtypes.DType.int) - self.assertEqual(jdoc.sections[0].properties[0].value, val_odml) + self.assertEqual(jdoc.sections[0].properties[0].values, val_odml) self.assertEqual(self.doc, jdoc) # Test correct xml save and load. @@ -201,7 +201,7 @@ def test_int(self): xdoc = odml.load(self.xml_file) self.assertEqual(xdoc.sections[0].properties[0].dtype, odml.dtypes.DType.int) - self.assertEqual(xdoc.sections[0].properties[0].value, val_odml) + self.assertEqual(xdoc.sections[0].properties[0].values, val_odml) self.assertEqual(self.doc, xdoc) # Test correct yaml save and load. @@ -209,7 +209,7 @@ def test_int(self): ydoc = odml.load(self.yaml_file, "YAML") self.assertEqual(ydoc.sections[0].properties[0].dtype, odml.dtypes.DType.int) - self.assertEqual(ydoc.sections[0].properties[0].value, val_odml) + self.assertEqual(ydoc.sections[0].properties[0].values, val_odml) self.assertEqual(self.doc, ydoc) def test_float(self): @@ -224,7 +224,7 @@ def test_float(self): jdoc = odml.load(self.json_file, "JSON") self.assertEqual(jdoc.sections[0].properties[0].dtype, odml.dtypes.DType.float) - self.assertEqual(jdoc.sections[0].properties[0].value, val_odml) + self.assertEqual(jdoc.sections[0].properties[0].values, val_odml) self.assertEqual(self.doc, jdoc) # Test correct xml save and load. @@ -232,7 +232,7 @@ def test_float(self): xdoc = odml.load(self.xml_file) self.assertEqual(xdoc.sections[0].properties[0].dtype, odml.dtypes.DType.float) - self.assertEqual(xdoc.sections[0].properties[0].value, val_odml) + self.assertEqual(xdoc.sections[0].properties[0].values, val_odml) self.assertEqual(self.doc, xdoc) # Test correct yaml save and load. @@ -240,7 +240,7 @@ def test_float(self): ydoc = odml.load(self.yaml_file, "YAML") self.assertEqual(ydoc.sections[0].properties[0].dtype, odml.dtypes.DType.float) - self.assertEqual(ydoc.sections[0].properties[0].value, val_odml) + self.assertEqual(ydoc.sections[0].properties[0].values, val_odml) self.assertEqual(self.doc, ydoc) def test_str(self): @@ -258,9 +258,9 @@ def test_str(self): jdoc = odml.load(self.json_file, "JSON") self.assertEqual(jdoc.sections[0].properties[0].dtype, odml.dtypes.DType.string) - self.assertEqual(jdoc.sections[0].properties[0].value, [val_in]) + self.assertEqual(jdoc.sections[0].properties[0].values, [val_in]) self.assertEqual(jdoc.sections[0].properties[1].dtype, odml.dtypes.DType.string) - self.assertEqual(jdoc.sections[0].properties[1].value, vals_odml) + self.assertEqual(jdoc.sections[0].properties[1].values, vals_odml) self.assertEqual(self.doc, jdoc) # Test correct xml save and load. @@ -268,9 +268,9 @@ def test_str(self): xdoc = odml.load(self.xml_file) self.assertEqual(xdoc.sections[0].properties[0].dtype, odml.dtypes.DType.string) - self.assertEqual(xdoc.sections[0].properties[0].value, [val_in]) + self.assertEqual(xdoc.sections[0].properties[0].values, [val_in]) self.assertEqual(xdoc.sections[0].properties[1].dtype, odml.dtypes.DType.string) - self.assertEqual(xdoc.sections[0].properties[1].value, vals_odml) + self.assertEqual(xdoc.sections[0].properties[1].values, vals_odml) self.assertEqual(self.doc, xdoc) # Test correct yaml save and load. @@ -278,9 +278,9 @@ def test_str(self): ydoc = odml.load(self.yaml_file, "YAML") self.assertEqual(ydoc.sections[0].properties[0].dtype, odml.dtypes.DType.string) - self.assertEqual(ydoc.sections[0].properties[0].value, [val_in]) + self.assertEqual(ydoc.sections[0].properties[0].values, [val_in]) self.assertEqual(ydoc.sections[0].properties[1].dtype, odml.dtypes.DType.string) - self.assertEqual(ydoc.sections[0].properties[1].value, vals_odml) + self.assertEqual(ydoc.sections[0].properties[1].values, vals_odml) self.assertEqual(self.doc, ydoc) def test_bool(self): @@ -298,9 +298,9 @@ def test_bool(self): jdoc = odml.load(self.json_file, "JSON") self.assertEqual(jdoc.sections[0].properties[0].dtype, odml.dtypes.DType.boolean) - self.assertEqual(jdoc.sections[0].properties[0].value, [val_in]) + self.assertEqual(jdoc.sections[0].properties[0].values, [val_in]) self.assertEqual(jdoc.sections[0].properties[1].dtype, odml.dtypes.DType.boolean) - self.assertEqual(jdoc.sections[0].properties[1].value, vals_odml) + self.assertEqual(jdoc.sections[0].properties[1].values, vals_odml) self.assertEqual(self.doc, jdoc) # Test correct xml save and load. @@ -308,9 +308,9 @@ def test_bool(self): xdoc = odml.load(self.xml_file) self.assertEqual(xdoc.sections[0].properties[0].dtype, odml.dtypes.DType.boolean) - self.assertEqual(xdoc.sections[0].properties[0].value, [val_in]) + self.assertEqual(xdoc.sections[0].properties[0].values, [val_in]) self.assertEqual(xdoc.sections[0].properties[1].dtype, odml.dtypes.DType.boolean) - self.assertEqual(xdoc.sections[0].properties[1].value, vals_odml) + self.assertEqual(xdoc.sections[0].properties[1].values, vals_odml) self.assertEqual(self.doc, xdoc) # Test correct yaml save and load. @@ -318,9 +318,9 @@ def test_bool(self): ydoc = odml.load(self.yaml_file, "YAML") self.assertEqual(ydoc.sections[0].properties[0].dtype, odml.dtypes.DType.boolean) - self.assertEqual(ydoc.sections[0].properties[0].value, [val_in]) + self.assertEqual(ydoc.sections[0].properties[0].values, [val_in]) self.assertEqual(ydoc.sections[0].properties[1].dtype, odml.dtypes.DType.boolean) - self.assertEqual(ydoc.sections[0].properties[1].value, vals_odml) + self.assertEqual(ydoc.sections[0].properties[1].values, vals_odml) self.assertEqual(self.doc, ydoc) def test_tuple(self): @@ -337,7 +337,7 @@ def test_tuple(self): jdoc = odml.load(self.json_file, "JSON") self.assertEqual(jdoc.sections[0].properties[0].dtype, val_type) - self.assertEqual(jdoc.sections[0].properties[0].value, [val_odml]) + self.assertEqual(jdoc.sections[0].properties[0].values, [val_odml]) self.assertEqual(self.doc, jdoc) # Test correct xml save and load. @@ -345,7 +345,7 @@ def test_tuple(self): xdoc = odml.load(self.xml_file) self.assertEqual(xdoc.sections[0].properties[0].dtype, val_type) - self.assertEqual(xdoc.sections[0].properties[0].value, [val_odml]) + self.assertEqual(xdoc.sections[0].properties[0].values, [val_odml]) self.assertEqual(self.doc, xdoc) # Test correct yaml save and load. @@ -353,5 +353,5 @@ def test_tuple(self): ydoc = odml.load(self.yaml_file, "YAML") self.assertEqual(ydoc.sections[0].properties[0].dtype, val_type) - self.assertEqual(ydoc.sections[0].properties[0].value, [val_odml]) + self.assertEqual(ydoc.sections[0].properties[0].values, [val_odml]) self.assertEqual(self.doc, ydoc) diff --git a/test/test_dumper.py b/test/test_dumper.py index d7324c2a..2a326ad4 100644 --- a/test/test_dumper.py +++ b/test/test_dumper.py @@ -18,17 +18,17 @@ def setUp(self): self.doc = odml.Document(author='Rave', version='1.0') s1 = odml.Section(name='Cell') - p1 = odml.Property(name='Type', value='Rechargeable') + p1 = odml.Property(name='Type', values='Rechargeable') s1.append(p1) s2 = odml.Section(name='Electrolyte') - p2 = odml.Property(name='Composition', value='Ni-Cd') + p2 = odml.Property(name='Composition', values='Ni-Cd') s2.append(p2) s1.append(s2) s3 = odml.Section(name='Electrode') - p3 = odml.Property(name='Material', value='Nickel') - p4 = odml.Property(name='Models', value=['AA', 'AAA']) + p3 = odml.Property(name='Material', values='Nickel') + p4 = odml.Property(name='Models', values=['AA', 'AAA']) s3.append(p3) s3.append(p4) s2.append(s3) @@ -42,12 +42,12 @@ def test_dump_doc(self): output = [x.strip() for x in self.captured_stdout.getvalue().split('\n') if x] expected_output = [] expected_output.append("*Cell ()") - expected_output.append(":Type (value=Rechargeable, dtype='string')") + expected_output.append(":Type (values=Rechargeable, dtype='string')") expected_output.append("*Electrolyte ()") - expected_output.append(":Composition (value=Ni-Cd, dtype='string')") + expected_output.append(":Composition (values=Ni-Cd, dtype='string')") expected_output.append("*Electrode ()") - expected_output.append(":Material (value=Nickel, dtype='string')") - expected_output.append(":Models (value=[AA,AAA], dtype='string')") + expected_output.append(":Material (values=Nickel, dtype='string')") + expected_output.append(":Models (values=[AA,AAA], dtype='string')") self.assertEqual(len(output), len(expected_output)) for i in range(len(output)): self.assertEqual(output[i], expected_output[i]) diff --git a/test/test_infer_type.py b/test/test_infer_type.py index 7f27bc4e..4be47578 100644 --- a/test/test_infer_type.py +++ b/test/test_infer_type.py @@ -11,51 +11,51 @@ def test_string(self): p = Property("test", value="somestring") assert(p.dtype == "string") if sys.version_info < (3, 0): - assert isinstance(p.value[0], unicode) + assert isinstance(p.values[0], unicode) else: - assert isinstance(p.value[0], str) + assert isinstance(p.values[0], str) def test_text(self): p = Property("test", value="some\nstring") assert(p.dtype == "text") if sys.version_info < (3, 0): - assert isinstance(p.value[0], unicode) + assert isinstance(p.values[0], unicode) else: - assert isinstance(p.value[0], str) + assert isinstance(p.values[0], str) def test_int(self): p = Property("test", value=111) assert(p.dtype == "int") - assert isinstance(p.value[0], int) + assert isinstance(p.values[0], int) def test_float(self): p = Property("test", value=3.14) assert(p.dtype == "float") - assert isinstance(p.value[0], float) + assert isinstance(p.values[0], float) def test_datetime(self): p = Property("test", value=dt.now()) assert(p.dtype == "datetime") - assert isinstance(p.value[0], dt) + assert isinstance(p.values[0], dt) def test_date(self): p = Property("test", dt.now().date()) assert(p.dtype == "date") - assert isinstance(p.value[0], date) + assert isinstance(p.values[0], date) def test_time(self): p = Property("test", value=dt.now().time()) assert(p.dtype == "time") - assert isinstance(p.value[0], time) + assert isinstance(p.values[0], time) def test_boolean(self): p = Property("test", True) assert(p.dtype == "boolean") - assert isinstance(p.value[0], bool) + assert isinstance(p.values[0], bool) p = Property("test", False) assert(p.dtype == "boolean") - assert isinstance(p.value[0], bool) + assert isinstance(p.values[0], bool) def test_read_write(self): doc = Document("author") @@ -79,37 +79,37 @@ def test_read_write(self): p = new_sec.properties["strprop"] assert(p.dtype == "string") if sys.version_info < (3, 0): - assert isinstance(p.value[0], unicode) + assert isinstance(p.values[0], unicode) else: - assert isinstance(p.value[0], str) + assert isinstance(p.values[0], str) p = new_sec.properties["txtprop"] assert(p.dtype == "text") if sys.version_info < (3, 0): - assert isinstance(p.value[0], unicode) + assert isinstance(p.values[0], unicode) else: - assert isinstance(p.value[0], str) + assert isinstance(p.values[0], str) p = new_sec.properties["intprop"] assert(p.dtype == "int") - assert isinstance(p.value[0], int) + assert isinstance(p.values[0], int) p = new_sec.properties["floatprop"] assert(p.dtype == "float") - assert isinstance(p.value[0], float) + assert isinstance(p.values[0], float) p = new_sec.properties["datetimeprop"] assert(p.dtype == "datetime") - assert isinstance(p.value[0], dt) + assert isinstance(p.values[0], dt) p = new_sec.properties["dateprop"] assert(p.dtype == "date") - assert isinstance(p.value[0], date) + assert isinstance(p.values[0], date) p = new_sec.properties["timeprop"] assert(p.dtype == "time") - assert isinstance(p.value[0], time) + assert isinstance(p.values[0], time) p = new_sec.properties["boolprop"] assert(p.dtype == "boolean") - assert isinstance(p.value[0], bool) + assert isinstance(p.values[0], bool) diff --git a/test/test_property.py b/test/test_property.py index e99a20da..80a67d61 100644 --- a/test/test_property.py +++ b/test/test_property.py @@ -69,33 +69,33 @@ def test_simple_attributes(self): def test_value(self): p = Property("property", 100) - self.assertEqual(p.value[0], 100) - self.assertIsInstance(p.value, list) + self.assertEqual(p.values[0], 100) + self.assertIsInstance(p.values, list) - p.value = None + p.values = None self.assertEqual(len(p), 0) - p.value = [1, 2, 3] - p.value = "" + p.values = [1, 2, 3] + p.values = "" self.assertEqual(len(p), 0) - p.value = [1, 2, 3] - p.value = [] + p.values = [1, 2, 3] + p.values = [] self.assertEqual(len(p), 0) - p.value = [1, 2, 3] - p.value = () + p.values = [1, 2, 3] + p.values = () self.assertEqual(len(p), 0) - p.value.append(5) - self.assertEqual(len(p.value), 0) + p.values.append(5) + self.assertEqual(len(p.values), 0) p2 = Property("test", {"name": "Marie", "name": "Johanna"}) self.assertEqual(len(p2), 1) # Test tuple dtype value. t = Property(name="Location", value='(39.12; 67.19)', dtype='2-tuple') - tuple_value = t.value[0] # As the formed tuple is a list of list + tuple_value = t.values[0] # As the formed tuple is a list of list self.assertEqual(tuple_value[0], '39.12') self.assertEqual(tuple_value[1], '67.19') @@ -108,22 +108,22 @@ def test_value_append(self): prop = Property(name="append") prop.append(1) self.assertEqual(prop.dtype, DType.int) - self.assertEqual(prop.value, [1]) + self.assertEqual(prop.values, [1]) # Test append with Property dtype. prop = Property(name="append", dtype="int") prop.append(3) - self.assertEqual(prop.value, [3]) + self.assertEqual(prop.values, [3]) # Test append with Property value prop = Property(name="append", value=[1, 2]) prop.append(3) - self.assertEqual(prop.value, [1, 2, 3]) + self.assertEqual(prop.values, [1, 2, 3]) # Test append with Property list value prop = Property(name="append", value=[1, 2]) prop.append([3]) - self.assertEqual(prop.value, [1, 2, 3]) + self.assertEqual(prop.values, [1, 2, 3]) # Test append of empty values, make sure 0 and False are properly handled prop = Property(name="append") @@ -131,31 +131,31 @@ def test_value_append(self): prop.append("") prop.append([]) prop.append({}) - self.assertEqual(prop.value, []) + self.assertEqual(prop.values, []) prop.append(0) - self.assertEqual(prop.value, [0]) + self.assertEqual(prop.values, [0]) - prop.value = None + prop.values = None prop.dtype = None prop.append(False) - self.assertEqual(prop.value, [False]) + self.assertEqual(prop.values, [False]) prop = Property(name="append", value=[1, 2]) prop.append(None) prop.append("") prop.append([]) prop.append({}) - self.assertEqual(prop.value, [1, 2]) + self.assertEqual(prop.values, [1, 2]) prop.append(0) - self.assertEqual(prop.value, [1, 2, 0]) + self.assertEqual(prop.values, [1, 2, 0]) # Test fail append with multiple values prop = Property(name="append", value=[1, 2, 3]) with self.assertRaises(ValueError): prop.append([4, 5]) - self.assertEqual(prop.value, [1, 2, 3]) + self.assertEqual(prop.values, [1, 2, 3]) # Test fail append with mismatching dtype prop = Property(name="append", value=[1, 2], dtype="int") @@ -165,18 +165,18 @@ def test_value_append(self): prop.append([True]) with self.assertRaises(ValueError): prop.append(["5.927"]) - self.assertEqual(prop.value, [1, 2]) + self.assertEqual(prop.values, [1, 2]) # Test strict flag prop.append(3.14, strict=False) prop.append(True, strict=False) prop.append("5.927", strict=False) - self.assertEqual(prop.value, [1, 2, 3, 1, 5]) + self.assertEqual(prop.values, [1, 2, 3, 1, 5]) # Make sure non-convertible values still raise an error with self.assertRaises(ValueError): prop.append("invalid") - self.assertEqual(prop.value, [1, 2, 3, 1, 5]) + self.assertEqual(prop.values, [1, 2, 3, 1, 5]) p5 = Property("test", value="a string") p5.append("Freude") @@ -190,25 +190,25 @@ def test_value_extend(self): val = [1, 2, 3] prop.extend(val) self.assertEqual(prop.dtype, DType.int) - self.assertEqual(prop.value, val) + self.assertEqual(prop.values, val) # Extend with single value. prop.extend(4) - self.assertEqual(prop.value, [1, 2, 3, 4]) + self.assertEqual(prop.values, [1, 2, 3, 4]) # Extend with list value. prop.extend([5, 6]) - self.assertEqual(prop.value, [1, 2, 3, 4, 5, 6]) + self.assertEqual(prop.values, [1, 2, 3, 4, 5, 6]) # Test extend w/o Property value prop = Property(name="extend", dtype="float") prop.extend([1.0, 2.0, 3.0]) - self.assertEqual(prop.value, [1.0, 2.0, 3.0]) + self.assertEqual(prop.values, [1.0, 2.0, 3.0]) # Test extend with Property value prop = Property(name="extend", value=10) prop.extend([20, 30, '40']) - self.assertEqual(prop.value, [10, 20, 30, 40]) + self.assertEqual(prop.values, [10, 20, 30, 40]) # Test extend fail with mismatching dtype with self.assertRaises(ValueError): @@ -220,41 +220,41 @@ def test_value_extend(self): prop = Property(name="extend", value=["a", "b"]) ext_prop = Property(name="value extend", value="c") prop.extend(ext_prop) - self.assertEqual(prop.value, ["a", "b", "c"]) + self.assertEqual(prop.values, ["a", "b", "c"]) - ext_prop.value = ["d", "e"] + ext_prop.values = ["d", "e"] prop.extend(ext_prop) - self.assertEqual(prop.value, ["a", "b", "c", "d", "e"]) + self.assertEqual(prop.values, ["a", "b", "c", "d", "e"]) ext_prop = Property(name="value extend", value=[1, 2 ,3]) with self.assertRaises(ValueError): prop.extend(ext_prop) - self.assertEqual(prop.value, ["a", "b", "c", "d", "e"]) + self.assertEqual(prop.values, ["a", "b", "c", "d", "e"]) # Test extend via Property unit check prop = Property(name="extend", value=[1, 2], unit="mV") ext_prop = Property(name="extend", value=[3, 4], unit="mV") prop.extend(ext_prop) - self.assertEqual(prop.value, [1, 2, 3, 4]) + self.assertEqual(prop.values, [1, 2, 3, 4]) ext_prop.unit = "kV" with self.assertRaises(ValueError): prop.extend(ext_prop) - self.assertEqual(prop.value, [1, 2, 3, 4]) + self.assertEqual(prop.values, [1, 2, 3, 4]) ext_prop.unit = "" with self.assertRaises(ValueError): prop.extend(ext_prop) - self.assertEqual(prop.value, [1, 2, 3, 4]) + self.assertEqual(prop.values, [1, 2, 3, 4]) # Test strict flag prop = Property(name="extend", value=[1, 2], dtype="int") with self.assertRaises(ValueError): prop.extend([3.14, True, "5.927"]) - self.assertEqual(prop.value, [1, 2]) + self.assertEqual(prop.values, [1, 2]) prop.extend([3.14, True, "5.927"], strict=False) - self.assertEqual(prop.value, [1, 2, 3, 1, 5]) + self.assertEqual(prop.values, [1, 2, 3, 1, 5]) # Make sure non-convertible values still raise an error with self.assertRaises(ValueError): @@ -265,7 +265,7 @@ def test_get_set_value(self): p = Property("property", value=values) self.assertEqual(len(p), 5) - for s, d in zip(values, p.value): + for s, d in zip(values, p.values): self.assertEqual(s, d) count = 0 @@ -284,13 +284,13 @@ def test_bool_conversion(self): assert(p.dtype == 'int') p.dtype = DType.boolean assert(p.dtype == 'boolean') - assert(p.value == [True, False, True, False, True]) + assert(p.values == [True, False, True, False, True]) q = Property(name='sent', value=['False', True, 'TRUE', '0', 't', 'F', '1']) assert(q.dtype == 'string') q.dtype = DType.boolean assert(q.dtype == 'boolean') - assert(q.value == [False, True, True, False, True, False, True]) + assert(q.values == [False, True, True, False, True, False, True]) # Failure tests curr_val = [3, 0, 1, 0, 8] @@ -300,7 +300,7 @@ def test_bool_conversion(self): with self.assertRaises(ValueError): p.dtype = DType.boolean assert(p.dtype == curr_type) - assert(p.value == curr_val) + assert(p.values == curr_val) curr_type = 'string' q = Property(name='sent', value=['False', True, 'TRUE', '0', 't', '12', 'Ft']) @@ -315,7 +315,7 @@ def test_str_to_int_convert(self): assert(p.dtype == 'string') p.dtype = DType.int assert(p.dtype == 'int') - assert(p.value == [3, 0, 1, 0, 8]) + assert(p.values == [3, 0, 1, 0, 8]) # Failure Test p = Property(name='dogs_onboard', value=['7', '20', '1 Dog', 'Seven']) @@ -325,7 +325,7 @@ def test_str_to_int_convert(self): p.dtype = DType.int assert(p.dtype == 'string') - assert(p.value == ['7', '20', '1 Dog', 'Seven']) + assert(p.values == ['7', '20', '1 Dog', 'Seven']) def test_name(self): # Test id is used when name is not provided @@ -415,7 +415,7 @@ def test_dtype(self): prop.dtype = "x-tuple" # Test not setting None when a property contains values. - prop.value = [1, 2, 3] + prop.values = [1, 2, 3] self.assertIsNotNone(prop.dtype) prop.dtype = None self.assertIsNotNone(prop.dtype) @@ -558,7 +558,7 @@ def test_merge(self): test_p = p_dst.clone() test_p.merge(p_src) - self.assertEqual(len(test_p.value), 5) + self.assertEqual(len(test_p.values), 5) p_inv_unit = p_src.clone() p_inv_unit.unit = 's' diff --git a/test/test_samplefile.py b/test/test_samplefile.py index 3bd5ec69..6fc2d25b 100644 --- a/test/test_samplefile.py +++ b/test/test_samplefile.py @@ -192,26 +192,26 @@ class AttributeTest(unittest.TestCase): def test_value_int(self): p = odml.Property("test", 1, dtype="int") - self.assertEqual(p.value[0], 1) + self.assertEqual(p.values[0], 1) def test_conversion_int_to_float(self): p = odml.Property("test", "1", dtype="int") self.assertEqual(p.dtype, "int") - self.assertIsInstance(p.value[0], int) + self.assertIsInstance(p.values[0], int) p.dtype = "float" # change dtype self.assertEqual(p.dtype, "float") - self.assertEqual(p.value[0], 1.0) + self.assertEqual(p.values[0], 1.0) def test_conversion_float_to_int(self): p = odml.Property("test", "1.5", dtype="float") self.assertEqual(p.dtype, "float") p.dtype = "int" self.assertEqual(p.dtype, "int") - self.assertEqual(p.value[0], 1) + self.assertEqual(p.values[0], 1) def test_value_float(self): p = odml.Property("test", value="1.5", dtype="float") - self.assertEqual(p.value[0], 1.5) + self.assertEqual(p.values[0], 1.5) class CopyTest(unittest.TestCase): @@ -223,15 +223,15 @@ def test_dependence(self): a = self.p b = self.p self.assertEqual(a, b) - a.value = 5 + a.values = 5 self.assertEqual(a, b) - self.assertEqual(a.value, b.value) + self.assertEqual(a.values, b.values) def test_independence(self): a = self.p.clone() b = self.p.clone() self.assertEqual(a, b) - a.value = 5 + a.values = 5 self.assertNotEqual(a, b) # self.assertUn diff --git a/test/test_section.py b/test/test_section.py index 29ec6496..ba4e3743 100644 --- a/test/test_section.py +++ b/test/test_section.py @@ -773,8 +773,8 @@ def test_merge(self): self.assertEqual(len(destination.sections["lvl"].properties), 1) self.assertIsNone(destination.definition) self.assertIsNone(destination.sections["lvl"].definition) - self.assertEqual(destination.sections["lvl"].properties[0].value, - d_subprop_one.value) + self.assertEqual(destination.sections["lvl"].properties[0].values, + d_subprop_one.values) with self.assertRaises(ValueError): destination.merge(source) @@ -783,8 +783,8 @@ def test_merge(self): self.assertEqual(len(destination.sections["lvl"].properties), 1) self.assertIsNone(destination.definition) self.assertIsNone(destination.sections["lvl"].definition) - self.assertEqual(destination.sections["lvl"].properties[0].value, - d_subprop_one.value) + self.assertEqual(destination.sections["lvl"].properties[0].values, + d_subprop_one.values) def test_comparison(self): sec_name = "sec name" @@ -930,7 +930,7 @@ def test_create_property(self): values = ["a", "b"] prop = root.create_property(name, value=values) self.assertEqual(len(root.properties), 2) - self.assertEqual(root.properties[name].value, values) + self.assertEqual(root.properties[name].values, values) name = "test_dtype" dtype = "str" diff --git a/test/test_version_converter_integration.py b/test/test_version_converter_integration.py index eaafe56d..571dfc45 100644 --- a/test/test_version_converter_integration.py +++ b/test/test_version_converter_integration.py @@ -78,10 +78,10 @@ def check_result(self): self.assertEqual(prop.unit, "arbitrary") self.assertEqual(prop.value_origin, "filename val 1") self.assertEqual(prop.dtype, "string") - self.assertEqual(len(prop.value), 3) + self.assertEqual(len(prop.values), 3) prop = sec.properties["prop_two"] - self.assertEqual(len(prop.value), 8) + self.assertEqual(len(prop.values), 8) prop = sec.properties["prop_three"] - self.assertEqual(len(prop.value), 0) + self.assertEqual(len(prop.values), 0) From bcf53576d6d50c69e7da29f4634d4683ea51c58c Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Thu, 22 Nov 2018 14:58:05 +0100 Subject: [PATCH 17/24] [Property] Add pprint method --- odml/property.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/odml/property.py b/odml/property.py index 08cb1db5..f7b9f825 100644 --- a/odml/property.py +++ b/odml/property.py @@ -626,3 +626,35 @@ def append(self, obj, strict=True): "to data type \'%s\'!" % self._dtype) self._values.append(dtypes.get(new_value[0], self.dtype)) + + def pprint(self, indent=2, max_length=80, current_depth=-1): + """ + Pretty print method to visualize Properties and Section-Property trees. + + :param indent: number of leading spaces for every child Property. + :param max_length: maximum number of characters printed in one line. + :param current_depth: number of hierarchical levels printed from the + starting Section. + """ + property_spaces = "" + prefix = "" + if current_depth >= 0: + property_spaces = " " * ((current_depth + 2) * indent) + prefix = "|-" + + if self.unit is None: + value_string = str(self.values) + else: + value_string = "{}{}".format(self.values, self.unit) + + p_len = len(property_spaces) + len(self.name) + len(value_string) + if p_len >= max_length - 4: + split_len = int((max_length - len(property_spaces) + + len(self.name) - len(prefix))/2) + str1 = value_string[0: split_len] + str2 = value_string[-split_len:] + print(("{}{} {}: {} ... {}".format(property_spaces, prefix, + self.name, str1, str2))) + else: + print(("{}{} {}: {}".format(property_spaces, prefix, self.name, + value_string))) From 3b8d4759cc62768615b7203e23651d7c7663794e Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Thu, 22 Nov 2018 14:58:18 +0100 Subject: [PATCH 18/24] [Section] Add pprint method Closes #309 --- odml/section.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/odml/section.py b/odml/section.py index 658b318b..2d792074 100644 --- a/odml/section.py +++ b/odml/section.py @@ -611,3 +611,30 @@ def create_property(self, name, value=None, dtype=None, oid=None): prop.parent = self return prop + + def pprint(self, indent=2, max_depth=1, max_length=80, current_depth=0): + """ + Pretty print method to visualize Section-Property trees. + + :param indent: number of leading spaces for every child Section or Property. + :param max_length: maximum number of characters printed in one line. + :param current_depth: number of hierarchical levels printed from the + starting Section. + """ + spaces = " " * (current_depth * indent) + sec_str = "{} {} [{}]".format(spaces, self.name, self.type) + print(sec_str) + for p in self.props: + p.pprint(current_depth=current_depth, indent=indent, + max_length=max_length) + if max_depth == -1 or current_depth < max_depth: + for s in self.sections: + s.pprint(current_depth=current_depth+1, max_depth=max_depth, + indent=indent, max_length=max_length) + elif max_depth == current_depth: + child_sec_indent = spaces + " " * indent + more_indent = spaces + " " * (current_depth + 2 * indent) + for s in self.sections: + print("{} {} [{}]\n{}[...]".format(child_sec_indent, + s.name, s.type, + more_indent)) From 66784aeb6c3e6adf4f4145abc57b733b75f32cac Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Thu, 22 Nov 2018 16:36:32 +0100 Subject: [PATCH 19/24] [doc/tutorial] Add Property.values updates --- doc/tutorial.rst | 129 +++++++++++++++++++++++------------------------ 1 file changed, 63 insertions(+), 66 deletions(-) diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 425973ad..a08fb40d 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -237,7 +237,7 @@ The Document If you loaded the example odML file, let's have a first look at the Document:: >>> print odmlEX - + As you can see, the printout gives you a short summary of the Document of the loaded example odML file. @@ -293,7 +293,7 @@ Let's check out all attributes with the following commands:: >>> print(odmlEX.parent) None >>> print(odmlEX.repository) - http://portal.g-node.org/odml/terminologies/v1.0/terminologies.xml + http://portal.g-node.org/odml/terminologies/v1.1/terminologies.xml >>> print(odmlEX.version) 42 @@ -307,7 +307,7 @@ Sections were attached to the Document of our example odML file using the following command:: >>> print(odmlEX.sections) - [
,
] + [Section[4/2] {name = TheCrew, type = crew, id = ...}, Section[1/7] {name = TheStarship, type = starship, id = ...}] As expected from the Document printout our example contains two Sections. The printout and attributes of a Section are explained in the next chapter. @@ -324,13 +324,13 @@ look at the first Section in the sections list attached to the Document in our example odML file:: >>> print(odmlEX.sections['TheCrew']) -
+ Section[4/2] {name = TheCrew, type = crew, id = ...} >>> print(odmlEX.sections[0]) -
+ Section[4/2] {name = TheCrew, type = crew, id = ...} >>> print(odmlEX['TheCrew']) -
+ Section[4/2] {name = TheCrew, type = crew, id = ...} >>> print(odmlEX[0]) -
+ Section[4/2] {name = TheCrew, type = crew, id = ...} In the following we will call Sections explicitly by their name using the short cut notation. @@ -338,17 +338,18 @@ short cut notation. The printout of a Section is similar to the Document printout and gives you already the following information: -- ``<...>`` indicates that you are looking at an object - ``Section`` tells you that you are looking at an odML Section -- ``TheCrew`` is the name of this Section -- ``[...]`` highlights the type of the Section (here ``crew``) -- ``(4)`` states that this Section has four Sections directly attached to it +- ``[4/2]`` states that this Section has four Sections and two Properties directly attached to it +- ``{...}`` provides ``name``, ``type`` and ``id`` of the Section +- ``name`` is the name of this Section, 'TheCrew' in the example case +- ``type`` provides the type of the Section, 'crew' in the example case +- ``id`` provides the uuid of the Section, the actual value has been omitted in the example to improve readability. + -Note that the Section printout tells you nothing about the number of attached -Properties or again about the depth of a possible sub-Section tree below the -directly attached ones. It also only list the type of the Section as one of the -Section attributes. In total, a Section can be defined by the following 5 -attributes: +Note that the Section printout tells you nothing about the depth of a possible +sub-Section tree below the directly attached ones. It also only list the type +of the Section as one of the Section attributes. In total, a Section can be +defined by the following 5 attributes: name - Returns the name of this Section. Should indicate what kind of @@ -413,27 +414,27 @@ To see which Sections are directly attached to the Section 'TheCrew' again use the following command:: >>> print(odmlEX['TheCrew'].sections) - [
, -
, -
, -
] + [Section[0/5] {name = Arthur Philip Dent, type = crew/person, id = ...}, + Section[0/5] {name = Zaphod Beeblebrox, type = crew/person, id = ...}, + Section[0/5] {name = Tricia Marie McMillan, type = crew/person, id = ...}, + Section[0/5] {name = Ford Prefect, type = crew/person, id = ...}] Or, for accessing these sub-Sections:: >>> print(odmlEX['TheCrew'].sections['Ford Prefect']) -
+ Section[0/5] {name = Ford Prefect, type = crew/person, id = ...} >>> print(odmlEX['TheCrew'].sections[3]) -
+ Section[0/5] {name = Ford Prefect, type = crew/person, id = ...} >>> print(odmlEX['TheCrew']['Ford Prefect']) -
+ Section[0/5] {name = Ford Prefect, type = crew/person, id = ...} >>> print(odmlEX['TheCrew'][3]) -
+ Section[0/5] {name = Ford Prefect, type = crew/person, id = ...} As you learned, besides sub-Sections, a Section can also have Properties attached. Let's see which Properties are attached to the Section 'TheCrew':: >>> print(odmlEX['TheCrew'].properties) - [, ] + [Property: {name = NameCrewMembers}, Property: {name = NoCrewMembers}] The printout and attributes of a Property are explained in the next chapter. @@ -445,17 +446,17 @@ Properties need to be called explicitly via the properties function of a Section. You can then either call a Property by name or by index:: >>> print(odmlEX['TheCrew'].properties['NoCrewMembers']) - + Property: {name = NoCrewMembers} >>> print(odmlEX['TheCrew'].properties[1]) - + Property: {name = NoCrewMembers} In the following we will only call Properties explicitly by their name. The Property printout is reduced and only gives you information about the following: -- ``<...>`` indicates that you are looking at an object - ``Property`` tells you that you are looking at an odML Property +- ``{...}`` provides the ``name`` of the Property - ``NoCrewMembers`` is the name of this Property Note that the Property printout tells you nothing about the number of Values, @@ -478,7 +479,7 @@ document parent - Returns the parent Section to which this Property was attached to. -value +values - Returns the metadata of this Property. Can be either a single metadata or multiple, but homogeneous metadata (all with same dtype and unit). For this reason, the output is always provided as a list. @@ -518,7 +519,7 @@ Let's check which attributes were defined for the Property 'NoCrewMembers':: Number of crew members >>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].document) - >>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].value) + >>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].values) [4] >>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].dtype) int @@ -533,22 +534,22 @@ Let's check which attributes were defined for the Property 'NoCrewMembers':: >>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].dependency_value) None -As mentioned the value attribute of a Property can only contain multiple +As mentioned the values attribute of a Property can only contain multiple metadata when they have the same ``dtype`` and ``unit``, as it is the case for the Property 'NameCrewMembers':: - >>> print(odmlEX['TheCrew'].properties['NameCrewMembers'].value) - [u'Arthur Philip Dent', - u'Zaphod Beeblebrox', - u'Tricia Marie McMillan', - u'Ford Prefect'] + >>> print(odmlEX['TheCrew'].properties['NameCrewMembers'].values) + ['Arthur Philip Dent', + 'Zaphod Beeblebrox', + 'Tricia Marie McMillan', + 'Ford Prefect'] >>> print(odmlEX['TheCrew'].properties['NameCrewMembers'].dtype) person >>> print(odmlEX['TheCrew'].properties['NameCrewMembers'].unit) None -NOTE: 'property.value' will always return a copy! Any direct changes to the -returned list will have no affect on the actual property value. If you want to +NOTE: 'property.values' will always return a copy! Any direct changes to the +returned list will have no affect on the actual property values. If you want to make changes to a property value, either use the 'append', 'extend' and 'remove' methods or assign a new value list to the property. @@ -664,7 +665,7 @@ updated:: >>> print(MYodML) >>> print(MYodML.sections) - [
] + [Section[0/0] {name = TheCrew, type = crew, id = ...}] >>> print(sec1.document) @@ -680,12 +681,12 @@ Let's try this with the next Section we create:: parent=sec1) >>> print(sec2) -
+ Section[0/0] {name = Arthur Philip Dent, type = crew/person, id = ...} >>> print(sec2.document) >>> print(sec2.parent) -
+ [Section[1/0] {name = TheCrew, type = crew, id = ...} Note that all of our created Sections do not contain any Properties yet. Let's see if we can change this... @@ -698,7 +699,7 @@ Let's create our first Property:: >>> prop1 = odml.Property(name="Gender", definition="Sex of the subject", - value="male") + values="male") Note that again, only the name attribute is obligatory for creating a Property. The remaining attributes can be defined later on, or are automatically @@ -752,16 +753,16 @@ automatically update its parent attribute:: >>> print(prop1.document) >>> print(prop1.parent) -
+ Section[0/1] {name = Arthur Philip Dent, type = crew/person, id = ...} Next, let us create a Property with multiple metadata entries:: >>> prop2 = odml.Property(name="NameCrewMembers", definition="List of crew members names", - value=["Arthur Philip Dent", - "Zaphod Beeblebrox", - "Tricia Marie McMillan", - "Ford Prefect"], + values=["Arthur Philip Dent", + "Zaphod Beeblebrox", + "Tricia Marie McMillan", + "Ford Prefect"], dtype=odml.DType.person) As you learned before, in such a case, the metadata entries must be @@ -776,12 +777,12 @@ previously created Section 'TheCrew':: Note that it is also possible to add a metadata entry later on:: >>> prop2.append("Blind Passenger") - >>> print(MYodML['TheCrew'].properties['NameCrewMembers'].value) - [u'Arthur Philip Dent', - u'Zaphod Beeblebrox', - u'Tricia Marie McMillan', - u'Ford Prefect', - u'Blind Passenger'] + >>> print(MYodML['TheCrew'].properties['NameCrewMembers'].values) + ['Arthur Philip Dent', + 'Zaphod Beeblebrox', + 'Tricia Marie McMillan', + 'Ford Prefect', + 'Blind Passenger'] The tuple datatype you might have noticed in the dtype table above has to be @@ -794,17 +795,17 @@ by brackets and separated by a semicolon. >>> pixel_prop = odml.Property(name="pixel map") >>> pixel_prop.dtype = "2-tuple" - >>> pixel_prop.value = ["(1; 2)", "(3; 4)"] + >>> pixel_prop.values = ["(1; 2)", "(3; 4)"] >>> voxel_prop = odml.Property(name="voxel map") >>> voxel_prop.dtype = "3-tuple" - >>> voxel_prop.value = "(1; 2; 3)" + >>> voxel_prop.values = "(1; 2; 3)" Please note, that inconsistent tuple values will raise an error: >>> tprop = odml.Property(name="tuple fail") >>> tprop.dtype = "3-tuple" - >>> tprop.value = ["(1; 2)"] + >>> tprop.values = ["(1; 2)"] Printing XML-representation of an odML file: @@ -883,13 +884,13 @@ After creating a Property with metadata the data type can be changed and the format of the corresponding entry will converted to the new data type, if the new format is valid for the given metadata:: - >>> test_dtype_conv = odml.Property('p', value=1.0) - >>> print(test_dtype_conv.value) + >>> test_dtype_conv = odml.Property('p', values=1.0) + >>> print(test_dtype_conv.values) [1.0] >>> print(test_dtype_conv.dtype) float >>> test_dtype_conv.dtype = odml.DType.int - >>> print(test_dtype_conv.value) + >>> print(test_dtype_conv.values) [1] >>> print(test_dtype_conv.dtype) int @@ -899,22 +900,18 @@ If the conversion is invalid a ValueError is raised. Also note, that during such a process metadata loss may occur if a float is converted to an integer and then back to a float:: - >>> test_dtype_conv = odml.Property('p', value=42.42) - >>> print(test_dtype_conv.value) + >>> test_dtype_conv = odml.Property('p', values=42.42) + >>> print(test_dtype_conv.values) [42.42] >>> test_dtype_conv.dtype = odml.DType.int >>> test_dtype_conv.dtype = odml.DType.float - >>> print(test_dtype_conv.value) + >>> print(test_dtype_conv.values) [42.0] Advanced knowledge on Properties -------------------------------- -Dependencies & dependency values -******************************** -(coming soon) - Advanced knowledge on Sections ------------------------------ From 62ca6d874faf2720f0732f157e87824a0b7f6d9a Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Thu, 22 Nov 2018 16:36:54 +0100 Subject: [PATCH 20/24] [CHANGELOG] Add latest changes --- CHANGELOG.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 845c9737..e34a19fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,26 @@ until the next release. # Latest changes in master +... + +# Version 1.4.2 + +## Print methods + +`pprint` methods have been added to both `Section` and `Property` +to print whole Section trees with their child sections and properties. +The `__repr__` style of `Section` and `Property` has been changed to +be more similar to the [nixpy](https://github.com/G-Node/nixpy) `__repr__` style. +Printing a `Section` now also features the immediate `Property` child count +in addition to the immediate `Section` child count. See #309. + +## Deprecation of 'Property.value' in favor of 'Property.values' + +To make working with odML more similar to working with the +metadata part of [nixpy](https://github.com/G-Node/nixpy), the `Property.value` +attribute has been marked deprecated and the `Property.values` +attribute has been added. See #308. + ## Uncertainty changes Uncertainty is now limited to float only. See #294. From 25391bb830caa2d603a7c2ef2e9ed20fb96ebacf Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Fri, 23 Nov 2018 10:38:22 +0100 Subject: [PATCH 21/24] [Section] Switch '/' to '|' in '__repr__' style --- odml/section.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/odml/section.py b/odml/section.py index 2d792074..f27c724b 100644 --- a/odml/section.py +++ b/odml/section.py @@ -57,7 +57,7 @@ def __init__(self, name=None, type=None, parent=None, self.parent = parent def __repr__(self): - return "Section[%d/%d] {name = %s, type = %s, id = %s}" % (len(self._sections), + return "Section[%d|%d] {name = %s, type = %s, id = %s}" % (len(self._sections), len(self._props), self._name, self.type, From db866f1b9e41527d17e5a0c778235979393ee9a8 Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Fri, 23 Nov 2018 10:39:05 +0100 Subject: [PATCH 22/24] [Property] Move '__repr__' to magic method block --- odml/property.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/odml/property.py b/odml/property.py index f7b9f825..5da97893 100644 --- a/odml/property.py +++ b/odml/property.py @@ -104,6 +104,9 @@ def __setitem__(self, key, item): raise ValueError("odml.Property.__setitem__: passed value cannot be " "converted to data type \'%s\'!" % self._dtype) + def __repr__(self): + return "Property: {name = %s}" % self._name + @property def oid(self): """ @@ -147,9 +150,6 @@ def name(self, new_name): self._name = new_name - def __repr__(self): - return "Property: {name = %s}" % self._name - @property def dtype(self): """ From f6422bdd9022784f69c65e1b1aca444e4ae846e3 Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Fri, 23 Nov 2018 10:39:28 +0100 Subject: [PATCH 23/24] [Document] Change '__repr__' to new style --- odml/doc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/odml/doc.py b/odml/doc.py index 1a76344f..279a9b2c 100644 --- a/odml/doc.py +++ b/odml/doc.py @@ -42,8 +42,8 @@ def __init__(self, author=None, date=None, version=None, repository=None, oid=No self._origin_file_name = None def __repr__(self): - return "" % (self._version, self._author, - len(self._sections)) + return "Document %s {author = %s, %d sections}" % \ + (self._version, self._author, len(self._sections)) @property def oid(self): From 3c0208cde02b631a45dc8fd46b5e00929560ebf3 Mon Sep 17 00:00:00 2001 From: "M. Sonntag" Date: Fri, 23 Nov 2018 10:39:59 +0100 Subject: [PATCH 24/24] [doc/tutorial] Add new '__repr__' style changes --- doc/tutorial.rst | 72 +++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/doc/tutorial.rst b/doc/tutorial.rst index a08fb40d..ee123c6d 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -237,18 +237,18 @@ The Document If you loaded the example odML file, let's have a first look at the Document:: >>> print odmlEX - + Document 42 {author = D. N. Adams, 2 sections} As you can see, the printout gives you a short summary of the Document of the loaded example odML file. The print out gives you already the follwing information about the odML file: -- ``<...>`` indicates that you are looking at an object -- ``Doc`` tells you that you are looking at an odML Document +- ``Document`` tells you that you are looking at an odML Document - ``42`` is the user defined version of this odML file -- ``by D. N. Adams`` states the author of the odML file -- ``(2 sections)`` tells you that this odML Document has 2 Section directly +- ``{...}`` provides ``author`` and number of attached sections +- ``author`` states the author of the odML file, "D. N. Adams" in the example case +- ``2 sections`` tells you that this odML Document has 2 Section directly appended Note that the Document printout tells you nothing about the depth of the @@ -289,7 +289,7 @@ Let's check out all attributes with the following commands:: >>> print(odmlEX.date) 1979-10-12 >>> print(odmlEX.document) - + Document 42 {author = D. N. Adams, 2 sections} >>> print(odmlEX.parent) None >>> print(odmlEX.repository) @@ -307,7 +307,8 @@ Sections were attached to the Document of our example odML file using the following command:: >>> print(odmlEX.sections) - [Section[4/2] {name = TheCrew, type = crew, id = ...}, Section[1/7] {name = TheStarship, type = starship, id = ...}] + [Section[4|2] {name = TheCrew, type = crew, id = ...}, + Section[1|7] {name = TheStarship, type = starship, id = ...}] As expected from the Document printout our example contains two Sections. The printout and attributes of a Section are explained in the next chapter. @@ -324,13 +325,13 @@ look at the first Section in the sections list attached to the Document in our example odML file:: >>> print(odmlEX.sections['TheCrew']) - Section[4/2] {name = TheCrew, type = crew, id = ...} + Section[4|2] {name = TheCrew, type = crew, id = ...} >>> print(odmlEX.sections[0]) - Section[4/2] {name = TheCrew, type = crew, id = ...} + Section[4|2] {name = TheCrew, type = crew, id = ...} >>> print(odmlEX['TheCrew']) - Section[4/2] {name = TheCrew, type = crew, id = ...} + Section[4|2] {name = TheCrew, type = crew, id = ...} >>> print(odmlEX[0]) - Section[4/2] {name = TheCrew, type = crew, id = ...} + Section[4|2] {name = TheCrew, type = crew, id = ...} In the following we will call Sections explicitly by their name using the short cut notation. @@ -339,7 +340,7 @@ The printout of a Section is similar to the Document printout and gives you already the following information: - ``Section`` tells you that you are looking at an odML Section -- ``[4/2]`` states that this Section has four Sections and two Properties directly attached to it +- ``[4|2]`` states that this Section has four Sections and two Properties directly attached to it - ``{...}`` provides ``name``, ``type`` and ``id`` of the Section - ``name`` is the name of this Section, 'TheCrew' in the example case - ``type`` provides the type of the Section, 'crew' in the example case @@ -394,9 +395,9 @@ Let's have a look at the attributes for the Section 'TheCrew':: >>> print(odmlEX['TheCrew'].definition) Information on the crew >>> print(odmlEX['TheCrew'].document) - + Document 42 {author = D. N. Adams, 2 sections} >>> print(odmlEX['TheCrew'].parent) - + Document 42 {author = D. N. Adams, 2 sections} >>> print(odmlEX['TheCrew'].type) crew >>> print(odmlEX['TheCrew'].reference) @@ -414,27 +415,28 @@ To see which Sections are directly attached to the Section 'TheCrew' again use the following command:: >>> print(odmlEX['TheCrew'].sections) - [Section[0/5] {name = Arthur Philip Dent, type = crew/person, id = ...}, - Section[0/5] {name = Zaphod Beeblebrox, type = crew/person, id = ...}, - Section[0/5] {name = Tricia Marie McMillan, type = crew/person, id = ...}, - Section[0/5] {name = Ford Prefect, type = crew/person, id = ...}] + [Section[0|5] {name = Arthur Philip Dent, type = crew/person, id = ...}, + Section[0|5] {name = Zaphod Beeblebrox, type = crew/person, id = ...}, + Section[0|5] {name = Tricia Marie McMillan, type = crew/person, id = ...}, + Section[0|5] {name = Ford Prefect, type = crew/person, id = ...}] Or, for accessing these sub-Sections:: >>> print(odmlEX['TheCrew'].sections['Ford Prefect']) - Section[0/5] {name = Ford Prefect, type = crew/person, id = ...} + Section[0|5] {name = Ford Prefect, type = crew/person, id = ...} >>> print(odmlEX['TheCrew'].sections[3]) - Section[0/5] {name = Ford Prefect, type = crew/person, id = ...} + Section[0|5] {name = Ford Prefect, type = crew/person, id = ...} >>> print(odmlEX['TheCrew']['Ford Prefect']) - Section[0/5] {name = Ford Prefect, type = crew/person, id = ...} + Section[0|5] {name = Ford Prefect, type = crew/person, id = ...} >>> print(odmlEX['TheCrew'][3]) - Section[0/5] {name = Ford Prefect, type = crew/person, id = ...} + Section[0|5] {name = Ford Prefect, type = crew/person, id = ...} As you learned, besides sub-Sections, a Section can also have Properties attached. Let's see which Properties are attached to the Section 'TheCrew':: >>> print(odmlEX['TheCrew'].properties) - [Property: {name = NameCrewMembers}, Property: {name = NoCrewMembers}] + [Property: {name = NameCrewMembers}, + Property: {name = NoCrewMembers}] The printout and attributes of a Property are explained in the next chapter. @@ -518,7 +520,7 @@ Let's check which attributes were defined for the Property 'NoCrewMembers':: >>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].definition) Number of crew members >>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].document) - + Document 42 {author = D. N. Adams, 2 sections} >>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].values) [4] >>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].dtype) @@ -586,7 +588,7 @@ You can check if your new Document contains actually what you created by using some of the commands you learned before:: >>> MYodML - >>> + >>> Document None {author = None, 0 sections} As you can see, we created an "empty" Document where the version and the author attributes are not defined and no section is yet attached. You will learn how to create @@ -623,7 +625,7 @@ Check if your new Document contains actually all attributes now:: >>> print(MYodML.date) 1979-10-12 >>> print(MYodML.document) - + Document 42 {author = D. N. Adams, 0 sections} >>> print(MYodML.parent) None >>> print(MYodML.repository) @@ -663,14 +665,14 @@ updated:: >>> MYodML.append(sec1) >>> print(MYodML) - + Document 42 {author = D. N. Adams, 1 sections} >>> print(MYodML.sections) - [Section[0/0] {name = TheCrew, type = crew, id = ...}] + [Section[0|0] {name = TheCrew, type = crew, id = ...}] >>> print(sec1.document) - + Document 42 {author = D. N. Adams, 1 sections} >>> print(sec1.parent) - + Document 42 {author = D. N. Adams, 1 sections} It is also possible to connect a Section directly to a parent object. Let's try this with the next Section we create:: @@ -681,12 +683,12 @@ Let's try this with the next Section we create:: parent=sec1) >>> print(sec2) - Section[0/0] {name = Arthur Philip Dent, type = crew/person, id = ...} + Section[0|0] {name = Arthur Philip Dent, type = crew/person, id = ...} >>> print(sec2.document) - + Document 42 {author = D. N. Adams, 1 sections} >>> print(sec2.parent) - [Section[1/0] {name = TheCrew, type = crew, id = ...} + [Section[1|0] {name = TheCrew, type = crew, id = ...} Note that all of our created Sections do not contain any Properties yet. Let's see if we can change this... @@ -751,9 +753,9 @@ automatically update its parent attribute:: >>> MYodML['TheCrew']['Arthur Philip Dent'].append(prop1) >>> print(prop1.document) - + Document 42 {author = D. N. Adams, 1 sections} >>> print(prop1.parent) - Section[0/1] {name = Arthur Philip Dent, type = crew/person, id = ...} + Section[0|1] {name = Arthur Philip Dent, type = crew/person, id = ...} Next, let us create a Property with multiple metadata entries::