diff --git a/odml/property.py b/odml/property.py
index a120ab3..8801325 100644
--- a/odml/property.py
+++ b/odml/property.py
@@ -328,8 +328,13 @@ class BaseProperty(base.BaseObject):
             self._dtype = dtypes.infer_dtype(new_value[0])
 
         if not self._validate_values(new_value):
-            raise ValueError("odml.Property.values: passed values are not of "
-                             "consistent type!")
+            if self._dtype in ("date", "time", "datetime"):
+                raise ValueError("odml.Property.values: passed values are not of "
+                                "consistent type \'%s\'! Format should be \'%s\'." %
+                                 (self._dtype, dtypes.default_values(self._dtype)))
+            else:
+                raise ValueError("odml.Property.values: passed values are not of "
+                                "consistent type!")
         self._values = [dtypes.get(v, self.dtype) for v in new_value]
 
     @property
@@ -662,3 +667,27 @@ class BaseProperty(base.BaseObject):
         else:
             print(("{}{} {}: {}".format(property_spaces, prefix, self.name,
                                         value_string)))
+
+    def export_leaf(self):
+        """
+        Export only the path from this property to the root.
+        Include all properties of parent sections.
+        """
+        curr = self.parent
+        par = self.parent
+        child = self.parent
+
+        while curr is not None:
+            par = curr.clone(children=False, keep_id=True)
+            if curr != self.parent:
+                par.append(child)
+            if hasattr(curr, 'properties'):
+                if curr == self.parent:
+                    par.append(self.clone(keep_id=True))
+                else:
+                    for prop in curr.properties:
+                        par.append(prop.clone(keep_id=True))
+            child = par
+            curr = curr.parent
+
+        return par
diff --git a/odml/section.py b/odml/section.py
index f27c724..c195f4b 100644
--- a/odml/section.py
+++ b/odml/section.py
@@ -638,3 +638,24 @@ class BaseSection(base.Sectionable):
                 print("{} {} [{}]\n{}[...]".format(child_sec_indent,
                                                    s.name, s.type,
                                                    more_indent))
+
+    def export_leaf(self):
+        """
+        Export only the path from this section to the root.
+        Include all properties for all sections, but no other subsections.
+        """
+        curr = self
+        par = self
+        child = self
+
+        while curr is not None:
+            par = curr.clone(children=False, keep_id=True)
+            if curr != self:
+                par.append(child)
+            if hasattr(curr, 'properties'):
+                for prop in curr.properties:
+                    par.append(prop.clone(keep_id=True))
+            child = par
+            curr = curr.parent
+
+        return par

Leaf export feature
During a workshop a feature request came up: leaf export.

When working with a large, deeply nested odml file, that documents a whole experiment, it might be interesting to export only the path from a single leaf in an odml tree all the way to the root and hand this reduced odml file to a collaborator.
diff --git a/test/test_property.py b/test/test_property.py
index 80f6c1c..95048f1 100644
--- a/test/test_property.py
+++ b/test/test_property.py
@@ -1,5 +1,7 @@
 import unittest
 
+import datetime
+
 from odml import Property, Section, Document, DType
 from odml.property import BaseProperty
 from odml.section import BaseSection
@@ -115,6 +117,19 @@ class TestProperty(unittest.TestCase):
         self.assertEqual(p5.value, [0])
         self.assertEqual(p5.values, [0])
 
+        with self.assertRaises(ValueError):
+            Property(name="dateprop", dtype=DType.date, value=['20190707'])
+
+        with self.assertRaises(ValueError):
+            Property(name="timeprop", dtype=DType.time, value=['11.11.11'])
+
+        with self.assertRaises(ValueError):
+            Property(name="datetimeprop", dtype=DType.datetime, value=['20190707'])
+
+        with self.assertRaises(ValueError):
+            Property(name="intprop", dtype=DType.int, value=[2, "Hello!", 4])
+
+
     def test_value_append(self):
         # Test append w/o Property value or dtype
         prop = Property(name="append")
@@ -733,6 +748,42 @@ class TestProperty(unittest.TestCase):
         prop_b.name = 'newPropertyName'
         self.assertNotEqual(prop_a, prop_b)
 
+    def test_export_leaf(self):
+        doc = Document()
+        first = doc.create_section("first")
+        second = first.create_section("second")
+        first.create_section("third")
+
+        name = "prop1"
+        values = [1.3]
+        first.create_property(name, value=values)
+
+        name = "prop2"
+        values = ["words"]
+        second.create_property(name, value=values)
+
+        name = "prop3"
+        values = ["a", "b"]
+        second.create_property(name, value=values)
+
+        name = "prop4"
+        values = [3]
+        second.create_property(name, value=values)
+
+        name = "prop5"
+        values = ["abc"]
+        first.create_property(name, value=values)
+
+        ex1 = first.properties["prop1"].export_leaf()
+        self.assertEqual(len(ex1['first'].properties), 1)
+        self.assertEqual(len(ex1['first'].sections), 0)
+
+        ex2 = second.properties["prop2"].export_leaf()
+        self.assertEqual(len(ex2.sections), 1)
+        self.assertEqual(len(ex2['first'].properties), 2)
+        self.assertEqual(len(ex2['first'].sections), 1)
+        self.assertEqual(len(ex2['first']['second'].properties), 1)
+
 
 if __name__ == "__main__":
     print("TestProperty")
