Skip to content

Commit a75d1db

Browse files
authored
Merge pull request #292 from mpsonntag/bagToSeq
[RDF] 'Bag' to 'Seq'
2 parents eb97b7f + 4e4eeb7 commit a75d1db

File tree

8 files changed

+109
-57
lines changed

8 files changed

+109
-57
lines changed

.travis.yml

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,21 @@ matrix:
1212
python: "3.4"
1313
- os: linux
1414
python: "3.5"
15+
- os: linux
16+
python: "3.6"
1517

1618
- os: osx
1719
language: generic
1820
env:
19-
- OSXENV=3.5
20-
# Keep only one osx branch active for now
21-
# since currently osx builds on travis
22-
# are frequently stalled or indefinitely delayed.
23-
# - os: osx
24-
# language: generic
25-
# env:
26-
# - OSXENV=2.7
21+
- OSXENV=3.5.0
22+
- os: osx
23+
language: generic
24+
env:
25+
- OSXENV=3.6.0
26+
- os: osx
27+
language: generic
28+
env:
29+
- OSXENV=2.7.14
2730

2831
install:
2932
- export PYVER=${TRAVIS_PYTHON_VERSION:0:1}
@@ -40,18 +43,20 @@ install:
4043
fi;
4144

4245
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
43-
if [[ "$OSXENV" == "2.7" ]]; then
44-
brew install python@2;
45-
virtualenv venv -p python;
46-
source venv/bin/activate;
47-
export PYCMD=python;
48-
export PIPCMD=pip;
49-
else
50-
brew upgrade python;
51-
source venv/bin/activate;
52-
export PYCMD=python3;
53-
export PIPCMD=pip3;
54-
fi;
46+
brew update;
47+
brew install pyenv;
48+
brew upgrade pyenv;
49+
brew install pyenv-virtualenv;
50+
eval "$(pyenv init -)";
51+
eval "$(pyenv virtualenv-init -)";
52+
pyenv install $OSXENV;
53+
pyenv virtualenv $OSXENV venv;
54+
pyenv activate venv;
55+
which python;
56+
python --version;
57+
which pip;
58+
export PYCMD=python;
59+
export PIPCMD=pip;
5560
fi;
5661

5762
- $PIPCMD install lxml enum34 pyyaml rdflib

appveyor.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ environment:
44
PYVER: "2.7"
55
- PYTHON: "C:\\Python35"
66
PYVER: "3.5"
7+
- PYTHON: "C:\\Python36"
8+
PYVER: "3.6"
79
- PYTHON: "C:\\Python27-x64"
810
PYVER: "2.7"
911
- PYTHON: "C:\\Python35-x64"
1012
PYVER: "3.5"
13+
- PYTHON: "C:\\Python36-x64"
14+
PYVER: "3.6"
1115

1216
build: false
1317

doc/odml_ontology/root-ontology.ttl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ xsd:date rdf:type rdfs:Datatype ;
5656
### https://g-node.org/projects/odml-rdf#hasValue
5757
:hasValue rdf:type owl:ObjectProperty ;
5858
rdfs:domain :Property ;
59-
rdfs:range rdf:Bag ;
59+
rdfs:range rdf:Seq ;
6060
rdfs:label "hasValue"^^xsd:string .
6161

6262

@@ -94,7 +94,7 @@ xsd:date rdf:type rdfs:Datatype ;
9494

9595
### https://g-node.org/projects/odml-rdf#isValueOf
9696
:isValueOf rdf:type owl:ObjectProperty ;
97-
rdfs:domain rdf:Bag ;
97+
rdfs:domain rdf:Seq ;
9898
rdfs:range :Property ;
9999
rdfs:label "isValueOf"^^xsd:string .
100100

@@ -211,15 +211,15 @@ xsd:date rdf:type rdfs:Datatype ;
211211
# Classes
212212
#################################################################
213213

