Skip to content

Commit

Permalink
Upgrades to oxigraph 0.4
Browse files Browse the repository at this point in the history
- Uses RdfFormat type
- Uses the loader "path" argument if possible to skip Python entirely
  • Loading branch information
Tpt committed Oct 17, 2024
1 parent e2a9945 commit 0b4935b
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 60 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.7
python-version: 3.8
cache: pip
- run: pip install . && pip install -r requirements-dev.txt && pip install 'rdflib==6.3.0'
- run: python -m unittest
Expand Down
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
rev: v4.6.0
hooks:
- id: check-ast
- id: check-builtin-literals
Expand All @@ -24,12 +24,12 @@ repos:
- id: requirements-txt-fixer
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.4
rev: v0.6.7
hooks:
- id: ruff-format
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.9.0
rev: v1.11.2
hooks:
- id: mypy
30 changes: 11 additions & 19 deletions oxrdflib/_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,27 +112,19 @@ def from_ox(
raise ValueError(f"Unexpected Oxigraph term: {term!r}")


def rdflib_to_mime_type(rdflib_type: str) -> str:
def guess_rdf_format(rdflib_type: str) -> ox.RdfFormat:
"""Convert an rdflib type to a MIME type."""
if rdflib_type in ("ttl", "turtle"):
return "text/turtle"
if rdflib_type in ("nt", "ntriples"):
return "application/n-triples"
if rdflib_type == "xml":
return "application/rdf+xml"
if rdflib_type == "trig":
return "application/trig"
if rdflib_type == "trix":
return "application/trix"
raise ValueError(f"Unsupported rdflib type: {rdflib_type}")
rdflib_type = ox_to_rdflib_type(rdflib_type)
rdf_format = (
ox.RdfFormat.from_media_type(rdflib_type)
or ox.RdfFormat.from_extension(rdflib_type)
or ox.RdfFormat.from_media_type(f"application/{rdflib_type}")
)
if rdf_format is None:
raise ValueError(f"Unsupported rdflib type: {rdflib_type}")
return rdf_format


def ox_to_rdflib_type(ox_format: str) -> str:
"""Convert an Oxigraph format to a rdflib parser format."""
if ox_format in ("ox-turtle", "ox-ttl"):
return "turtle"
if ox_format in ("ox-nt", "ox-ntriples"):
return "nt"
if ox_format == "ox-xml":
return "xml"
raise ValueError(f"Unsupported Oxigraph type: {ox_format}")
return ox_format[len("ox-") :] if ox_format.startswith("ox-") else ox_format
48 changes: 20 additions & 28 deletions oxrdflib/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
create_input_source,
)

from oxrdflib._converter import ox_to_rdflib_type, rdflib_to_mime_type, to_ox
from oxrdflib._converter import guess_rdf_format, ox_to_rdflib_type, to_ox
from oxrdflib.store import OxigraphStore

__all__ = [
Expand All @@ -22,9 +22,6 @@


class OxigraphParser(Parser):
def __init__(self):
pass

def parse(
self,
source: InputSource,
Expand All @@ -34,7 +31,7 @@ def parse(
**kwargs: Any,
) -> None:
if encoding not in (None, "utf-8"):
raise ParserError("N3/Turtle files are always utf-8 encoded, I was passed: %s" % encoding)
raise ParserError("N3/Turtle files are always utf-8 encoded, I was passed: {encoding}")

if not isinstance(sink.store, OxigraphStore):
warnings.warn(
Expand All @@ -44,31 +41,26 @@ def parse(
stacklevel=2,
)
sink.parse(source, format=ox_to_rdflib_type(format))
return

base_iri = sink.absolutize(source.getPublicId() or source.getSystemId() or "")

args = {
"format": guess_rdf_format(format),
"base_iri": base_iri,
"to_graph": to_ox(sink.identifier),
}
if isinstance(source, URLInputSource):
source = create_input_source(source.url, format=ox_to_rdflib_type(format))
if isinstance(source, FileInputSource):
args["path"] = source.file.name
else:
args["input"] = source.getByteStream()

if kwargs.get("transactional", True):
sink.store._inner.load(**args)
else:
base_iri = sink.absolutize(source.getPublicId() or source.getSystemId() or "")

if isinstance(source, FileInputSource):
input = source.file
elif isinstance(source, URLInputSource):
input = create_input_source(source.url, format=ox_to_rdflib_type(format)).getByteStream()
else:
input = source.getByteStream()

if kwargs.get("transactional", True):
sink.store._inner.load(
input,
rdflib_to_mime_type(ox_to_rdflib_type(format)),
base_iri=base_iri,
to_graph=to_ox(sink.identifier),
)
else:
sink.store._inner.bulk_load(
input,
rdflib_to_mime_type(ox_to_rdflib_type(format)),
base_iri=base_iri,
to_graph=to_ox(sink.identifier),
)
sink.store._inner.bulk_load(**args)


class OxigraphTurtleParser(OxigraphParser):
Expand Down
18 changes: 12 additions & 6 deletions oxrdflib/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,16 @@ def triples(
return iter(()) # We just don't return anything

def __len__(self, context: Optional[Graph] = None) -> int:
if context is None:
# TODO: very bad
return len({q.triple for q in self._inner})
return sum(1 for _ in self._inner.quads_for_pattern(None, None, None, to_ox(context)))
return int(
next(
self._inner.query(
"SELECT (COUNT(DISTINCT TRIPLE(?s, ?p, ?o)) AS ?c) WHERE { ?s ?p ?o }",
**(
{"use_default_graph_as_union": True} if context is None else {"default_graph": to_ox(context)} # type: ignore[dict-item]
),
)
)[0].value
)

def contexts(self, triple: Optional[_Triple] = None) -> Generator[Graph, None, None]:
if triple is None:
Expand Down Expand Up @@ -145,9 +151,9 @@ def query(
use_default_graph_as_union=queryGraph == "__UNION__",
default_graph=(to_ox(queryGraph) if isinstance(queryGraph, Node) else None),
)
if isinstance(result, bool):
if isinstance(result, ox.QueryBoolean):
out = Result("ASK")
out.askAnswer = result
out.askAnswer = bool(result)
elif isinstance(result, ox.QuerySolutions):
out = Result("SELECT")
out.vars = [Variable(v.value) for v in result.variables]
Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,21 @@ description = "rdflib stores based on pyoxigraph"
classifiers = [
"Programming Language :: Python",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"License :: OSI Approved :: BSD License",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Database :: Database Engines/Servers",
]
dependencies = ["pyoxigraph~=0.3.14", "rdflib>=6.3,<8.0"]
dependencies = ["pyoxigraph~=0.4.0", "rdflib>=6.3,<8.0"]
dynamic = ["version"]
license = { text = "BSD-3-Clause" }
name = "oxrdflib"
readme = "README.md"
requires-python = ">=3.7"
requires-python = ">=3.8"


[project.entry-points."rdf.plugins.store"]
Expand Down

0 comments on commit 0b4935b

Please sign in to comment.