Repository: G-Node/nix-odML-converter

Issue:
Add more test covering empty/None attributes
I noticed some irregularities when using the converter on files, which do not have entries for all attributes. E.g. the following test fails:

```python
    def test_empty(self):
        odml.Property(name='empty property', value=[],
                      parent=self.odml_doc.sections[0],
                      unit=None, uncertainty=None, reference=None)

        self.test_double_conversion()
```

Discussion:

Patch:
diff --git a/nixodmlconverter/convert.py b/nixodmlconverter/convert.py
index 3a75a14..accb945 100644
--- a/nixodmlconverter/convert.py
+++ b/nixodmlconverter/convert.py
@@ -93,11 +93,9 @@ def user_input(prompt):
 
 def infer_dtype(values):
     """
-    PROTOTYPE
+    Tests, whether values with dtype "string" are maybe of different dtype.
 
-    Tests whether values with dtype "string" are maybe of different dtype.
-
-    :param prop: property the validation is applied on.
+    :param values: values, for which the dtype should be found
     """
 
     dtype_checks = {
@@ -135,18 +133,18 @@ def infer_dtype(values):
 
     if len(set(val_dtypes)) == 1:
         return val_dtypes[0]
-    elif "text" in set(val_dtypes):
+    if "text" in set(val_dtypes):
         return "text"
 
     return "string"
 
+
 def non_binary_value(val):
     if isinstance(val, bytes):
         return str(val, "utf-8")
-    else:
-        return val
+    return val
 
-#def print_same_line(msg):
+# def print_same_line(msg):
 #    """
 #    Print a message to the same line on the command line and
 #    use the appropriate function depending on the Python version.
@@ -197,12 +195,10 @@ def odml_to_nix_property(odmlprop, nixsec):
         if nixv is not None:
             nixvalues.append(nixv)
 
-    if not nixvalues:
-        INFO["skipped empty properties"] += 1
-        return
-
     # We need to get the appropriate NIX DataType for the current odML values
-    dtype = nix.DataType.get_dtype(nixvalues[0])
+    dtype = nix.DataType.String
+    if nixvalues:
+        dtype = nix.DataType.get_dtype(nixvalues[0])
 
     nixprop = nixsec.create_property(odmlprop.name, dtype, oid=odmlprop.id)
 
@@ -220,15 +216,7 @@ def odml_to_nix_property(odmlprop, nixsec):
         nixprop.values = enc_vals
         INFO["mod_prop_values"] += 1
 
-    # Python2 hotfix, since the omega character is not sanitized
-    # in nixpy Property.unit
-    try:
-        nixprop.unit = odmlprop.unit
-    except UnicodeDecodeError:
-        if u"Ω" in odmlprop.unit:
-            print("\n[WARNING] Property.unit currently does not support the omega "
-                  "unicode character. It will be replaced by 'Ohm'.\n")
-            nixprop.unit = odmlprop.unit.replace(u"Ω", "Ohm").encode('ascii')
+    nixprop.unit = odmlprop.unit
 
     nixprop.definition = odmlprop.definition
     nixprop.uncertainty = odmlprop.uncertainty
@@ -305,7 +293,6 @@ def nixwrite(odml_doc, filename, mode='append'):
         odml_to_nix_recurse(odml_doc.sections, nix_document_section)
 
 
-
 ############### NIX -> ODML #################
 
 def odmlwrite(nix_file, filename):
@@ -386,7 +373,10 @@ def nix_to_odml_property(nixprop, odml_sec):
     if odml_type and odml_type.value:
         nix_prop_attributes['dtype'] = non_binary_value(odml_type.value)
     else:
-        nix_prop_attributes['dtype'] = infer_dtype(non_byte_vals)
+        if len(non_byte_vals) == 0:
+            nix_prop_attributes['dtype'] = None
+        else:
+            nix_prop_attributes['dtype'] = infer_dtype(non_byte_vals)
 
     if 'reference' in nix_prop_attributes:
         nix_prop_attributes['reference'] = non_binary_value(nix_prop_attributes.pop('reference'))


Test patch:
diff --git a/test/test_convert.py b/test/test_convert.py
index fe8a01d..df284bf 100644
--- a/test/test_convert.py
+++ b/test/test_convert.py
@@ -30,7 +30,7 @@ class TestBlock(unittest.TestCase):
                      type='testsection', parent=self.odml_doc, reference='reference 1',
                      repository='also unknown', link='???', include=False)
 
