Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions odml/doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,21 @@ def get_terminology_equivalent(self):
return None
term = terminology.load(self.repository)
return term
def pprint(self, indent=2, max_depth=1, max_length=80, current_depth=0):
"""
Pretty print method to visualize Document-Section trees.

:param indent: number of leading spaces for every child Section or Property.
:param max_depth: maximum number of hierarchical levels printed from the
starting Section.
:param max_length: maximum number of characters printed in one line.
:param current_depth: number of hierarchical levels printed from the
starting Section.
"""
doc_str = "[{} [{}] {}, sections: {}, repository: {}]".format(self.author, self.version,
self.date, len(self._sections), self.repository)
print(doc_str)

for s in self._sections:
s.pprint(current_depth=current_depth+1, max_depth=max_depth,
indent=indent, max_length=max_length)
2 changes: 2 additions & 0 deletions odml/dtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ def default_values(dtype):

_dtype_map = {'str': 'string', 'bool': 'boolean'}

special_dtypes = ["url", "person", "text"]


def infer_dtype(value):
dtype = (type(value)).__name__
Expand Down
14 changes: 9 additions & 5 deletions odml/property.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def __init__(self, name=None, values=None, parent=None, unit=None,

self._values = []
self.values = values
if not values and (value or isinstance(value, bool)):
if not values and (value or isinstance(value, bool) or isinstance(value, int)):
self.values = value

self.parent = parent
Expand Down Expand Up @@ -588,8 +588,10 @@ def extend(self, obj, strict=True):

new_value = self._convert_value_input(obj)
if len(new_value) > 0 and strict and dtypes.infer_dtype(new_value[0]) != self.dtype:
raise ValueError("odml.Property.extend: "
"passed value data type does not match dtype!")

if not (dtypes.infer_dtype(new_value[0]) == "string" and self.dtype in dtypes.special_dtypes):
raise ValueError("odml.Property.extend: passed value data type found (\"%s\") "
"does not match expected dtype \"%s\"!" % (dtypes.infer_dtype(new_value[0]), self._dtype))

if not self._validate_values(new_value):
raise ValueError("odml.Property.extend: passed value(s) cannot be converted "
Expand Down Expand Up @@ -618,8 +620,10 @@ def append(self, obj, strict=True):
raise ValueError("odml.property.append: Use extend to add a list of values!")

if len(new_value) > 0 and strict and dtypes.infer_dtype(new_value[0]) != self.dtype:
raise ValueError("odml.Property.append: "
"passed value data type does not match dtype!")

if not (dtypes.infer_dtype(new_value[0]) == "string" and self.dtype in dtypes.special_dtypes):
raise ValueError("odml.Property.append: passed value data type found (\"%s\") "
"does not match expected dtype \"%s\"!" % (dtypes.infer_dtype(new_value[0]), self._dtype))

if not self._validate_values(new_value):
raise ValueError("odml.Property.append: passed value(s) cannot be converted "
Expand Down
39 changes: 39 additions & 0 deletions odml/tools/version_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
from ..info import FORMAT_VERSION
from ..terminology import Terminologies, REPOSITORY_BASE

import uuid

try:
unicode = unicode
except NameError:
Expand Down Expand Up @@ -194,6 +196,8 @@ def _convert(self, tree):
if e.tag == "repository":
self._handle_repository(e)

tree = self._check_add_ids(tree)

return tree

def _handle_include(self, element):
Expand Down Expand Up @@ -410,6 +414,41 @@ def _change_entity_name(tree, elem_map, name):
elem_map[named_path] += 1
name.text += "-" + str(elem_map[named_path])

def _check_add_ids(self, tree):
"""
Checks, whether elements (properties) possess an UUID
and adds one in case of absence.
:param tree: ElementTree of the doc
:return: ElementTree
"""
root = tree.getroot()
self._add_id(root)
for sec in root.iter("section"):
self._add_id(sec)
for prop in sec.iter("property"):
self._add_id(prop)

return tree

@staticmethod
def _add_id(element):
"""
Checks, whether an element possesses an ID. If yes, make sure it has
the right format. Otherwise a new UUID is created.
:param element: lxml element.
"""
oid = element.find("id")
new_id = ET.Element("id")
new_id.text = str(uuid.uuid4())
if oid is not None:
try:
if oid.text is not None:
new_id.text = str(uuid.UUID(oid.text))
except ValueError as e:
print(e)
element.remove(oid)
element.append(new_id)

def _log(self, msg):
"""
Adds the passed message to the conversion_log attribute and
Expand Down
54 changes: 54 additions & 0 deletions test/test_property.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,18 @@ def test_value(self):
with self.assertRaises(ValueError):
_ = Property(name="Public-Key", value='(5689; 1254; 687)', dtype='2-tuple')

p3 = Property('myprop', value=0, dtype=DType.int)
self.assertEqual(p3.value, [0])
self.assertEqual(p3.values, [0])

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should also test the boolean case

p4 = Property('myprop', value=0, dtype=DType.boolean)
self.assertEqual(p4.value, [False])
self.assertEqual(p4.values, [False])

p5 = Property('myprop', value=0)
self.assertEqual(p5.value, [0])
self.assertEqual(p5.values, [0])

def test_value_append(self):
# Test append w/o Property value or dtype
prop = Property(name="append")
Expand Down Expand Up @@ -183,6 +195,27 @@ def test_value_append(self):
self.assertEqual(len(p5), 2)
self.assertRaises(ValueError, p5.append, "[a, b, c]")

p6 = Property(name="prop", value=["A Abraham", "B Barnes", "C Clark"], dtype=DType.person)
p6.append("D Dickins")
self.assertEqual(len(p6), 4)
self.assertRaises(ValueError, p6.append, 1)
self.assertRaises(ValueError, p6.append, 1.3)
self.assertRaises(ValueError, p6.append, True)

p7 = Property(name="prop", value=["https://en.wikipedia.org/wiki/Earth"], dtype=DType.url)
p7.append("https://en.wikipedia.org/wiki/Mars")
self.assertEqual(len(p7), 2)
self.assertRaises(ValueError, p7.append, 1)
self.assertRaises(ValueError, p7.append, 1.3)
self.assertRaises(ValueError, p7.append, True)

p8 = Property(name="prop", value=["Earth is No. 3."], dtype=DType.text)
p8.append("Mars is No. 4.")
self.assertEqual(len(p8), 2)
self.assertRaises(ValueError, p8.append, 1)
self.assertRaises(ValueError, p8.append, 1.3)
self.assertRaises(ValueError, p8.append, True)

def test_value_extend(self):
prop = Property(name="extend")

Expand Down Expand Up @@ -260,6 +293,27 @@ def test_value_extend(self):
with self.assertRaises(ValueError):
prop.extend([6, "some text"])

p1 = Property(name="prop", value=["A Abraham", "B Barnes", "C Clark"], dtype=DType.person)
p1.extend("D Dickins")
self.assertEqual(len(p1), 4)
self.assertRaises(ValueError, p1.extend, 1)
self.assertRaises(ValueError, p1.extend, 1.3)
self.assertRaises(ValueError, p1.extend, True)

p2 = Property(name="prop", value=["https://en.wikipedia.org/wiki/Earth"], dtype=DType.url)
p2.extend("https://en.wikipedia.org/wiki/Mars")
self.assertEqual(len(p2), 2)
self.assertRaises(ValueError, p2.append, 1)
self.assertRaises(ValueError, p2.append, 1.3)
self.assertRaises(ValueError, p2.append, True)

p3 = Property(name="prop", value=["Earth is No. 3."], dtype=DType.text)
p3.extend("Mars is No. 4.")
self.assertEqual(len(p3), 2)
self.assertRaises(ValueError, p3.append, 1)
self.assertRaises(ValueError, p3.append, 1.3)
self.assertRaises(ValueError, p3.append, True)

def test_get_set_value(self):
values = [1, 2, 3, 4, 5]
p = Property("property", value=values)
Expand Down
Loading