Skip to content

Commit

Permalink
Allows using Oxigraph native serializers
Browse files Browse the repository at this point in the history
  • Loading branch information
Tpt committed Oct 20, 2024
1 parent 409d3db commit 5bf7acb
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 2 deletions.
63 changes: 63 additions & 0 deletions oxrdflib/serializer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from abc import ABC, abstractmethod
from typing import IO, Any, Optional

from pyoxigraph import RdfFormat, serialize
from rdflib.serializer import Serializer

from oxrdflib._converter import to_ox
from oxrdflib.store import OxigraphStore

__all__ = [
"OxigraphN3Serializer",
"OxigraphTurtleSerializer",
"OxigraphNTriplesSerializer",
"OxigraphRdfXmlSerializer",
"OxigraphTriGSerializer",
"OxigraphNQuadsSerializer",
]


class _OxigraphSerializer(Serializer, ABC):
def serialize(
self,
stream: IO[bytes],
_base: Optional[str] = None,
encoding: Optional[str] = None,
**kwargs: Any, # noqa: ARG002
) -> None:
if encoding not in (None, "utf-8"):
raise ValueError(f"RDF files are always utf-8 encoded, I was passed: {encoding}")
# TODO: base and prefixes
if isinstance(self.store, OxigraphStore):
self.store._inner.dump(stream, format=self._format)
else:
serialize((to_ox(q) for q in self.store), stream, format=self._format)

@property
@abstractmethod
def _format(self) -> RdfFormat:
pass


class OxigraphN3Serializer(_OxigraphSerializer):
_format = RdfFormat.N3


class OxigraphTurtleSerializer(_OxigraphSerializer):
_format = RdfFormat.TURTLE


class OxigraphNTriplesSerializer(_OxigraphSerializer):
_format = RdfFormat.N_TRIPLES


class OxigraphRdfXmlSerializer(_OxigraphSerializer):
_format = RdfFormat.RDF_XML


class OxigraphNQuadsSerializer(_OxigraphSerializer):
_format = RdfFormat.N_QUADS


class OxigraphTriGSerializer(_OxigraphSerializer):
_format = RdfFormat.TRIG
13 changes: 11 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,29 @@ name = "oxrdflib"
readme = "README.md"
requires-python = ">=3.8"


[project.entry-points."rdf.plugins.store"]
Oxigraph = "oxrdflib.store:OxigraphStore"
oxigraph = "oxrdflib.store:OxigraphStore"
OxMemory = "oxrdflib.store:OxigraphStore"
OxSled = "oxrdflib.store:OxigraphStore"


[project.entry-points."rdf.plugins.parser"]
ox-turtle = "oxrdflib.parser:OxigraphTurtleParser"
ox-ttl = "oxrdflib.parser:OxigraphTurtleParser"
ox-ntriples = "oxrdflib.parser:OxigraphNTriplesParser"
ox-nt = "oxrdflib.parser:OxigraphNTriplesParser"
ox-xml = "oxrdflib.parser:OxigraphRdfXmlParser"

[project.entry-points."rdf.plugins.serializer"]
ox-turtle = "oxrdflib.serializer:OxigraphTurtleSerializer"
ox-ttl = "oxrdflib.serializer:OxigraphTurtleSerializer"
ox-ntriples = "oxrdflib.serializer:OxigraphNTriplesSerializer"
ox-n3 = "oxrdflib.serializer:OxigraphN3Serializer"
ox-nquads = "oxrdflib.serializer:OxigraphNQuadsSerializer"
ox-nt = "oxrdflib.serializer:OxigraphNTriplesSerializer"
ox-nt11 = "oxrdflib.serializer:OxigraphNTriplesSerializer"
ox-trig = "oxrdflib.serializer:OxigraphTriGSerializer"
ox-xml = "oxrdflib.serializer:OxigraphRdfXmlSerializer"

[project.urls]
Changelog = "https://github.com/oxigraph/oxrdflib/blob/main/CHANGELOG.md"
Expand Down
60 changes: 60 additions & 0 deletions tests/test_serializer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import unittest

from rdflib import Dataset, Graph, URIRef

s = URIRef("http://example.com/s")
p = URIRef("http://example.com/vocab#p")
o = URIRef("http://example.com/o")
g = URIRef("http://example.com/g")


class TestSerializer(unittest.TestCase):
def test_serialize_graph(self):
for store in ("default", "oxigraph"):
for fmt, serialization in (
("ox-turtle", "<http://example.com/s> <http://example.com/vocab#p> <http://example.com/o> .\n"),
("ox-ttl", "<http://example.com/s> <http://example.com/vocab#p> <http://example.com/o> .\n"),
("ox-ntriples", "<http://example.com/s> <http://example.com/vocab#p> <http://example.com/o> .\n"),
("ox-n3", "<http://example.com/s> <http://example.com/vocab#p> <http://example.com/o> .\n"),
("ox-nquads", "<http://example.com/s> <http://example.com/vocab#p> <http://example.com/o> .\n"),
("ox-nt", "<http://example.com/s> <http://example.com/vocab#p> <http://example.com/o> .\n"),
("ox-nt11", "<http://example.com/s> <http://example.com/vocab#p> <http://example.com/o> .\n"),
("ox-trig", "<http://example.com/s> <http://example.com/vocab#p> <http://example.com/o> .\n"),
(
"ox-xml",
"""<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="http://example.com/s">
<s xmlns="http://example.com/vocab#" rdf:resource="http://example.com/o"/>
</rdf:Description>
</rdf:RDF>""",
),
):
with self.subTest(store=store, format=fmt):
graph = Graph(store=store)
graph.add((s, p, o))
graph.store.add((o, p, s), context=Graph(identifier=g)) # Should not be serialized
self.assertEqual(graph.serialize(format=fmt), serialization)

def test_serialize_dataset(self):
for store in ("default", "oxigraph"):
for fmt, serialization in (
(
"ox-nquads",
"<http://example.com/s> <http://example.com/vocab#p> "
"<http://example.com/o> <http://example.com/g> .\n",
),
(
"ox-trig",
"<http://example.com/g> {\n\t<http://example.com/s> "
"<http://example.com/vocab#p> <http://example.com/o> .\n}\n",
),
):
with self.subTest(store=store, format=fmt):
dataset = Dataset(store=store)
dataset.add((s, p, o, Graph(identifier=g)))
self.assertEqual(dataset.serialize(format=fmt), serialization)


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

0 comments on commit 5bf7acb

Please sign in to comment.