diff --git a/test/test_section.py b/test/test_section.py
index ba4e374..ae99019 100644
--- a/test/test_section.py
+++ b/test/test_section.py
@@ -943,6 +943,41 @@ class TestSection(unittest.TestCase):
         prop = root.create_property(name, dtype=dtype)
         self.assertIsNone(prop.dtype)
 
+    def test_export_leaf(self):
+        doc = Document()
+        first = doc.create_section("first")
+        second = first.create_section("second")
+        third = first.create_section("third")
+
+        name = "prop1"
+        values = [1.3]
+        first.create_property(name, value=values)
+
+        name = "prop2"
+        values = ["words"]
+        first.create_property(name, value=values)
+
+        name = "prop3"
+        values = ["a", "b"]
+        second.create_property(name, value=values)
+
+        ex1 = first.export_leaf()
+        self.assertEqual(len(ex1.sections), 1)
+        self.assertEqual(len(ex1['first'].properties), 2)
+        self.assertEqual(len(ex1['first'].sections), 0)
+
+        ex2 = second.export_leaf()
+        self.assertEqual(len(ex2.sections), 1)
+        self.assertEqual(len(ex2['first'].properties), 2)
+        self.assertEqual(len(ex2['first'].sections), 1)
+        self.assertEqual(len(ex2['first']['second'].properties), 1)
+
+        ex3 = third.export_leaf()
+        self.assertEqual(len(ex3.sections), 1)
+        self.assertEqual(len(ex3['first'].properties), 2)
+        self.assertEqual(len(ex3['first'].sections), 1)
+        self.assertEqual(len(ex3['first']['third']), 0)
+
     def test_link(self):
         pass
 

pip install -e .
parse_log_pytest
pytest
pytest
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///croot/attrs_1668696182826/work
certifi @ file:///croot/certifi_1671487769961/work/certifi
docopt==0.6.2
flit_core @ file:///opt/conda/conda-bld/flit-core_1644941570762/work/source/flit_core
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1648562407465/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
isodate==0.6.1
lxml==5.3.1
-e git+https://github.com/G-Node/python-odml.git@3ebada59ce95a5fbc54da08a47322f0d5857a607#egg=odML
packaging @ file:///croot/packaging_1671697413597/work
pathlib==1.0.1
pluggy @ file:///tmp/build/80754af9/pluggy_1648042572264/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pyparsing==3.1.4
pytest==7.1.2
PyYAML==4.2b4
rdflib==6.3.2
six==1.17.0
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
typing_extensions @ file:///croot/typing_extensions_1669924550328/work
zipp @ file:///croot/zipp_1672387121353/work

name: python-odml
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=22.1.0=py37h06a4308_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - flit-core=3.6.0=pyhd3eb1b0_0
  - importlib-metadata=4.11.3=py37h06a4308_0
  - importlib_metadata=4.11.3=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=22.0=py37h06a4308_0
  - pip=22.3.1=py37h06a4308_0
  - pluggy=1.0.0=py37h06a4308_1
  - py=1.11.0=pyhd3eb1b0_0
  - pytest=7.1.2=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py37h06a4308_0
  - typing_extensions=4.4.0=py37h06a4308_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.11.0=py37h06a4308_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - docopt==0.6.2
      - isodate==0.6.1
      - lxml==5.3.1
      - pathlib==1.0.1
      - pyparsing==3.1.4
      - pyyaml==4.2b4
      - rdflib==6.3.2
      - six==1.17.0
prefix: /opt/conda/envs/python-odml

test/test_property.py::TestProperty::test_export_leaf test/test_section.py::TestSection::test_export_leaf
test/test_property.py::TestProperty::test_bool_conversion test/test_property.py::TestProperty::test_clone test/test_property.py::TestProperty::test_comparison test/test_property.py::TestProperty::test_dtype test/test_property.py::TestProperty::test_get_merged_equivalent test/test_property.py::TestProperty::test_get_path test/test_property.py::TestProperty::test_get_set_value test/test_property.py::TestProperty::test_id test/test_property.py::TestProperty::test_merge test/test_property.py::TestProperty::test_merge_check test/test_property.py::TestProperty::test_name test/test_property.py::TestProperty::test_new_id test/test_property.py::TestProperty::test_parent test/test_property.py::TestProperty::test_simple_attributes test/test_property.py::TestProperty::test_str_to_int_convert test/test_property.py::TestProperty::test_value test/test_property.py::TestProperty::test_value_append test/test_property.py::TestProperty::test_value_extend test/test_section.py::TestSection::test_append test/test_section.py::TestSection::test_children test/test_section.py::TestSection::test_clone test/test_section.py::TestSection::test_clone_keep_id test/test_section.py::TestSection::test_comparison test/test_section.py::TestSection::test_contains test/test_section.py::TestSection::test_create_property test/test_section.py::TestSection::test_create_section test/test_section.py::TestSection::test_extend test/test_section.py::TestSection::test_id test/test_section.py::TestSection::test_include test/test_section.py::TestSection::test_insert test/test_section.py::TestSection::test_link test/test_section.py::TestSection::test_merge test/test_section.py::TestSection::test_merge_check test/test_section.py::TestSection::test_name test/test_section.py::TestSection::test_new_id test/test_section.py::TestSection::test_parent test/test_section.py::TestSection::test_path test/test_section.py::TestSection::test_remove test/test_section.py::TestSection::test_reorder test/test_section.py::TestSection::test_repository test/test_section.py::TestSection::test_simple_attributes test/test_section.py::TestSection::test_unmerge
odml/section.py odml/property.py
odml/section.py odml/property.py