-        odml.Property(name='first property', value=[1, 2, 3],
+        odml.Property(name='first property', values=[1, 2, 3],
                       parent=self.odml_doc.sections[0],
                       unit='Volt', uncertainty=3, reference='still unknown',
                       definition='first property recorded', dependency='unknown',
@@ -66,6 +66,6 @@ class TestBlock(unittest.TestCase):
     def test_example_nix_file(self):
         file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 
                                  '../odmlfiles/test')
-        nix_file = nix.File.open(file_path + '.nix', "r")
+        nix_file = nix.File.open(file_path + '.nix', nix.FileMode.ReadOnly)
         convert.odmlwrite(nix_file, file_path + '.xml')
         nix_file.close()
diff --git a/test/test_doc.py b/test/test_doc.py
new file mode 100644
index 0000000..378ec40
--- /dev/null
+++ b/test/test_doc.py
@@ -0,0 +1,92 @@
+import os
+import shutil
+import tempfile
+import unittest
+
+import nixio as nix
+import odml
+
+from nixodmlconverter import convert
+
+
+class TestBlock(unittest.TestCase):
+    def setUp(self):
+        self.test_dir = tempfile.mkdtemp("_odmlnix", "test_", tempfile.gettempdir())
+
+    def tearDown(self):
+        # cleanup temporary files and folder
+        shutil.rmtree(self.test_dir)
+
+    def test_odml_to_nix_none(self):
+        file_name = 'tmp'
+        nix_path = os.path.join(self.test_dir, file_name + '.nix')
+
+        odml_doc = odml.Document(author=None, date=None,
+                                 version=None, repository=None)
+
+        convert.nixwrite(odml_doc, nix_path, 'overwrite')
+        nix_file = nix.File.open(nix_path)
+
+        self.assertEqual(len(nix_file.sections), 1)
+        self.assertEqual(len(nix_file.sections[0].props), 0)
+
+        nix_doc = nix_file.sections[0]
+        self.assertGreater(len(getattr(nix_doc, "id")), 0)
+        nix_file.close()
+
+    def test_odml_to_nix_empty(self):
+        file_name = 'tmp'
+        nix_path = os.path.join(self.test_dir, file_name + '.nix')
+
+        odml_doc = odml.Document()
+
+        convert.nixwrite(odml_doc, nix_path, 'overwrite')
+        nix_file = nix.File.open(nix_path)
+
+        self.assertEqual(len(nix_file.sections), 1)
+        self.assertEqual(len(nix_file.sections[0].props), 0)
+
+        nix_doc = nix_file.sections[0]
+        self.assertGreater(len(getattr(nix_doc, "id")), 0)
+        nix_file.close()
+
+    def test_nix_to_odml_none(self):
+        file_name = 'tmp'
+        nix_path = os.path.join(self.test_dir, file_name + '.nix')
+        odml_path = os.path.join(self.test_dir, file_name + '.xml')
+
+        orig_odml_doc = odml.Document(author=None, date=None,
+                                      version=None, repository=None)
+
+        convert.nixwrite(orig_odml_doc, nix_path, 'overwrite')
+
+        nix_file_r = nix.File.open(nix_path, nix.FileMode.ReadOnly)
+        convert.odmlwrite(nix_file_r, odml_path)
+        odml_doc = odml.load(odml_path)
+
+        self.assertGreater(len(getattr(odml_doc, "id")), 0)
+        self.assertEqual(getattr(odml_doc, "author"), None)
+        self.assertEqual(getattr(odml_doc, "version"), None)
+        self.assertEqual(getattr(odml_doc, "repository"), None)
+
+        nix_file_r.close()
+
+    def test_nix_to_odml_empty(self):
+        file_name = 'tmp'
+        nix_path = os.path.join(self.test_dir, file_name + '.nix')
+        odml_path = os.path.join(self.test_dir, file_name + '.xml')
+
+        orig_odml_doc = odml.Document()
+
+        convert.nixwrite(orig_odml_doc, nix_path, 'overwrite')
+
+        nix_file_r = nix.File.open(nix_path, nix.FileMode.ReadOnly)
+        convert.odmlwrite(nix_file_r, odml_path)
+        odml_doc = odml.load(odml_path)
+
+        self.assertGreater(len(getattr(odml_doc, "id")), 0)
+        self.assertEqual(getattr(odml_doc, "author"), None)
+        self.assertEqual(getattr(odml_doc, "version"), None)
+        self.assertEqual(getattr(odml_doc, "repository"), None)
+
+        nix_file_r.close()
diff --git a/test/test_property.py b/test/test_property.py
new file mode 100644
index 0000000..e70e843
--- /dev/null
+++ b/test/test_property.py
@@ -0,0 +1,156 @@
+import datetime
+import os
+import shutil
+import tempfile
+import unittest
+import numpy as np
+
+import nixio as nix
+import odml
+
+from nixodmlconverter import convert
+
+
+class TestBlock(unittest.TestCase):
+    def setUp(self):
+        self.test_dir = tempfile.mkdtemp("_odmlnix", "test_", tempfile.gettempdir())
+
+        self.odml_doc = odml.Document(author='me', date=datetime.date.today(),
+                                      version='0.0.1', repository='unknown')
+        odml.Section(name='first section', parent=self.odml_doc)
+
+    def tearDown(self):
+        # cleanup temporary files and folder
+        shutil.rmtree(self.test_dir)
+
+    def test_odml_to_nix_none(self):
+        file_name = 'tmp'
+        nix_path = os.path.join(self.test_dir, file_name + '.nix')
+
+        odml.Property(name=None, oid=None, definition=None,
+                      parent=self.odml_doc.sections[0],
+                      values=None, dtype=None,
+                      unit=None, uncertainty=None,
+                      reference=None, dependency=None,
+                      dependency_value=None, value_origin=None)
+
+        convert.nixwrite(self.odml_doc, nix_path, 'overwrite')
+        nix_file = nix.File.open(nix_path)
+
+        self.assertEqual(len(nix_file.sections[0].sections[0].props), 1)
+
+        nix_prop = nix_file.sections[0].sections[0].props[0]
+
+        self.assertGreater(len(getattr(nix_prop, "id")), 0)
+        self.assertEqual(getattr(nix_prop, "name"), getattr(nix_prop, "id"))
+        self.assertEqual(getattr(nix_prop, "values"), ())
+        self.assertEqual(getattr(nix_prop, "data_type"), np.str_)
+        self.assertEqual(getattr(nix_prop, "odml_type"), None)
+        self.assertEqual(getattr(nix_prop, "definition"), None)
+        self.assertEqual(getattr(nix_prop, "unit"), None)
+        self.assertEqual(getattr(nix_prop, "uncertainty"), None)
+        self.assertEqual(getattr(nix_prop, "reference"), None)
+        self.assertEqual(getattr(nix_prop, "dependency"), None)
+        self.assertEqual(getattr(nix_prop, "dependency_value"), None)
+        self.assertEqual(getattr(nix_prop, "value_origin"), None)
+
+        nix_file.close()
+
+    def test_odml_to_nix_empty(self):
+        file_name = 'tmp'
+        nix_path = os.path.join(self.test_dir, file_name + '.nix')
+
+        odml.Property(parent=self.odml_doc.sections[0])
+
+        convert.nixwrite(self.odml_doc, nix_path, 'overwrite')
+        nix_file = nix.File.open(nix_path)
+
+        self.assertEqual(len(nix_file.sections[0].sections[0].props), 1)
+
+        nix_prop = nix_file.sections[0].sections[0].props[0]
+
+        self.assertGreater(len(getattr(nix_prop, "id")), 0)
+        self.assertEqual(getattr(nix_prop, "name"), getattr(nix_prop, "id"))
+        self.assertEqual(getattr(nix_prop, "values"), ())
+        self.assertEqual(getattr(nix_prop, "data_type"), np.str_)
+        self.assertEqual(getattr(nix_prop, "odml_type"), None)
+        self.assertEqual(getattr(nix_prop, "definition"), None)
+        self.assertEqual(getattr(nix_prop, "unit"), None)
+        self.assertEqual(getattr(nix_prop, "uncertainty"), None)
+        self.assertEqual(getattr(nix_prop, "reference"), None)
+        self.assertEqual(getattr(nix_prop, "dependency"), None)
+        self.assertEqual(getattr(nix_prop, "dependency_value"), None)
+        self.assertEqual(getattr(nix_prop, "value_origin"), None)
+
+        nix_file.close()
+
+    def test_nix_to_odml_none(self):
+        file_name = 'tmp'
+        nix_path = os.path.join(self.test_dir, file_name + '.nix')
+        nix_file_w = nix.File.open(nix_path, nix.FileMode.Overwrite)
+        odml_path = os.path.join(self.test_dir, file_name + '.xml')
+
+        odml.Property(name=None, oid=None, definition=None,
+                      parent=self.odml_doc.sections[0],
+                      values=None, dtype=None,
+                      unit=None, uncertainty=None,
+                      reference=None, dependency=None,
+                      dependency_value=None, value_origin=None)
+
+        convert.nixwrite(self.odml_doc, nix_path)
+        nix_file_w.close()
+
+        nix_file_r = nix.File.open(nix_path, nix.FileMode.ReadOnly)
+        convert.odmlwrite(nix_file_r, odml_path)
+        odml_doc = odml.load(odml_path)
+
+        self.assertEqual(len(odml_doc.sections[0].props), 1)
+
+        odml_prop = odml_doc.sections[0].props[0]
+
+        self.assertGreater(len(getattr(odml_prop, "id")), 0)
+        self.assertEqual(getattr(odml_prop, "name"), getattr(odml_prop, "id"))
+        self.assertEqual(getattr(odml_prop, "values"), [])
+        self.assertEqual(getattr(odml_prop, "dtype"), None)
+        self.assertEqual(getattr(odml_prop, "definition"), None)
+        self.assertEqual(getattr(odml_prop, "unit"), None)
+        self.assertEqual(getattr(odml_prop, "uncertainty"), None)
+        self.assertEqual(getattr(odml_prop, "reference"), None)
+        self.assertEqual(getattr(odml_prop, "dependency"), None)
+        self.assertEqual(getattr(odml_prop, "dependency_value"), None)
+        self.assertEqual(getattr(odml_prop, "value_origin"), None)
+
+        nix_file_r.close()
+
+    def test_nix_to_odml_empty(self):
+        file_name = 'tmp'
+        nix_path = os.path.join(self.test_dir, file_name + '.nix')
+        nix_file_w = nix.File.open(nix_path, nix.FileMode.Overwrite)
+        odml_path = os.path.join(self.test_dir, file_name + '.xml')
+
+        odml.Property(parent=self.odml_doc.sections[0])
+
+        convert.nixwrite(self.odml_doc, nix_path)
+        nix_file_w.close()
+
+        nix_file_r = nix.File.open(nix_path, nix.FileMode.ReadOnly)
+        convert.odmlwrite(nix_file_r, odml_path)
+        odml_doc = odml.load(odml_path)
+
+        self.assertEqual(len(odml_doc.sections[0].props), 1)
+
+        odml_prop = odml_doc.sections[0].props[0]
+
+        self.assertGreater(len(getattr(odml_prop, "id")), 0)
+        self.assertEqual(getattr(odml_prop, "name"), getattr(odml_prop, "id"))
+        self.assertEqual(getattr(odml_prop, "values"), [])
+        self.assertEqual(getattr(odml_prop, "dtype"), None)
+        self.assertEqual(getattr(odml_prop, "definition"), None)
+        self.assertEqual(getattr(odml_prop, "unit"), None)
+        self.assertEqual(getattr(odml_prop, "uncertainty"), None)
+        self.assertEqual(getattr(odml_prop, "reference"), None)
+        self.assertEqual(getattr(odml_prop, "dependency"), None)
+        self.assertEqual(getattr(odml_prop, "dependency_value"), None)
+        self.assertEqual(getattr(odml_prop, "value_origin"), None)
+
+        nix_file_r.close()
diff --git a/test/test_section.py b/test/test_section.py
new file mode 100644
index 0000000..5fa2c3a
--- /dev/null
+++ b/test/test_section.py
@@ -0,0 +1,132 @@
+import datetime
+import os
+import shutil
+import tempfile
+import unittest
+
+import nixio as nix
+import odml
+
+from nixodmlconverter import convert
+
+
+class TestBlock(unittest.TestCase):
+    def setUp(self):
+        self.test_dir = tempfile.mkdtemp("_odmlnix", "test_", tempfile.gettempdir())
+
+        self.odml_doc = odml.Document(author='me', date=datetime.date.today(),
+                                      version='0.0.1', repository='unknown')
+
+    def tearDown(self):
+        # cleanup temporary files and folder
+        shutil.rmtree(self.test_dir)
+
+    def test_odml_to_nix_none(self):
+        file_name = 'tmp'
+        nix_path = os.path.join(self.test_dir, file_name + '.nix')
+
+        odml.Section(name=None, oid=None, definition=None,
+                     parent=self.odml_doc, type="MustBeSet",
+                     reference=None, repository=None,
+                     link=None, include=None)
+
+        convert.nixwrite(self.odml_doc, nix_path, 'overwrite')
+        nix_file = nix.File.open(nix_path)
+
+        self.assertEqual(len(nix_file.sections[0].sections), 1)
+
+        nix_sec = nix_file.sections[0].sections[0]
+
+        self.assertGreater(len(getattr(nix_sec, "id")), 0)
+        self.assertEqual(getattr(nix_sec, "name"), getattr(nix_sec, "id"))
+        self.assertEqual(getattr(nix_sec, "type"), "MustBeSet")
+        self.assertEqual(getattr(nix_sec, "definition"), None)
+        self.assertEqual(getattr(nix_sec, "reference"), None)
+        self.assertEqual(getattr(nix_sec, "repository"), None)
+        self.assertEqual(getattr(nix_sec, "link"), None)
+        #self.assertEqual(getattr(nix_sec, "include"), None)
+
+        nix_file.close()
+
+    def test_odml_to_nix_empty(self):
+        file_name = 'tmp'
+        nix_path = os.path.join(self.test_dir, file_name + '.nix')
+
+        odml.Section(parent=self.odml_doc)
+
+        convert.nixwrite(self.odml_doc, nix_path, 'overwrite')
+        nix_file = nix.File.open(nix_path)
+
+        self.assertEqual(len(nix_file.sections[0].sections), 1)
+
+        nix_sec = nix_file.sections[0].sections[0]
+
+        self.assertGreater(len(getattr(nix_sec, "id")), 0)
+        self.assertEqual(getattr(nix_sec, "name"), getattr(nix_sec, "id"))
+        self.assertEqual(getattr(nix_sec, "type"), "n.s.")
+        self.assertEqual(getattr(nix_sec, "definition"), None)
+        self.assertEqual(getattr(nix_sec, "reference"), None)
+        self.assertEqual(getattr(nix_sec, "repository"), None)
+        self.assertEqual(getattr(nix_sec, "link"), None)
+        #self.assertEqual(getattr(nix_sec, "include"), None)
+
+        nix_file.close()
+
+    def test_nix_to_odml_none(self):
+        file_name = 'tmp'
+        nix_path = os.path.join(self.test_dir, file_name + '.nix')
+        nix_file_w = nix.File.open(nix_path, nix.FileMode.Overwrite)
+        odml_path = os.path.join(self.test_dir, file_name + '.xml')
+
+        odml.Section(name=None, oid=None, definition=None,
+                     parent=self.odml_doc, type="MustBeSet",
+                     reference=None, repository=None,
+                     link=None, include=None)
+
+        convert.nixwrite(self.odml_doc, nix_path)
+        nix_file_w.close()
+
+        nix_file_r = nix.File.open(nix_path, nix.FileMode.ReadOnly)
+        convert.odmlwrite(nix_file_r, odml_path)
+        odml_doc = odml.load(odml_path)
+        self.assertEqual(len(odml_doc.sections), 1)
+        odml_sec = odml_doc.sections[0]
+
+        self.assertGreater(len(getattr(odml_sec, "id")), 0)
+        self.assertEqual(getattr(odml_sec, "name"), getattr(odml_sec, "id"))
+        self.assertEqual(getattr(odml_sec, "type"), "MustBeSet")
+        self.assertEqual(getattr(odml_sec, "definition"), None)
+        self.assertEqual(getattr(odml_sec, "reference"), None)
+        self.assertEqual(getattr(odml_sec, "repository"), None)
+        self.assertEqual(getattr(odml_sec, "link"), None)
+        self.assertEqual(getattr(odml_sec, "include"), None)
+
+        nix_file_r.close()
+
+    def test_nix_to_odml_empty(self):
+        file_name = 'tmp'
+        nix_path = os.path.join(self.test_dir, file_name + '.nix')
+        nix_file_w = nix.File.open(nix_path, nix.FileMode.Overwrite)
+        odml_path = os.path.join(self.test_dir, file_name + '.xml')
+
+        odml.Section(parent=self.odml_doc)
+
+        convert.nixwrite(self.odml_doc, nix_path)
+        nix_file_w.close()
+
+        nix_file_r = nix.File.open(nix_path, nix.FileMode.ReadOnly)
+        convert.odmlwrite(nix_file_r, odml_path)
+        odml_doc = odml.load(odml_path)
+        self.assertEqual(len(odml_doc.sections), 1)
+        odml_sec = odml_doc.sections[0]
+
+        self.assertGreater(len(getattr(odml_sec, "id")), 0)
+        self.assertEqual(getattr(odml_sec, "name"), getattr(odml_sec, "id"))
+        self.assertEqual(getattr(odml_sec, "type"), "n.s.")
+        self.assertEqual(getattr(odml_sec, "definition"), None)
+        self.assertEqual(getattr(odml_sec, "reference"), None)
+        self.assertEqual(getattr(odml_sec, "repository"), None)
+        self.assertEqual(getattr(odml_sec, "link"), None)
+        self.assertEqual(getattr(odml_sec, "include"), None)
+
+        nix_file_r.close()