214-
### http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag
215-
rdf:Bag rdf:type owl:Class ;
214+
### http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq
215+
rdf:Seq rdf:type owl:Class ;
216216
rdfs:subClassOf [ rdf:type owl:Restriction ;
217217
owl:onProperty :isValueOf ;
218218
owl:someValuesFrom :Property
219219
] ;
220-
rdfs:comment "The class of unordered containers." ;
220+
rdfs:comment "The class of ordered containers." ;
221221
rdfs:isDefinedBy rdf: ;
222-
rdfs:label "Bag" .
222+
rdfs:label "Seq" .
223223

224224

225225
### https://g-node.org/projects/odml-rdf#Cell
@@ -346,7 +346,7 @@ rdf:Bag rdf:type owl:Class ;
346346
rdfs:subClassOf owl:Thing ,
347347
[ rdf:type owl:Restriction ;
348348
owl:onProperty :hasValue ;
349-
owl:someValuesFrom rdf:Bag
349+
owl:someValuesFrom rdf:Seq
350350
] ,
351351
[ rdf:type owl:Restriction ;
352352
owl:onProperty :isPropertyOf ;

odml/tools/rdf_converter.py

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from io import StringIO
66
from os.path import dirname, abspath
77
from rdflib import Graph, Literal, URIRef
8+
from rdflib.graph import Seq
89
from rdflib.namespace import XSD, RDF
910

1011
import odml
@@ -123,11 +124,27 @@ def save_element(self, e, node=None):
123124
elif isinstance(fmt, Property.__class__) and \
124125
k == 'value' and len(getattr(e, k)) > 0:
125126
values = getattr(e, k)
126-
bag = URIRef(odmlns + str(uuid.uuid4()))
127-
self.g.add((bag, RDF.type, RDF.Bag))
128-
self.g.add((curr_node, fmt.rdf_map(k), bag))
127+
seq = URIRef(odmlns + str(uuid.uuid4()))
128+
self.g.add((seq, RDF.type, RDF.Seq))
129+
self.g.add((curr_node, fmt.rdf_map(k), seq))
130+
# rdflib so far does not respect RDF:li item order
131+
# in RDF:Seq on loading so we have to use custom
132+
# numbered Node elements for now. Once rdflib upgrades
133+
# this should be reversed to RDF:li again!
134+
# see https://github.com/RDFLib/rdflib/issues/280
135+
# -- keep until supported
136+
# bag = URIRef(odmlns + str(uuid.uuid4()))
137+
# self.g.add((bag, RDF.type, RDF.Bag))
138+
# self.g.add((curr_node, fmt.rdf_map(k), bag))
139+
# for v in values:
140+
# self.g.add((bag, RDF.li, Literal(v)))
141+
142+
counter = 1
129143
for v in values:
130-
self.g.add((bag, RDF.li, Literal(v)))
144+
pred = "%s_%s" % (str(RDF), counter)
145+
self.g.add((seq, URIRef(pred), Literal(v)))
146+
counter = counter + 1
147+
131148
# adding entities' properties
132149
else:
133150
val = getattr(e, k)
@@ -258,9 +275,20 @@ def parse_property(self, prop_uri):
258275
elems = list(self.g.objects(subject=prop_uri, predicate=attr[1]))
259276
if attr[0] == "value" and len(elems) > 0:
260277
prop_attrs[attr[0]] = []
278+
279+
# rdflib does not respect order with RDF.li items yet, see comment above
280+
# support both RDF.li and rdf:_nnn for now.
281+
# Remove rdf:_nnn once rdflib respects RDF.li order in an RDF.Seq obj.
261282
values = list(self.g.objects(subject=elems[0], predicate=RDF.li))
262-
for v in values:
263-
prop_attrs[attr[0]].append(v.toPython())
283+
if len(values) > 0:
284+
for v in values:
285+
prop_attrs[attr[0]].append(v.toPython())
286+
else:
287+
# rdf:__nnn part
288+
valseq = Seq(graph=self.g, subject=elems[0])
289+
for seqitem in valseq:
290+
prop_attrs[attr[0]].append(seqitem.toPython())
291+
264292
elif attr[0] == "id":
265293
prop_attrs[attr[0]] = prop_uri.split("#", 1)[1]
266294
else:

test/resources/version_conversion.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ Document:
1111
properties:
1212
- name: prop_name
1313
values:
14-
- dtype: !!python/object/apply:odml.dtypes.DType
14+
- dtype:
1515
- string
1616
value: '[''one'', ''two'']'
17-
- dtype: !!python/object/apply:odml.dtypes.DType
17+
- dtype:
1818
- int
1919
value: '1'
2020
odml-version: '1'

test/resources/version_conversion_int.yaml

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,23 @@ Document:
1414
values:
1515
- dtype: string
1616
- definition: def val 1
17-
dtype: !!python/object/apply:odml.dtypes.DType
17+
dtype:
1818
- string
1919
filename: filename val 1
2020
reference: ref val 1
2121
uncertainty: 11
2222
unit: arbitrary
2323
value: '1'
2424
- definition: def val 2
25-
dtype: !!python/object/apply:odml.dtypes.DType
25+
dtype:
2626
- int
2727
filename: filename val 2
2828
reference: ref val 2
2929
uncertainty: 12
3030
unit: arbitrary 2
3131
value: '2'
3232
- definition: def val 3
33-
dtype: !!python/object/apply:odml.dtypes.DType
33+
dtype:
3434
- string
3535
filename: filename val 3
3636
reference: ref val 3
@@ -44,63 +44,63 @@ Document:
4444
values:
4545
- dtype: string
4646
- definition: def val 1
47-
dtype: !!python/object/apply:odml.dtypes.DType
47+
dtype:
4848
- int
4949
filename: filename val 1
5050
reference: ref val 1
5151
uncertainty: 12
5252
unit: arbitrary
5353
value: '1'
5454
- definition: def val 1
55-
dtype: !!python/object/apply:odml.dtypes.DType
55+
dtype:
5656
- int
5757
filename: filename val 1
5858
reference: ref val 1
5959
uncertainty: 12
6060
unit: arbitrary
6161
value: '2'
6262
- definition: def val 1
63-
dtype: !!python/object/apply:odml.dtypes.DType
63+
dtype:
6464
- int
6565
filename: filename val 1
6666
reference: ref val 1
6767
uncertainty: 12
6868
unit: arbitrary
6969
value: '3'
7070
- definition: def val 1
71-
dtype: !!python/object/apply:odml.dtypes.DType
71+
dtype:
7272
- int
7373
filename: filename val 1
7474
reference: ref val 1
7575
uncertainty: 12
7676
unit: arbitrary
7777
value: '4'
7878
- definition: def val 1
79-
dtype: !!python/object/apply:odml.dtypes.DType
79+
dtype:
8080
- int
8181
filename: filename val 1
8282
reference: ref val 1
8383
uncertainty: 12
8484
unit: arbitrary
8585
value: '4'
8686
- definition: def val 1
87-
dtype: !!python/object/apply:odml.dtypes.DType
87+
dtype:
8888
- int
8989
filename: filename val 1
9090
reference: ref val 1
9191
uncertainty: 12
9292
unit: arbitrary
9393
value: '4'
9494
- definition: def val 1
95-
dtype: !!python/object/apply:odml.dtypes.DType
95+
dtype:
9696
- int
9797
filename: filename val 1
9898
reference: ref val 1
9999
uncertainty: 12
100100
unit: arbitrary
101101
value: '4'
102102
- definition: def val 1
103-
dtype: !!python/object/apply:odml.dtypes.DType
103+
dtype:
104104
- int
105105
filename: filename val 1
106106
reference: ref val 1
@@ -132,31 +132,31 @@ Document:
132132
values:
133133
- dtype: string
134134
- definition: def val 1
135-
dtype: !!python/object/apply:odml.dtypes.DType
135+
dtype:
136136
- int
137137
filename: filename val 1
138138
reference: ref val 1
139139
uncertainty: 12
140140
unit: arbitrary
141141
value: '4'
142142
- definition: def val 1
143-
dtype: !!python/object/apply:odml.dtypes.DType
143+
dtype:
144144
- int
145145
filename: filename val 1
146146
reference: ref val 1
147147
uncertainty: 12
148148
unit: arbitrary
149149
value: '4'
150150
- definition: def val 1
151-
dtype: !!python/object/apply:odml.dtypes.DType
151+
dtype:
152152
- int
153153
filename: filename val 1
154154
reference: ref val 1
155155
uncertainty: 12
156156
unit: arbitrary
157157
value: '4'
158158
- definition: def val 1
159-
dtype: !!python/object/apply:odml.dtypes.DType
159+
dtype:
160160
- int
161161
filename: filename val 1
162162
reference: ref val 1

test/test_parser_odml.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,11 @@ def test_rdf_file(self):
8585
self.rdf_writer.write_file(self.odml_doc, self.rdf_file)
8686
rdf_doc = self.rdf_reader.from_file(self.rdf_file, "turtle")
8787

88-
# RDF does not preserve the order of sections,
89-
# need to check the attributes by hand.
88+
self.assertEqual(self.odml_doc, rdf_doc[0])
89+
90+
# RDF does not preserve the order of sections or properties,
91+
# check the attributes by hand to make sure everything
92+
# was correctly imported.
9093
self.assertEqual(len(rdf_doc), 1)
9194
self.assertEqual(rdf_doc[0].author, self.odml_doc.author)
9295
self.assertEqual(rdf_doc[0].version, self.odml_doc.version)

test/test_rdf_writer.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ def test_adding_values(self):
9090
w = RDFWriter([doc])
9191
w.convert_to_rdf()
9292
self.assertEqual(len(list(w.g.subject_objects(predicate=RDF.li))), 0)
93+
self.assertEqual(len(list(
94+
w.g.subject_objects(predicate=URIRef("%s_1" % str(RDF))))), 0)
9395

9496
doc = parse("""
9597
s1[t1]
@@ -98,14 +100,22 @@ def test_adding_values(self):
98100

99101
w = RDFWriter([doc])
100102
w.convert_to_rdf()
101-
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li, object=Literal("val")))), 1)
103+
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li,
104+
object=Literal("val")))), 0)
105+
self.assertEqual(len(list(w.g.subjects(predicate=URIRef("%s_1" % str(RDF)),
106+
object=Literal("val")))), 1)
102107

103108
doc.sections[0].properties[0].append("val2")
104109
w = RDFWriter([doc])
105110
w.convert_to_rdf()
106-
self.assertEqual(len(list(w.g.subject_objects(predicate=RDF.li))), 2)
107-
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li, object=Literal("val")))), 1)
108-
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li, object=Literal("val2")))), 1)
111+
self.assertEqual(len(list(w.g.subject_objects(predicate=RDF.li))), 0)
112+
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li, object=Literal("val")))), 0)
113+
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li, object=Literal("val2")))), 0)
114+
115+
self.assertEqual(len(list(w.g.subjects(predicate=URIRef("%s_1" % str(RDF)),
116+
object=Literal("val")))), 1)
117+
self.assertEqual(len(list(w.g.subjects(predicate=URIRef("%s_2" % str(RDF)),
118+
object=Literal("val2")))), 1)
109119

110120
doc = parse("""
111121
s1[t1]
@@ -117,7 +127,9 @@ def test_adding_values(self):
117127

118128
w = RDFWriter([doc])
119129
w.convert_to_rdf()
120-
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li, object=Literal("val")))), 3)
130+
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li, object=Literal("val")))), 0)
131+
self.assertEqual(len(list(w.g.subjects(predicate=URIRef("%s_1" % str(RDF)),
132+
object=Literal("val")))), 3)
121133

122134
def test_section_subclass(self):
123135
p = os.path.join(dirname(dirname(abspath(__file__))), 'doc', 'section_subclasses.yaml')

0 commit comments

Comments
 (0)