Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 1003 #1005

Merged
merged 8 commits into from
Apr 17, 2020
14 changes: 10 additions & 4 deletions rdflib/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,9 @@ class Graph(Node):
For more on named graphs, see: http://www.w3.org/2004/03/trix/
"""

def __init__(self, store="default", identifier=None, namespace_manager=None):
def __init__(self, store="default", identifier=None, namespace_manager=None, base=None):
super(Graph, self).__init__()
self.base = base
self.__identifier = identifier or BNode()

if not isinstance(self.__identifier, Node):
Expand Down Expand Up @@ -952,14 +953,19 @@ def serialize(
Format support can be extended with plugins,
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

nicholascar marked this conversation as resolved.
Show resolved Hide resolved
serializer = plugin.get(format, Serializer)(self)
if destination is None:
stream = BytesIO()
serializer.serialize(stream, base=base, encoding=encoding, **args)
serializer.serialize(stream, base=self.base, encoding=encoding, **args)
return stream.getvalue()
if hasattr(destination, "write"):
stream = destination
serializer.serialize(stream, base=base, encoding=encoding, **args)
serializer.serialize(stream, base=self.base, encoding=encoding, **args)
else:
location = destination
scheme, netloc, path, params, _query, fragment = urlparse(location)
Expand All @@ -970,7 +976,7 @@ def serialize(
return
fd, name = tempfile.mkstemp()
stream = os.fdopen(fd, "wb")
serializer.serialize(stream, base=base, encoding=encoding, **args)
serializer.serialize(stream, base=self.base, encoding=encoding, **args)
stream.close()
if hasattr(shutil, "move"):
shutil.move(name, path)
Expand Down
7 changes: 6 additions & 1 deletion rdflib/plugins/serializers/turtle.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,9 @@ def serialize(self, stream, base=None, encoding=None,
spacious=None, **args):
self.reset()
self.stream = stream
self.base = base
# if base is set here, override previously set base if set at graph init
if base is not None:
self.base = base
white-gecko marked this conversation as resolved.
Show resolved Hide resolved

if spacious is not None:
self._spacious = spacious
Expand Down Expand Up @@ -291,6 +293,9 @@ def getQName(self, uri, gen_prefix=True):
def startDocument(self):
self._started = True
ns_list = sorted(self.namespaces.items())

if self.base:
self.write(self.indent() + '@base <%s> .\n' % self.base)
for prefix, uri in ns_list:
self.write(self.indent() + '@prefix %s: <%s> .\n' % (prefix, uri))
if ns_list and self._spacious:
Expand Down
58 changes: 58 additions & 0 deletions test/test_issue1003.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from rdflib import Graph, Literal, Namespace, RDF, URIRef
from rdflib.namespace import SKOS, DCTERMS

"""
Testing scenarios:
1. no base set
2. base set at graph creation
3. base set at serialization
4. base set at both graph creation & serialization, serialization overrides
"""

# variables
base = Namespace("http://example.org/")
title = Literal("Title", lang="en")
description = Literal("Test Description", lang="en")
creator = URIRef("https://creator.com")
cs = URIRef("")

# starting graph
g = Graph()
g.add((cs, RDF.type, SKOS.ConceptScheme))
g.add((cs, DCTERMS.creator, creator))
g.add((cs, DCTERMS.source, URIRef("nick")))
g.bind("dct", DCTERMS)
g.bind("skos", SKOS)


# 1. no base set
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)
g2 += g
# @base should be in output
assert "@base" in g2.serialize(format='turtle').decode("utf-8")


# 3. base set at serialization
g3 = Graph()
g3 += g
# @base should be in output
assert "@base" in g3.serialize(format='turtle', base=base).decode("utf-8")


# 4. base set at both graph creation & serialization, serialization overrides
g4 = Graph(base=Namespace("http://nothing.com/"))
g4 += g

# @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")