summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Car <nicholas.car@csiro.au>2020-04-16 23:19:22 +1000
committerNicholas Car <nicholas.car@csiro.au>2020-04-16 23:19:22 +1000
commit56d0d74c6becdfa22a193c98293314bd6ee9dde1 (patch)
tree6c44e0328ee76bc665e6dc72c8c416a96e64d174
parent26710b0bbd8ed9c8c950479f61ae9dec0a504e2e (diff)
downloadrdflib-issue_1003.tar.gz
inverted precedence of base: graph wins over adding base to serialize(). Added RDF/XML, TriX & 1/2 TriG (incomplete)issue_1003
-rw-r--r--rdflib/graph.py21
-rw-r--r--rdflib/plugins/serializers/rdfxml.py10
-rw-r--r--rdflib/plugins/serializers/trig.py8
-rw-r--r--rdflib/plugins/serializers/trix.py6
-rw-r--r--rdflib/plugins/serializers/turtle.py8
-rw-r--r--test/test_issue1003.py95
6 files changed, 114 insertions, 34 deletions
diff --git a/rdflib/graph.py b/rdflib/graph.py
index a00730ce..9868b097 100644
--- a/rdflib/graph.py
+++ b/rdflib/graph.py
@@ -954,18 +954,20 @@ class Graph(Node):
but "xml", "n3", "turtle", "nt", "pretty-xml", "trix", "trig" and "nquads" are built in.
"""
- # if a base is set here, use it, else if it was set at graph creation time, use that (self.base)
- if base is not None:
- self.base = base
+ # if base is set for the graph use that, if not and a base is given here, use that
+ if self.base is not None:
+ base = self.base
+ else:
+ pass # i.e. base is set in this method
serializer = plugin.get(format, Serializer)(self)
if destination is None:
stream = BytesIO()
- serializer.serialize(stream, base=self.base, encoding=encoding, **args)
+ serializer.serialize(stream, base=base, encoding=encoding, **args)
return stream.getvalue()
if hasattr(destination, "write"):
stream = destination
- serializer.serialize(stream, base=self.base, encoding=encoding, **args)
+ serializer.serialize(stream, base=base, encoding=encoding, **args)
else:
location = destination
scheme, netloc, path, params, _query, fragment = urlparse(location)
@@ -976,7 +978,7 @@ class Graph(Node):
return
fd, name = tempfile.mkstemp()
stream = os.fdopen(fd, "wb")
- serializer.serialize(stream, base=self.base, encoding=encoding, **args)
+ serializer.serialize(stream, base=base, encoding=encoding, **args)
stream.close()
if hasattr(shutil, "move"):
shutil.move(name, path)
@@ -1657,13 +1659,13 @@ class Dataset(ConjunctiveGraph):
.. versionadded:: 4.0
"""
- def __init__(self, store="default", default_union=False):
+ def __init__(self, store="default", default_union=False, default_graph_base=None):
super(Dataset, self).__init__(store=store, identifier=None)
if not self.store.graph_aware:
raise Exception("DataSet must be backed by a graph-aware store!")
self.default_context = Graph(
- store=self.store, identifier=DATASET_DEFAULT_GRAPH_ID
+ store=self.store, identifier=DATASET_DEFAULT_GRAPH_ID, base=default_graph_base
)
self.default_union = default_union
@@ -1674,7 +1676,7 @@ class Dataset(ConjunctiveGraph):
)
return pattern % self.store.__class__.__name__
- def graph(self, identifier=None):
+ def graph(self, identifier=None, base=None):
if identifier is None:
from rdflib.term import rdflib_skolem_genid
@@ -1684,6 +1686,7 @@ class Dataset(ConjunctiveGraph):
identifier = BNode().skolemize()
g = self._graph(identifier)
+ g.base = base
self.store.add_graph(g)
return g
diff --git a/rdflib/plugins/serializers/rdfxml.py b/rdflib/plugins/serializers/rdfxml.py
index 631c8fe0..0da1cccd 100644
--- a/rdflib/plugins/serializers/rdfxml.py
+++ b/rdflib/plugins/serializers/rdfxml.py
@@ -46,7 +46,11 @@ class XMLSerializer(Serializer):
yield prefix, namespace
def serialize(self, stream, base=None, encoding=None, **args):
- self.base = base
+ # if base is set for the graph use that, if not and a base is given here, use that
+ if self.store.base is not None:
+ self.base = self.store.base
+ else:
+ self.base = base
self.__stream = stream
self.__serialized = {}
encoding = self.encoding
@@ -60,8 +64,8 @@ class XMLSerializer(Serializer):
write('<rdf:RDF\n')
# If provided, write xml:base attribute for the RDF
- if "xml_base" in args:
- write(' xml:base="%s"\n' % args['xml_base'])
+ if self.base:
+ write(' xml:base="%s"\n' % self.base)
# TODO:
# assert(
# namespaces["http://www.w3.org/1999/02/22-rdf-syntax-ns#"]=='rdf')
diff --git a/rdflib/plugins/serializers/trig.py b/rdflib/plugins/serializers/trig.py
index 6c05ad75..2cfc2145 100644
--- a/rdflib/plugins/serializers/trig.py
+++ b/rdflib/plugins/serializers/trig.py
@@ -39,7 +39,7 @@ class TrigSerializer(TurtleSerializer):
for triple in context:
self.preprocessTriple(triple)
- self._contexts[context]=(self.orderSubjects(), self._subjects, self._references)
+ self._contexts[context] = (self.orderSubjects(), self._subjects, self._references)
def reset(self):
super(TrigSerializer, self).reset()
@@ -49,7 +49,11 @@ class TrigSerializer(TurtleSerializer):
spacious=None, **args):
self.reset()
self.stream = stream
- self.base = base
+ # if base is set for the graph use that, if not and a base is given here, use that
+ if self.store.base is not None:
+ self.base = self.store.base
+ else:
+ self.base = base
if spacious is not None:
self._spacious = spacious
diff --git a/rdflib/plugins/serializers/trix.py b/rdflib/plugins/serializers/trix.py
index fceec6bd..f3477eab 100644
--- a/rdflib/plugins/serializers/trix.py
+++ b/rdflib/plugins/serializers/trix.py
@@ -29,6 +29,10 @@ class TriXSerializer(Serializer):
self.writer = XMLWriter(stream, nm, encoding, extra_ns={"": TRIXNS})
self.writer.push(TRIXNS[u"TriX"])
+ if self.store.base:
+ base = self.store.base
+ if base is not None:
+ self.writer.attribute("http://www.w3.org/XML/1998/namespacebase", base)
self.writer.namespaces()
if isinstance(self.store, ConjunctiveGraph):
@@ -44,6 +48,8 @@ class TriXSerializer(Serializer):
def _writeGraph(self, graph):
self.writer.push(TRIXNS[u"graph"])
+ if graph.base:
+ self.writer.attribute("http://www.w3.org/XML/1998/namespacebase", graph.base)
if isinstance(graph.identifier, URIRef):
self.writer.element(
TRIXNS[u"uri"], content=text_type(graph.identifier))
diff --git a/rdflib/plugins/serializers/turtle.py b/rdflib/plugins/serializers/turtle.py
index 63f9da06..b7f50087 100644
--- a/rdflib/plugins/serializers/turtle.py
+++ b/rdflib/plugins/serializers/turtle.py
@@ -224,8 +224,10 @@ class TurtleSerializer(RecursiveSerializer):
spacious=None, **args):
self.reset()
self.stream = stream
- # if base is set here, override previously set base if set at graph init
- if base is not None:
+ # if base is set for the graph use that, if not and a base is given here, use that
+ if self.store.base is not None:
+ self.base = self.store.base
+ else:
self.base = base
if spacious is not None:
@@ -248,6 +250,8 @@ class TurtleSerializer(RecursiveSerializer):
self.endDocument()
stream.write(b("\n"))
+ self.base = None
+
def preprocessTriple(self, triple):
super(TurtleSerializer, self).preprocessTriple(triple)
for i, node in enumerate(triple):
diff --git a/test/test_issue1003.py b/test/test_issue1003.py
index 99953ba9..883022a7 100644
--- a/test/test_issue1003.py
+++ b/test/test_issue1003.py
@@ -1,4 +1,4 @@
-from rdflib import Graph, Literal, Namespace, RDF, URIRef
+from rdflib import Graph, Dataset, Literal, Namespace, RDF, URIRef
from rdflib.namespace import SKOS, DCTERMS
"""
@@ -7,10 +7,15 @@ Testing scenarios:
2. base set at graph creation
3. base set at serialization
4. base set at both graph creation & serialization, serialization overrides
+ 5. multiple serialization side effect checking
+ 6. checking results for RDF/XML
+ 7. checking results for N3
+ 8. checking results for TriX & TriG
"""
# variables
-base = Namespace("http://example.org/")
+base_one = Namespace("http://one.org/")
+base_two = Namespace("http://two.org/")
title = Literal("Title", lang="en")
description = Literal("Test Description", lang="en")
creator = URIRef("https://creator.com")
@@ -25,34 +30,88 @@ g.bind("dct", DCTERMS)
g.bind("skos", SKOS)
-# 1. no base set
+# 1. no base set for graph, no base set for serialization
g1 = Graph()
g1 += g
# @base should not be in output
assert "@base" not in g.serialize(format='turtle').decode("utf-8")
-# 2. base set at graph creation
-g2 = Graph(base=base)
+# 2. base one set for graph, no base set for serialization
+g2 = Graph(base=base_one)
g2 += g
-# @base should be in output
-assert "@base" in g2.serialize(format='turtle').decode("utf-8")
+# @base should be in output, from Graph (one)
+assert "@base <http://one.org/> ." in g2.serialize(format='turtle').decode("utf-8")
-# 3. base set at serialization
+# 3. no base set for graph, base two set for serialization
g3 = Graph()
g3 += g
-# @base should be in output
-assert "@base" in g3.serialize(format='turtle', base=base).decode("utf-8")
+# @base should be in output, from serialization (two)
+assert "@base <http://two.org/> ." in g3.serialize(format='turtle', base=base_two).decode("utf-8")
-# 4. base set at both graph creation & serialization, serialization overrides
-g4 = Graph(base=Namespace("http://nothing.com/"))
+# 4. base one set for graph, base two set for serialization, Graph one overrides
+g4 = Graph(base=base_one)
g4 += g
+# @base should be in output, from graph (one)
+assert "@base <http://one.org/> ." in g4.serialize(format='turtle', base=base_two).decode("utf-8")
+# just checking that the serialization setting (two) hasn't snuck through
+assert "@base <http://two.org/> ." not in g4.serialize(format='turtle', base=base_two).decode("utf-8")
-# @base should be in output and it should be http://example.org/ (graph init copy)
-assert "@base <http://nothing.com/>" in g4.serialize(format='turtle').decode("utf-8")
-# @base should be in output and it should be http://example.org/, not http://nothing.com/ (serialization overwritten)
-assert "@base <http://example.org/>" in g4.serialize(format='turtle', base=base).decode("utf-8")
-# just checking that the graph init base isn't sneakily in output
-assert "@base <http://nothing.com/>" not in g4.serialize(format='turtle', base=base).decode("utf-8")
+
+# 5. multiple serialization side effect checking
+g5 = Graph()
+g5 += g
+# @base should be in output, from serialization (two)
+assert "@base <http://two.org/> ." in g5.serialize(format='turtle', base=base_two).decode("utf-8")
+
+# checking for side affects - no base now set for this serialization
+# @base should not be in output
+assert "@base" not in g5.serialize(format='turtle').decode("utf-8")
+
+
+# 6. checking results for RDF/XML
+g6 = Graph()
+g6 += g
+g6.bind("dct", DCTERMS)
+g6.bind("skos", SKOS)
+assert "@xml:base" not in g6.serialize(format='xml').decode("utf-8")
+assert 'xml:base="http://one.org/"' in g6.serialize(format='xml', base=base_one).decode("utf-8")
+g6.base = base_two
+assert 'xml:base="http://two.org/"' in g6.serialize(format='xml').decode("utf-8")
+assert 'xml:base="http://two.org/"' in g6.serialize(format='xml', base=base_one).decode("utf-8")
+
+# 7. checking results for N3
+g7 = Graph()
+g7 += g
+g7.bind("dct", DCTERMS)
+g7.bind("skos", SKOS)
+assert "@xml:base" not in g7.serialize(format='xml').decode("utf-8")
+assert "@base <http://one.org/> ." in g7.serialize(format='n3', base=base_one).decode("utf-8")
+g7.base = base_two
+assert "@base <http://two.org/> ." in g7.serialize(format='n3').decode("utf-8")
+assert "@base <http://two.org/> ." in g7.serialize(format='n3', base=base_one).decode("utf-8")
+
+# 8. checking results for TriX & TriG
+# TriX can specify a base per graph but setting a base for the whole
+base_three = Namespace("http://three.org/")
+ds1 = Dataset()
+ds1.bind("dct", DCTERMS)
+ds1.bind("skos", SKOS)
+g8 = ds1.graph(URIRef('http://g8.com/'), base=base_one)
+g9 = ds1.graph(URIRef('http://g9.com/'))
+g8 += g
+g9 += g
+g9.base = base_two
+ds1.base = base_three
+
+trix = ds1.serialize(format='trix', base=Namespace("http://two.org/")).decode("utf-8")
+assert '<graph xml:base="http://one.org/">' in trix
+assert '<graph xml:base="http://two.org/">' in trix
+assert '<TriX xml:base="http://three.org/"' in trix
+
+trig = ds1.serialize(format='trig', base=Namespace("http://two.org/")).decode("utf-8")
+assert '@base <http://one.org/> .' not in trig
+assert '@base <http://two.org/> .' not in trig
+assert '@base <http://three.org/> .' in trig