Skip to content

Commit

Permalink
feat: add optional target_graph argument to Graph.cbd and use it …
Browse files Browse the repository at this point in the history
…for DESCRIBE queries (#2322)

Add optional keyword only `target_graph` argument to `rdflib.graph.Graph.cbd` and use this new argument in `evalDescribeQuery`.

This makes it possible to compute a concise bounded description without creating a new graph to hold the result, and also without potentially having to copy it to another final graph.

Co-authored-by: Iwan Aucamp <aucampia@gmail.com>
  • Loading branch information
mgberg and aucampia committed Apr 11, 2023
1 parent 5c3c78a commit 81d13d4
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 5 deletions.
12 changes: 9 additions & 3 deletions rdflib/graph.py
Expand Up @@ -1814,7 +1814,9 @@ def do_de_skolemize2(t: _TripleType) -> _TripleType:

return retval

def cbd(self, resource: _SubjectType) -> Graph:
def cbd(
self, resource: _SubjectType, *, target_graph: Optional[Graph] = None
) -> Graph:
"""Retrieves the Concise Bounded Description of a Resource from a Graph
Concise Bounded Description (CBD) is defined in [1] as:
Expand All @@ -1840,10 +1842,14 @@ def cbd(self, resource: _SubjectType) -> Graph:
[1] https://www.w3.org/Submission/CBD/
:param resource: a URIRef object, of the Resource for queried for
:return: a Graph, subgraph of self
:param target_graph: Optionally, a graph to add the CBD to; otherwise, a new graph is created for the CBD
:return: a Graph, subgraph of self if no graph was provided otherwise the provided graph
"""
subgraph = Graph()
if target_graph is None:
subgraph = Graph()
else:
subgraph = target_graph

def add_to_cbd(uri: _SubjectType) -> None:
for s, p, o in self.triples((uri, None, None)):
Expand Down
2 changes: 1 addition & 1 deletion rdflib/plugins/sparql/evaluate.py
Expand Up @@ -630,7 +630,7 @@ def evalDescribeQuery(ctx: QueryContext, query) -> Dict[str, Union[str, Graph]]:
# Get a CBD for all resources identified to describe
for resource in to_describe:
# type error: Item "None" of "Optional[Graph]" has no attribute "cbd"
graph += ctx.graph.cbd(resource) # type: ignore[union-attr]
ctx.graph.cbd(resource, target_graph=graph) # type: ignore[union-attr]

res: Dict[str, Union[str, Graph]] = {}
res["type_"] = "DESCRIBE"
Expand Down
27 changes: 26 additions & 1 deletion test/test_graph/test_graph_cbd.py
Expand Up @@ -4,7 +4,8 @@
import pytest

from rdflib import Graph, Namespace
from rdflib.term import URIRef
from rdflib.namespace import RDF, RDFS
from rdflib.term import Literal, URIRef

EXAMPLE_GRAPH_FILE_PATH = TEST_DATA_DIR / "spec" / "cbd" / "example_graph.rdf"
EXAMPLE_GRAPH_CBD_FILE_PATH = TEST_DATA_DIR / "spec" / "cbd" / "example_graph_cbd.rdf"
Expand Down Expand Up @@ -134,3 +135,27 @@ def test_cbd_example():
assert len(g.cbd(URIRef(query))) == (
21
), "cbd() for aReallyGreatBook should return 21 triples"


def test_cbd_target(rdfs_graph: Graph):
"""
`Graph.cbd` places the Concise Bounded Description in the target graph.
"""

target = Graph()
result = rdfs_graph.cbd(RDFS.Literal, target_graph=target)

expected_result = {
(RDFS.Literal, RDFS.subClassOf, RDFS.Resource),
(RDFS.Literal, RDF.type, RDFS.Class),
(RDFS.Literal, RDFS.label, Literal("Literal")),
(
RDFS.Literal,
RDFS.comment,
Literal("The class of literal values, eg. textual strings and integers."),
),
(RDFS.Literal, RDFS.isDefinedBy, URIRef(f"{RDFS}")),
}

assert result is target
assert expected_result == set(result.triples((None, None, None)))

0 comments on commit 81d13d4

Please sign in to comment.