Skip to content

Commit

Permalink
Longturtle improvements (#2500)
Browse files Browse the repository at this point in the history
* small updates to the longturtle serializer and an improved test for it
* add docco

---------

Co-authored-by: Iwan Aucamp <aucampia@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
3 people committed Jul 25, 2023
1 parent b1ff089 commit 5ee8bd7
Show file tree
Hide file tree
Showing 3 changed files with 268 additions and 210 deletions.
11 changes: 10 additions & 1 deletion docs/plugin_serializers.rst
Expand Up @@ -32,7 +32,7 @@ xml :class:`~rdflib.plugins.serializers.rdfxml.XMLSerializer`

JSON-LD
-------
JSON-LD - 'json-ld' - has been incorprated in rdflib since v6.0.0.
JSON-LD - 'json-ld' - has been incorporated into RDFLib since v6.0.0.

HexTuples
---------
Expand All @@ -43,3 +43,12 @@ Hextuple) will be an empty string.

For context-aware (multi-graph) serialization, the 'graph' field of the default graph will be an empty string and
the values for other graphs will be Blank Node IDs or IRIs.

Longturtle
----------
Longturtle is just the turtle format with newlines preferred over compactness - multiple nodes on the same line
to enhance the format's text file version control (think Git) friendliness - and more modern forms of prefix markers -
PREFIX instead of @prefix - to make it as similar to SPARQL as possible.

Longturtle is Turtle 1.1 compliant and will work wherever ordinary turtle works, however some very old parsers don't
understand PREFIX, only @prefix...
43 changes: 22 additions & 21 deletions rdflib/plugins/serializers/longturtle.py
Expand Up @@ -13,7 +13,7 @@
on the start of the next line
* uses default encoding (encode()) is used instead of "latin-1"
- Nicholas Car, 2021
- Nicholas Car, 2023
"""

from rdflib.exceptions import Error
Expand Down Expand Up @@ -101,7 +101,6 @@ def serialize(self, stream, base=None, encoding=None, spacious=None, **args):
self.write("\n")

self.endDocument()
self.write("\n")

self.base = None

Expand Down Expand Up @@ -168,21 +167,20 @@ def s_default(self, subject):
self.path(subject, SUBJECT)
self.write("\n" + self.indent())
self.predicateList(subject)
self.write(" ;\n.")
self.write("\n.")
return True

def s_squared(self, subject):
if (self._references[subject] > 0) or not isinstance(subject, BNode):
return False
self.write("\n" + self.indent() + "[]")
self.predicateList(subject)
self.predicateList(subject, newline=False)
self.write(" ;\n.")
return True

def path(self, node, position, newline=False):
if not (
self.p_squared(node, position, newline)
or self.p_default(node, position, newline)
self.p_squared(node, position) or self.p_default(node, position, newline)
):
raise Error("Cannot serialize node '%s'" % (node,))

Expand All @@ -207,7 +205,11 @@ def label(self, node, position):

return self.getQName(node, position == VERB) or node.n3()

def p_squared(self, node, position, newline=False):
def p_squared(
self,
node,
position,
):
if (
not isinstance(node, BNode)
or node in self._serialized
Expand All @@ -216,23 +218,19 @@ def p_squared(self, node, position, newline=False):
):
return False

if not newline:
self.write(" ")

if self.isValidList(node):
# this is a list
self.depth += 2
self.write("(\n")
self.depth -= 1
self.write(" (\n")
self.depth -= 2
self.doList(node)
self.depth -= 1
self.write("\n" + self.indent(1) + ")")
self.write("\n" + self.indent() + ")")
else:
# this is a Blank Node
self.subjectDone(node)
self.depth += 2
self.write("[\n")
self.depth -= 1
self.predicateList(node, newline=False)
self.write("\n" + self.indent(1) + "[\n")
self.depth += 1
self.predicateList(node)
self.depth -= 1
self.write("\n" + self.indent(1) + "]")

Expand Down Expand Up @@ -279,6 +277,7 @@ def predicateList(self, subject, newline=False):
self.write(" ;\n" + self.indent(1))
self.verb(predicate, newline=True)
self.objectList(properties[predicate])
self.write(" ;")

def verb(self, node, newline=False):
self.path(node, VERB, newline)
Expand All @@ -291,11 +290,13 @@ def objectList(self, objects):
self.depth += depthmod
first_nl = False
if count > 1:
self.write("\n" + self.indent(1))
if not isinstance(objects[0], BNode):
self.write("\n" + self.indent(1))
first_nl = True
self.path(objects[0], OBJECT, newline=first_nl)
for obj in objects[1:]:
self.write(" ,\n")
self.write(self.indent(1))
self.write(" ,")
if not isinstance(obj, BNode):
self.write("\n" + self.indent(1))
self.path(obj, OBJECT, newline=True)
self.depth -= depthmod

0 comments on commit 5ee8bd7

Please sign in to comment.