From 80e73a00d2c4dbede4348a74e8040f5797efa589 Mon Sep 17 00:00:00 2001 From: David Habgood Date: Tue, 2 Jul 2024 13:54:53 +1000 Subject: [PATCH] Add retrieval of remote prefix declarations. Not yet passing with local pytest tests. Tested to be working manually with Fuseki. Local test failing may be resolved with changes to tests in V4. (#240) --- prez/services/app_service.py | 43 +++++++++++----- tests/data/prefixes/data_using_prefixes.ttl | 11 ++++ tests/data/prefixes/remote_prefixes.ttl | 9 ++++ tests/test_remote_prefixes.py | 57 +++++++++++++++++++++ 4 files changed, 107 insertions(+), 13 deletions(-) create mode 100644 tests/data/prefixes/data_using_prefixes.ttl create mode 100644 tests/data/prefixes/remote_prefixes.ttl create mode 100644 tests/test_remote_prefixes.py diff --git a/prez/services/app_service.py b/prez/services/app_service.py index f4e9e6dc..59d4824c 100644 --- a/prez/services/app_service.py +++ b/prez/services/app_service.py @@ -90,21 +90,22 @@ async def add_prefixes_to_prefix_graph(repo: Repo): """ Adds prefixes to the prefix graph """ + # look for remote prefixes + remote_prefix_query = f""" + CONSTRUCT WHERE {{ ?bn ?prefix; + ?namespace. }} + """ + remote_prefix_g, _ = await repo.send_queries([remote_prefix_query], []) + if remote_prefix_g: + remote_i = await _add_prefixes_from_graph(remote_prefix_g) + log.info(f"{remote_i+1:,} prefixes bound from remote repository.") + else: + log.info("No remote prefix declarations found.") + for f in (Path(__file__).parent.parent / "reference_data/prefixes").glob("*.ttl"): g = Graph().parse(f, format="turtle") - for i, (s, prefix) in enumerate( - g.subject_objects( - predicate=URIRef("http://purl.org/vocab/vann/preferredNamespacePrefix") - ) - ): - namespace = g.value( - s, URIRef("http://purl.org/vocab/vann/preferredNamespaceUri") - ) - prefix_graph.bind(str(prefix), namespace) - - # prefix_graph.bind(str(subject_objects[1]), subject_objects[0]) - log.info(f"{i+1:,} prefixes bound from file {f.name}") - log.info("Prefixes from local files added to prefix graph") + local_i = await _add_prefixes_from_graph(g) + log.info(f"{local_i+1:,} prefixes bound from file {f.name}") if settings.disable_prefix_generation: log.info("DISABLE_PREFIX_GENERATION set to false. Skipping prefix generation.") @@ -119,6 +120,8 @@ async def add_prefixes_to_prefix_graph(repo: Repo): _, rows = await repo.send_queries([], [(None, query)]) iris = [tup["iri"]["value"] for tup in rows[0][1]] + len_iris = len(iris) + log.info(f"Generating prefixes for {len_iris} IRIs.") skipped_count = 0 skipped = [] for iri in iris: @@ -135,6 +138,20 @@ async def add_prefixes_to_prefix_graph(repo: Repo): log.info(f"Skipped IRI {skipped_iri}") +async def _add_prefixes_from_graph(g): + i = 0 + for i, (s, prefix) in enumerate( + g.subject_objects( + predicate=URIRef("http://purl.org/vocab/vann/preferredNamespacePrefix") + ) + ): + namespace = g.value( + s, URIRef("http://purl.org/vocab/vann/preferredNamespaceUri") + ) + prefix_graph.bind(str(prefix), namespace) + return i + + async def create_endpoints_graph(repo) -> Graph: flavours = ["CatPrez", "SpacePrez", "VocPrez"] added_anything = False diff --git a/tests/data/prefixes/data_using_prefixes.ttl b/tests/data/prefixes/data_using_prefixes.ttl new file mode 100644 index 00000000..0d43b5d0 --- /dev/null +++ b/tests/data/prefixes/data_using_prefixes.ttl @@ -0,0 +1,11 @@ +PREFIX dcat: +PREFIX dcterms: +PREFIX ex: +PREFIX rdf: +PREFIX rdfs: + + a dcat:Catalog ; + rdfs:label "A Catalog with prefixed david" ; + dcterms:hasPart ex:DCATResource ; + ex:property "some property" ; +. \ No newline at end of file diff --git a/tests/data/prefixes/remote_prefixes.ttl b/tests/data/prefixes/remote_prefixes.ttl new file mode 100644 index 00000000..cad8bbac --- /dev/null +++ b/tests/data/prefixes/remote_prefixes.ttl @@ -0,0 +1,9 @@ +PREFIX vann: +PREFIX ldgovau: +PREFIX gnaf: +PREFIX addr: + + +[ vann:preferredNamespacePrefix "davo" ; +vann:preferredNamespaceUri ; +] . \ No newline at end of file diff --git a/tests/test_remote_prefixes.py b/tests/test_remote_prefixes.py new file mode 100644 index 00000000..4357f001 --- /dev/null +++ b/tests/test_remote_prefixes.py @@ -0,0 +1,57 @@ +from pathlib import Path + +import pytest +from fastapi.testclient import TestClient +from pyoxigraph.pyoxigraph import Store +from rdflib import Graph, URIRef +from rdflib.namespace import RDF, DCAT + +from prez.app import assemble_app +from prez.dependencies import get_repo +from prez.sparql.methods import Repo, PyoxigraphRepo + + +@pytest.fixture(scope="session") +def test_store() -> Store: + # Create a new pyoxigraph Store + store = Store() + + for file in Path(__file__).parent.glob("../tests/data/prefixes/*.ttl"): + store.load(file.read_bytes(), "text/turtle") + + return store + + +@pytest.fixture(scope="session") +def test_repo(test_store: Store) -> Repo: + # Create a PyoxigraphQuerySender using the test_store + return PyoxigraphRepo(test_store) + + +@pytest.fixture(scope="session") +def client(test_repo: Repo) -> TestClient: + # Override the dependency to use the test_repo + def override_get_repo(): + return test_repo + + app = assemble_app() + + app.dependency_overrides[get_repo] = override_get_repo + + with TestClient(app) as c: + yield c + + # Remove the override to ensure subsequent tests are unaffected + app.dependency_overrides.clear() + + +@pytest.mark.xfail( + reason="Dependency overrides not configured correctly. Test passes when manually tested using Fuseki" +) +def test_catalog_link(client): + # get link for first catalog + r = client.get("/c/catalogs") + g = Graph().parse(data=r.text) + member_uri = g.value(None, RDF.type, DCAT.Catalog) + link = str(g.value(member_uri, URIRef(f"https://prez.dev/link", None))) + assert link == "/c/catalogs/davo:bogusCatalogous"