diff --git a/glowtables/sparql.py b/glowtables/sparql.py index 8c6b713..5662b83 100644 --- a/glowtables/sparql.py +++ b/glowtables/sparql.py @@ -17,7 +17,7 @@ import abc from typing import Iterable -import SPARQLWrapper +import requests class SparqlBackend(abc.ABC): @@ -37,9 +37,12 @@ class RemoteSparqlBackend(SparqlBackend): :param agent: User-Agent to use in HTTP requests """ self._url = url - self._agent = agent + self._session = requests.Session() + self._session.headers["User-Agent"] = agent def query(self, query: str) -> Iterable[tuple]: - sparql = SPARQLWrapper.SPARQLWrapper(self._url, agent=self._agent) - sparql.setQuery(query) - return sparql.query() + params = {"format": "json", "query": query} + resp = self._session.post(self._url, params=params).json() + variables = resp["head"]["vars"] + for result in resp["results"]["bindings"]: + yield tuple(result.get(variable) for variable in variables) diff --git a/glowtables/tests/conftest.py b/glowtables/tests/conftest.py index 673f8b6..7be2bf5 100644 --- a/glowtables/tests/conftest.py +++ b/glowtables/tests/conftest.py @@ -16,23 +16,10 @@ # pylint: disable=redefined-outer-name -from typing import Iterable - import pytest import rdflib -from glowtables.sparql import SparqlBackend - - -class RdflibSparqlBackend(SparqlBackend): - """Mock SPARQL backend that queries a local rdflib graph.""" - - def __init__(self, graph: rdflib.Graph): - self._graph = graph - - def query(self, query: str) -> Iterable[tuple]: - ret = self._graph.query(query) - return ret +from glowtables.sparql import RemoteSparqlBackend @pytest.fixture() @@ -42,6 +29,16 @@ def rdflib_graph() -> rdflib.Graph: @pytest.fixture() -def rdflib_sparql(rdflib_graph: rdflib.Graph) -> RdflibSparqlBackend: +def rdflib_sparql(requests_mock, rdflib_graph: rdflib.Graph) -> RemoteSparqlBackend: """Returns a SPARQL backend instance for ``rdflib_graph``.""" - return RdflibSparqlBackend(rdflib_graph) + + def json_callback(request, context): + result = rdflib_graph.query(request.json()) + context.status_code = 200 + return { + "head": {"vars": result.vars}, + "results": list(result), + } + + requests_mock.register_uri("POST", "mock://sparql.example.org/", json=json_callback) + return RemoteSparqlBackend("mock://sparql.example.org/", agent="Mock Client") diff --git a/glowtables/tests/table_test.py b/glowtables/tests/table_test.py index 3a3e1a3..1a5b2f5 100644 --- a/glowtables/tests/table_test.py +++ b/glowtables/tests/table_test.py @@ -17,12 +17,11 @@ import textwrap import pytest import rdflib +from glowtables.sparql import SparqlBackend from glowtables.table import Language, LiteralField, Table -from .conftest import RdflibSparqlBackend - -def test_single_literal(rdflib_sparql: RdflibSparqlBackend) -> None: +def test_single_literal(rdflib_sparql: SparqlBackend) -> None: name_field = LiteralField( "display_name", {Language("en"): "Name"}, @@ -46,7 +45,7 @@ def test_single_literal(rdflib_sparql: RdflibSparqlBackend) -> None: rdflib_sparql.query(table.sparql()) -def test_two_literals(rdflib_sparql: RdflibSparqlBackend) -> None: +def test_two_literals(rdflib_sparql: SparqlBackend) -> None: name_field = LiteralField( "display_name", {Language("en"): "Name"}, @@ -76,7 +75,7 @@ def test_two_literals(rdflib_sparql: RdflibSparqlBackend) -> None: rdflib_sparql.query(table.sparql()) -def test_default_value(rdflib_sparql: RdflibSparqlBackend) -> None: +def test_default_value(rdflib_sparql: SparqlBackend) -> None: name_field = LiteralField( "display_name", {Language("en"): "Name"}, diff --git a/pyproject.toml b/pyproject.toml index e96213c..df505d1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,7 @@ requires-python = ">=3.9" dependencies = [ "flask ~= 2.0.0", "rdflib ~= 6.0.0", + "requests ~= 3.0.0", ] [project.optional-dependencies] @@ -29,7 +30,6 @@ python_version = "3.9" [[tool.mypy.overrides]] module = [ "requests_mock", - "SPARQLWrapper", ] ignore_missing_imports = true