Skip to content

Commit

Permalink
Fix turtle serialization of rdf:type in subject and object
Browse files Browse the repository at this point in the history
Previously if `rdf:type` occurred in subject or object of a triple then
turtle would have not added a prefix for rdf as it considered `rdf:type`
to be a keyword regardless of where in the triple it occurred.

This changeset ensures that rdf:type is only considered a keyword if it
occurs as the predicate of a triple.
  • Loading branch information
aucampia committed Jan 23, 2022
1 parent d3f9453 commit acb1a10
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 22 deletions.
3 changes: 2 additions & 1 deletion rdflib/plugins/serializers/turtle.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,8 @@ def serialize(self, stream, base=None, encoding=None, spacious=None, **args):
def preprocessTriple(self, triple):
super(TurtleSerializer, self).preprocessTriple(triple)
for i, node in enumerate(triple):
if node in self.keywords:
if i == VERB and node in self.keywords:
# predicate is a keyword
continue
# Don't use generated prefixes for subjects and objects
self.getQName(node, gen_prefix=(i == VERB))
Expand Down
16 changes: 0 additions & 16 deletions test/test_roundtrip.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,22 +138,6 @@
reason="missing escaping: PCDATA invalid Char value 12 and 8",
raises=SAXParseException,
),
("n3", "rdf_prefix.jsonld"): pytest.mark.xfail(
reason="missing 'rdf:' prefix",
raises=BadSyntax,
),
("ttl", "rdf_prefix.jsonld"): pytest.mark.xfail(
reason="missing 'rdf:' prefix",
raises=BadSyntax,
),
("trig", "rdf_prefix.jsonld"): pytest.mark.xfail(
reason="missing 'rdf:' prefix",
raises=BadSyntax,
),
("turtle", "rdf_prefix.jsonld"): pytest.mark.xfail(
reason="missing 'rdf:' prefix",
raises=BadSyntax,
),
}

# This is for files which can only be represented properly in one format
Expand Down
51 changes: 46 additions & 5 deletions test/test_serializer.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,53 @@
import logging
import unittest
from rdflib import Graph, URIRef, Literal
from rdflib import RDF, Graph, Literal, Namespace, URIRef
from tempfile import TemporaryDirectory
from pathlib import Path, PurePath

from typing import Tuple, cast

import pytest
import itertools

from rdflib.graph import ConjunctiveGraph

from .testutils import GraphHelper


@pytest.mark.parametrize(
"format, tuple_index, is_keyword",
[
(format, tuple_index, keyword)
for format, (tuple_index, keyword) in itertools.product(
["turtle", "n3", "trig"],
[
(0, False),
(1, True),
(2, False),
],
)
]
+ [("trig", 3, False)],
)
def test_rdf_type(format: str, tuple_index: int, is_keyword: bool) -> None:
NS = Namespace("example:")
graph = ConjunctiveGraph()
graph.bind("eg", NS)
nodes = [NS.subj, NS.pred, NS.obj, NS.graph]
nodes[tuple_index] = RDF.type
quad = cast(Tuple[URIRef, URIRef, URIRef, URIRef], tuple(nodes))
graph.add(quad)
data = graph.serialize(format=format)
logging.info("data = %s", data)
assert NS in data
if is_keyword:
assert str(RDF) not in data
else:
assert str(RDF) in data
parsed_graph = ConjunctiveGraph()
parsed_graph.parse(data=data, format=format)
GraphHelper.assert_triple_sets_equals(graph, parsed_graph)


class TestSerialize(unittest.TestCase):
def setUp(self) -> None:
Expand Down Expand Up @@ -56,7 +101,3 @@ def test_serialize_to_fileurl(self):
graph_check = Graph()
graph_check.parse(source=tfpath, format="nt")
self.assertEqual(self.triple, next(iter(graph_check)))


if __name__ == "__main__":
unittest.main()

0 comments on commit acb1a10

Please sign in to comment.