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. diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 425973ad..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,11 +289,11 @@ 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) - 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,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 = ...}] 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 = ...} >>> 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 +339,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 @@ -393,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) @@ -413,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 = ...}] 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 +448,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 +481,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. @@ -517,8 +520,8 @@ 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) - - >>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].value) + Document 42 {author = D. N. Adams, 2 sections} + >>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].values) [4] >>> print(odmlEX['TheCrew'].properties['NoCrewMembers'].dtype) int @@ -533,22 +536,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. @@ -585,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 @@ -622,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) @@ -662,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 = ...}] >>> 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:: @@ -680,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 = ...} >>> print(sec2.document) - + Document 42 {author = D. N. Adams, 1 sections} >>> 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 +701,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 @@ -750,18 +753,18 @@ 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 = ...} 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 +779,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 +797,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 +886,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 +902,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 ------------------------------ 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): """ 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): 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, diff --git a/odml/property.py b/odml/property.py index 74787dd3..5da97893 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: @@ -78,16 +80,18 @@ def __init__(self, name=None, value=None, parent=None, unit=None, else: print("Warning: Unknown dtype '%s'." % dtype) - self._value = [] - self.value = value + self._values = [] + self.values = values + if not values and (value or isinstance(value, bool)): + self.values = 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,11 +99,14 @@ 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) + def __repr__(self): + return "Property: {name = %s}" % self._name + @property def oid(self): """ @@ -143,9 +150,6 @@ def name(self, new_name): self._name = new_name - def __repr__(self): - return "" % self._name - @property def dtype(self): """ @@ -166,10 +170,10 @@ 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 + self.values = old_values except: self._dtype = old_type # If conversion failed, restore old dtype raise ValueError("cannot convert from '%s' to '%s'" % @@ -209,42 +213,27 @@ 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._value) + print("The attribute 'value' is deprecated. Please use 'values' instead.") + self.values = new_value 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): """ @@ -285,19 +274,52 @@ 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): + @property + def values(self): """ - Set the value of the property discarding any previous information. + 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 an ValueError if not possible. + 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._value = [] + self._values = [] return new_value = self._convert_value_input(new_value) @@ -306,9 +328,9 @@ def value(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._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 +416,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 +439,7 @@ def clone(self, keep_id=False): """ obj = super(BaseProperty, self).clone() obj._parent = None - obj.value = self._value + obj.values = self._values if not keep_id: obj.new_id() @@ -441,7 +463,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) @@ -512,7 +534,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.values if v not in self._values] self.extend(to_add, strict=strict) def unmerge(self, other): @@ -557,11 +579,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) @@ -572,7 +594,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): """ @@ -587,8 +609,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) @@ -603,4 +625,36 @@ 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)) + + 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))) diff --git a/odml/section.py b/odml/section.py index bdea5674..f27c724b 100644 --- a/odml/section.py +++ b/odml/section.py @@ -57,7 +57,11 @@ 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[%d|%d] {name = %s, type = %s, id = %s}" % (len(self._sections), + len(self._props), + self._name, + self.type, + self.id) def __iter__(self): """ @@ -607,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)) diff --git a/odml/tools/dict_parser.py b/odml/tools/dict_parser.py index 2da96fc1..f10a77a9 100644 --- a/odml/tools/dict_parser.py +++ b/odml/tools/dict_parser.py @@ -84,12 +84,11 @@ 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 \ - prop.dtype.endswith("-tuple") and len(prop.value) > 0: - prop_dict["value"] = "(%s)" % ";".join(prop.value[0]) + 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: # Always use the arguments key attribute name when saving prop_dict[i] = tag 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"]))) 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: 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) 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)