Skip to content

Commit 81d13d4

Browse files
mgbergaucampia
andauthored
feat: add optional target_graph argument to Graph.cbd and use it 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>
1 parent 5c3c78a commit 81d13d4

File tree

3 files changed

+36
-5
lines changed

3 files changed

+36
-5
lines changed

rdflib/graph.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1814,7 +1814,9 @@ def do_de_skolemize2(t: _TripleType) -> _TripleType:
18141814

18151815
return retval
18161816

1817-
def cbd(self, resource: _SubjectType) -> Graph:
1817+
def cbd(
1818+
self, resource: _SubjectType, *, target_graph: Optional[Graph] = None
1819+
) -> Graph:
18181820
"""Retrieves the Concise Bounded Description of a Resource from a Graph
18191821
18201822
Concise Bounded Description (CBD) is defined in [1] as:
@@ -1840,10 +1842,14 @@ def cbd(self, resource: _SubjectType) -> Graph:
18401842
[1] https://www.w3.org/Submission/CBD/
18411843
18421844
:param resource: a URIRef object, of the Resource for queried for
1843-
:return: a Graph, subgraph of self
1845+
:param target_graph: Optionally, a graph to add the CBD to; otherwise, a new graph is created for the CBD
1846+
:return: a Graph, subgraph of self if no graph was provided otherwise the provided graph
18441847
18451848
"""
1846-
subgraph = Graph()
1849+
if target_graph is None:
1850+
subgraph = Graph()
1851+
else:
1852+
subgraph = target_graph
18471853

18481854
def add_to_cbd(uri: _SubjectType) -> None:
18491855
for s, p, o in self.triples((uri, None, None)):

rdflib/plugins/sparql/evaluate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ def evalDescribeQuery(ctx: QueryContext, query) -> Dict[str, Union[str, Graph]]:
630630
# Get a CBD for all resources identified to describe
631631
for resource in to_describe:
632632
# type error: Item "None" of "Optional[Graph]" has no attribute "cbd"
633-
graph += ctx.graph.cbd(resource) # type: ignore[union-attr]
633+
ctx.graph.cbd(resource, target_graph=graph) # type: ignore[union-attr]
634634

635635
res: Dict[str, Union[str, Graph]] = {}
636636
res["type_"] = "DESCRIBE"

test/test_graph/test_graph_cbd.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
import pytest
55

66
from rdflib import Graph, Namespace
7-
from rdflib.term import URIRef
7+
from rdflib.namespace import RDF, RDFS
8+
from rdflib.term import Literal, URIRef
89

910
EXAMPLE_GRAPH_FILE_PATH = TEST_DATA_DIR / "spec" / "cbd" / "example_graph.rdf"
1011
EXAMPLE_GRAPH_CBD_FILE_PATH = TEST_DATA_DIR / "spec" / "cbd" / "example_graph_cbd.rdf"
@@ -134,3 +135,27 @@ def test_cbd_example():
134135
assert len(g.cbd(URIRef(query))) == (
135136
21
136137
), "cbd() for aReallyGreatBook should return 21 triples"
138+
139+
140+
def test_cbd_target(rdfs_graph: Graph):
141+
"""
142+
`Graph.cbd` places the Concise Bounded Description in the target graph.
143+
"""
144+
145+
target = Graph()
146+
result = rdfs_graph.cbd(RDFS.Literal, target_graph=target)
147+
148+
expected_result = {
149+
(RDFS.Literal, RDFS.subClassOf, RDFS.Resource),
150+
(RDFS.Literal, RDF.type, RDFS.Class),
151+
(RDFS.Literal, RDFS.label, Literal("Literal")),
152+
(
153+
RDFS.Literal,
154+
RDFS.comment,
155+
Literal("The class of literal values, eg. textual strings and integers."),
156+
),
157+
(RDFS.Literal, RDFS.isDefinedBy, URIRef(f"{RDFS}")),
158+
}
159+
160+
assert result is target
161+
assert expected_result == set(result.triples((None, None, None)))

0 commit comments

Comments
 (0)