Skip to content

Commit

Permalink
Merge pull request #292 from mpsonntag/bagToSeq
Browse files Browse the repository at this point in the history
[RDF] 'Bag' to 'Seq'
  • Loading branch information
jgrewe authored Jul 4, 2018
2 parents eb97b7f + 4e4eeb7 commit a75d1db
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 57 deletions.
45 changes: 25 additions & 20 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,21 @@ matrix:
python: "3.4"
- os: linux
python: "3.5"
- os: linux
python: "3.6"

- os: osx
language: generic
env:
- OSXENV=3.5
# Keep only one osx branch active for now
# since currently osx builds on travis
# are frequently stalled or indefinitely delayed.
# - os: osx
# language: generic
# env:
# - OSXENV=2.7
- OSXENV=3.5.0
- os: osx
language: generic
env:
- OSXENV=3.6.0
- os: osx
language: generic
env:
- OSXENV=2.7.14

install:
- export PYVER=${TRAVIS_PYTHON_VERSION:0:1}
Expand All @@ -40,18 +43,20 @@ install:
fi;

- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
if [[ "$OSXENV" == "2.7" ]]; then
brew install python@2;
virtualenv venv -p python;
source venv/bin/activate;
export PYCMD=python;
export PIPCMD=pip;
else
brew upgrade python;
source venv/bin/activate;
export PYCMD=python3;
export PIPCMD=pip3;
fi;
brew update;
brew install pyenv;
brew upgrade pyenv;
brew install pyenv-virtualenv;
eval "$(pyenv init -)";
eval "$(pyenv virtualenv-init -)";
pyenv install $OSXENV;
pyenv virtualenv $OSXENV venv;
pyenv activate venv;
which python;
python --version;
which pip;
export PYCMD=python;
export PIPCMD=pip;
fi;

- $PIPCMD install lxml enum34 pyyaml rdflib
Expand Down
4 changes: 4 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ environment:
PYVER: "2.7"
- PYTHON: "C:\\Python35"
PYVER: "3.5"
- PYTHON: "C:\\Python36"
PYVER: "3.6"
- PYTHON: "C:\\Python27-x64"
PYVER: "2.7"
- PYTHON: "C:\\Python35-x64"
PYVER: "3.5"
- PYTHON: "C:\\Python36-x64"
PYVER: "3.6"

build: false

Expand Down
14 changes: 7 additions & 7 deletions doc/odml_ontology/root-ontology.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ xsd:date rdf:type rdfs:Datatype ;
### https://g-node.org/projects/odml-rdf#hasValue
:hasValue rdf:type owl:ObjectProperty ;
rdfs:domain :Property ;
rdfs:range rdf:Bag ;
rdfs:range rdf:Seq ;
rdfs:label "hasValue"^^xsd:string .


Expand Down Expand Up @@ -94,7 +94,7 @@ xsd:date rdf:type rdfs:Datatype ;

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

Expand Down Expand Up @@ -211,15 +211,15 @@ xsd:date rdf:type rdfs:Datatype ;
# Classes
#################################################################

### http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag
rdf:Bag rdf:type owl:Class ;
### http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq
rdf:Seq rdf:type owl:Class ;
rdfs:subClassOf [ rdf:type owl:Restriction ;
owl:onProperty :isValueOf ;
owl:someValuesFrom :Property
] ;
rdfs:comment "The class of unordered containers." ;
rdfs:comment "The class of ordered containers." ;
rdfs:isDefinedBy rdf: ;
rdfs:label "Bag" .
rdfs:label "Seq" .


