Skip to content
Closed
27 changes: 19 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,34 @@ before_install:

install:
- export PYVER=${TRAVIS_PYTHON_VERSION:0:1}
- if [ $PYVER = 3 ]; then
export PYCMD=python3;
export PIPCMD=pip3;
else
export PYCMD=python;
export PIPCMD=pip;
fi;

- if [ $COVERALLS = 1 ]; then
pip install --upgrade coveralls;
$PIPCMD install --upgrade coveralls;
fi;

- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
which python;
which $PYCMD;
source venv/bin/activate;
which python;
fi
- pip install lxml enum34 pyyaml rdflib
brew upgrade python;
which $PYCMD;
fi;

- $PIPCMD install lxml enum34 pyyaml rdflib

script:
- which python
- python setup.py build
- which $PYCMD
- $PYCMD setup.py build
- if [ $COVERALLS = 1 ]; then
coverage${PYVER} run --source=odml setup.py test && coverage${PYVER} report -m;
else
python setup.py test;
$PYCMD setup.py test;
fi;

after_success:
Expand Down
46 changes: 37 additions & 9 deletions odml/property.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def _validate_parent(new_parent):

@property
def value(self):
return self._value
return tuple(self._value)

def value_str(self, index=0):
"""
Expand All @@ -172,18 +172,32 @@ def _validate_values(self, values):
return False
return True

@value.setter
def value(self, new_value):
# Make sure boolean value 'False' gets through as well...
if new_value is None or new_value == "":
return
def _convert_value_input(self, new_value):
"""
This method ensures, that the passed new value is a list.
If new_value is a string, it will convert it to a list of
strings if the new_value contains embracing brackets.

returns list of new_value
"""
if isinstance(new_value, str):
if new_value[0] == "[" and new_value[-1] == "]":
new_value = new_value[1:-1].split(",")
if not isinstance(new_value, list):
new_value = [new_value]
return new_value

@value.setter
def value(self, new_value):
# Make sure boolean value 'False' gets through as well...
if new_value is None or new_value == "":
return

new_value = self._convert_value_input(new_value)

if self._dtype is None:
self._dtype = dtypes.infer_dtype(new_value[0])

if not self._validate_values(new_value):
raise ValueError("odml.Property.value: passed values are not of "
"consistent type!")
Expand Down Expand Up @@ -267,14 +281,14 @@ def clone(self):
"""
obj = super(BaseProperty, self).clone()
obj._section = None
obj.value = self.value
obj.value = self._value
return obj

def merge(self, property):
"""
Stub that doesn't do anything for this class
Merges the values in 'property' into self, if possible.
"""
pass
self.append(list(property.value))

def unmerge(self, property):
"""
Expand Down Expand Up @@ -308,3 +322,17 @@ def __len__(self):

def __getitem__(self, key):
return self._value[key]

def append(self, obj):
if isinstance(obj, BaseProperty):
self.merge(obj)
return
if self._value == []:
self.value = obj
else:
new_value = self._convert_value_input(obj)
if not self._validate_values(new_value):
raise ValueError("odml.Property.append: 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])

7 changes: 4 additions & 3 deletions odml/tools/dict_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,9 @@ def get_properties(props_list):

if hasattr(prop, attr):
tag = getattr(prop, attr)

if (tag == []) or tag: # Even if 'value' is empty, allow '[]'
if isinstance(tag, tuple):
prop_dict[attr] = list(tag)
elif (tag == []) or tag: # Even if 'value' is empty, allow '[]'
prop_dict[attr] = tag

props_seq.append(prop_dict)
Expand Down Expand Up @@ -187,7 +188,7 @@ def parse_properties(self, props_list):
prop_attrs[attr] = _property[attr]

prop = odmlfmt.Property.create(**prop_attrs)
prop._value = values
prop.value = values
odml_props.append(prop)

return odml_props
2 changes: 1 addition & 1 deletion odml/tools/dumper.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def get_props(obj, props):
if hasattr(obj, p):
x = getattr(obj, p)
if x is not None:
if isinstance(x, list):
if isinstance(x, list) or isinstance(x, tuple):
out.append("%s=%s" % (p, to_csv(x)))
else:
out.append("%s=%s" % (p, repr(x)))
Expand Down
23 changes: 18 additions & 5 deletions test/test_property.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ def setUp(self):
def test_value(self):
p = Property("property", 100)
self.assertEqual(p.value[0], 100)
self.assertEqual(type(p.value), tuple)

p.append(10)
self.assertEqual(len(p.value), 2)
p.append([20, 30, '40'])
self.assertEqual(len(p.value), 5)
with self.assertRaises(ValueError):
p.append('invalid')
p.append(('5', 6, 7))

p2 = Property("property 2", 3)
p.append(p2)
self.assertEqual(len(p.value), 6)

def test_bool_conversion(self):

Expand All @@ -21,13 +34,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.value == (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.value == (False, True, True, False, True, False, True))

# Failure tests
curr_val = [3, 0, 1, 0, 8]
Expand All @@ -37,7 +50,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.value == tuple(curr_val))

curr_type = 'string'
q = Property(name='sent', value=['False', True, 'TRUE', '0', 't', '12', 'Ft'])
Expand All @@ -53,7 +66,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.value == (3, 0, 1, 0, 8))

# Failure Test
p = Property(name='dogs_onboard', value=['7', '20', '1 Dog', 'Seven'])
Expand All @@ -63,7 +76,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.value == ('7', '20', '1 Dog', 'Seven'))

def test_name(self):
pass
Expand Down
2 changes: 1 addition & 1 deletion test/test_rdf_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def test_adding_values(self):
w.convert_to_rdf()
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li, object=Literal("val")))), 1)

doc.sections[0].properties[0].value.append("val2")
doc.sections[0].properties[0].append("val2")
w = RDFWriter([doc])
w.convert_to_rdf()
self.assertEqual(len(list(w.g.subject_objects(predicate=RDF.li))), 2)
Expand Down