### https://g-node.org/projects/odml-rdf#Cell
Expand Down Expand Up @@ -346,7 +346,7 @@ rdf:Bag rdf:type owl:Class ;
rdfs:subClassOf owl:Thing ,
[ rdf:type owl:Restriction ;
owl:onProperty :hasValue ;
owl:someValuesFrom rdf:Bag
owl:someValuesFrom rdf:Seq
] ,
[ rdf:type owl:Restriction ;
owl:onProperty :isPropertyOf ;
Expand Down
40 changes: 34 additions & 6 deletions odml/tools/rdf_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from io import StringIO
from os.path import dirname, abspath
from rdflib import Graph, Literal, URIRef
from rdflib.graph import Seq
from rdflib.namespace import XSD, RDF

import odml
Expand Down Expand Up @@ -123,11 +124,27 @@ def save_element(self, e, node=None):
elif isinstance(fmt, Property.__class__) and \
k == 'value' and len(getattr(e, k)) > 0:
values = getattr(e, k)
bag = URIRef(odmlns + str(uuid.uuid4()))
self.g.add((bag, RDF.type, RDF.Bag))
self.g.add((curr_node, fmt.rdf_map(k), bag))
seq = URIRef(odmlns + str(uuid.uuid4()))
self.g.add((seq, RDF.type, RDF.Seq))
self.g.add((curr_node, fmt.rdf_map(k), seq))
# rdflib so far does not respect RDF:li item order
# in RDF:Seq on loading so we have to use custom
# numbered Node elements for now. Once rdflib upgrades
# this should be reversed to RDF:li again!
# see https://github.com/RDFLib/rdflib/issues/280
# -- keep until supported
# bag = URIRef(odmlns + str(uuid.uuid4()))
# self.g.add((bag, RDF.type, RDF.Bag))
# self.g.add((curr_node, fmt.rdf_map(k), bag))
# for v in values:
# self.g.add((bag, RDF.li, Literal(v)))

counter = 1
for v in values:
self.g.add((bag, RDF.li, Literal(v)))
pred = "%s_%s" % (str(RDF), counter)
self.g.add((seq, URIRef(pred), Literal(v)))
counter = counter + 1

# adding entities' properties
else:
val = getattr(e, k)
Expand Down Expand Up @@ -258,9 +275,20 @@ def parse_property(self, prop_uri):
elems = list(self.g.objects(subject=prop_uri, predicate=attr[1]))
if attr[0] == "value" and len(elems) > 0:
prop_attrs[attr[0]] = []

# rdflib does not respect order with RDF.li items yet, see comment above
# support both RDF.li and rdf:_nnn for now.
# Remove rdf:_nnn once rdflib respects RDF.li order in an RDF.Seq obj.
values = list(self.g.objects(subject=elems[0], predicate=RDF.li))
for v in values:
prop_attrs[attr[0]].append(v.toPython())
if len(values) > 0:
for v in values:
prop_attrs[attr[0]].append(v.toPython())
else:
# rdf:__nnn part
valseq = Seq(graph=self.g, subject=elems[0])
for seqitem in valseq:
prop_attrs[attr[0]].append(seqitem.toPython())

elif attr[0] == "id":
prop_attrs[attr[0]] = prop_uri.split("#", 1)[1]
else:
Expand Down
4 changes: 2 additions & 2 deletions test/resources/version_conversion.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ Document:
properties:
- name: prop_name
values:
- dtype: !!python/object/apply:odml.dtypes.DType
- dtype:
- string
value: '[''one'', ''two'']'
- dtype: !!python/object/apply:odml.dtypes.DType
- dtype:
- int
value: '1'
odml-version: '1'
30 changes: 15 additions & 15 deletions test/resources/version_conversion_int.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,23 @@ Document:
values:
- dtype: string
- definition: def val 1
dtype: !!python/object/apply:odml.dtypes.DType
dtype:
- string
filename: filename val 1
reference: ref val 1
uncertainty: 11
unit: arbitrary
value: '1'
- definition: def val 2
dtype: !!python/object/apply:odml.dtypes.DType
dtype:
- int
filename: filename val 2
reference: ref val 2
uncertainty: 12
unit: arbitrary 2
value: '2'
- definition: def val 3
dtype: !!python/object/apply:odml.dtypes.DType
dtype:
- string
filename: filename val 3
reference: ref val 3
Expand All @@ -44,63 +44,63 @@ Document:
values:
- dtype: string
- definition: def val 1
dtype: !!python/object/apply:odml.dtypes.DType
dtype:
- int
filename: filename val 1
reference: ref val 1
uncertainty: 12
unit: arbitrary
value: '1'
- definition: def val 1
dtype: !!python/object/apply:odml.dtypes.DType
dtype:
- int
filename: filename val 1
reference: ref val 1
uncertainty: 12
unit: arbitrary
value: '2'
- definition: def val 1
dtype: !!python/object/apply:odml.dtypes.DType
dtype:
- int
filename: filename val 1
reference: ref val 1
uncertainty: 12
unit: arbitrary
value: '3'
- definition: def val 1
dtype: !!python/object/apply:odml.dtypes.DType
dtype:
- int
filename: filename val 1
reference: ref val 1
uncertainty: 12
unit: arbitrary
value: '4'
- definition: def val 1
dtype: !!python/object/apply:odml.dtypes.DType
dtype:
- int
filename: filename val 1
reference: ref val 1
uncertainty: 12
unit: arbitrary
value: '4'
- definition: def val 1
dtype: !!python/object/apply:odml.dtypes.DType
dtype:
- int
filename: filename val 1
reference: ref val 1
uncertainty: 12
unit: arbitrary
value: '4'
- definition: def val 1
dtype: !!python/object/apply:odml.dtypes.DType
dtype:
- int
filename: filename val 1
reference: ref val 1
uncertainty: 12
unit: arbitrary
value: '4'
- definition: def val 1
dtype: !!python/object/apply:odml.dtypes.DType
dtype:
- int
filename: filename val 1
reference: ref val 1
Expand Down Expand Up @@ -132,31 +132,31 @@ Document:
values:
- dtype: string
- definition: def val 1
dtype: !!python/object/apply:odml.dtypes.DType
dtype:
- int
filename: filename val 1
reference: ref val 1
uncertainty: 12
unit: arbitrary
value: '4'
- definition: def val 1
dtype: !!python/object/apply:odml.dtypes.DType
dtype:
- int
filename: filename val 1
reference: ref val 1
uncertainty: 12
unit: arbitrary
value: '4'
- definition: def val 1
dtype: !!python/object/apply:odml.dtypes.DType
dtype:
- int
filename: filename val 1
reference: ref val 1
uncertainty: 12
unit: arbitrary
value: '4'
- definition: def val 1
dtype: !!python/object/apply:odml.dtypes.DType
dtype:
- int
filename: filename val 1
reference: ref val 1
Expand Down
7 changes: 5 additions & 2 deletions test/test_parser_odml.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,11 @@ def test_rdf_file(self):
self.rdf_writer.write_file(self.odml_doc, self.rdf_file)
rdf_doc = self.rdf_reader.from_file(self.rdf_file, "turtle")

# RDF does not preserve the order of sections,
# need to check the attributes by hand.
self.assertEqual(self.odml_doc, rdf_doc[0])

# RDF does not preserve the order of sections or properties,
# check the attributes by hand to make sure everything
# was correctly imported.
self.assertEqual(len(rdf_doc), 1)
self.assertEqual(rdf_doc[0].author, self.odml_doc.author)
self.assertEqual(rdf_doc[0].version, self.odml_doc.version)
Expand Down
22 changes: 17 additions & 5 deletions test/test_rdf_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ def test_adding_values(self):
w = RDFWriter([doc])
w.convert_to_rdf()
self.assertEqual(len(list(w.g.subject_objects(predicate=RDF.li))), 0)
self.assertEqual(len(list(
w.g.subject_objects(predicate=URIRef("%s_1" % str(RDF))))), 0)

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

w = RDFWriter([doc])
w.convert_to_rdf()
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li, object=Literal("val")))), 1)
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li,
object=Literal("val")))), 0)
self.assertEqual(len(list(w.g.subjects(predicate=URIRef("%s_1" % str(RDF)),
object=Literal("val")))), 1)

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)
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li, object=Literal("val")))), 1)
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li, object=Literal("val2")))), 1)
self.assertEqual(len(list(w.g.subject_objects(predicate=RDF.li))), 0)
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li, object=Literal("val")))), 0)
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li, object=Literal("val2")))), 0)

self.assertEqual(len(list(w.g.subjects(predicate=URIRef("%s_1" % str(RDF)),
object=Literal("val")))), 1)
self.assertEqual(len(list(w.g.subjects(predicate=URIRef("%s_2" % str(RDF)),
object=Literal("val2")))), 1)

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

w = RDFWriter([doc])
w.convert_to_rdf()
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li, object=Literal("val")))), 3)
self.assertEqual(len(list(w.g.subjects(predicate=RDF.li, object=Literal("val")))), 0)
self.assertEqual(len(list(w.g.subjects(predicate=URIRef("%s_1" % str(RDF)),
object=Literal("val")))), 3)

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

0 comments on commit a75d1db

Please sign in to comment.