Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

id-as-context copied over from PR 409 #2438

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 52 additions & 38 deletions rdflib/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,14 +530,14 @@ def add(self: _GraphT, triple: "_TripleType") -> _GraphT:
assert isinstance(s, Node), "Subject %s must be an rdflib term" % (s,)
assert isinstance(p, Node), "Predicate %s must be an rdflib term" % (p,)
assert isinstance(o, Node), "Object %s must be an rdflib term" % (o,)
self.__store.add((s, p, o), self, quoted=False)
self.__store.add((s, p, o), self.identifier, quoted=False)
return self

def addN(self: _GraphT, quads: Iterable["_QuadType"]) -> _GraphT: # noqa: N802
"""Add a sequence of triple with context"""

self.__store.addN(
(s, p, o, c)
(s, p, o, c.identifier)
for s, p, o, c in quads
if isinstance(c, Graph)
and c.identifier is self.identifier
Expand All @@ -551,7 +551,7 @@ def remove(self: _GraphT, triple: "_TriplePatternType") -> _GraphT:
If the triple does not provide a context attribute, removes the triple
from all contexts.
"""
self.__store.remove(triple, context=self)
self.__store.remove(triple, context=self.identifier)
return self

@overload
Expand Down Expand Up @@ -589,7 +589,9 @@ def triples(
for _s, _o in p.eval(self, s, o):
yield _s, p, _o
else:
for (_s, _p, _o), cg in self.__store.triples((s, p, o), context=self):
for (_s, _p, _o), cg in self.__store.triples(
(s, p, o), context=self.identifier
):
yield _s, _p, _o

def __getitem__(self, item):
Expand Down Expand Up @@ -669,7 +671,7 @@ def __len__(self) -> int:
returned instead.
"""
# type error: Unexpected keyword argument "context" for "__len__" of "Store"
return self.__store.__len__(context=self) # type: ignore[call-arg]
return self.__store.__len__(context=self.identifier) # type: ignore[call-arg]

def __iter__(self) -> Generator["_TripleType", None, None]:
"""Iterates over all triples in the store"""
Expand Down Expand Up @@ -947,7 +949,7 @@ def triples_choices(
# type error: Argument 1 to "triples_choices" of "Store" has incompatible type "Tuple[Union[List[Node], Node], Union[Node, List[Node]], Union[Node, List[Node]]]"; expected "Union[Tuple[List[Node], Node, Node], Tuple[Node, List[Node], Node], Tuple[Node, Node, List[Node]]]"
# type error note: unpacking discards type info
for (s, p, o), cg in self.store.triples_choices(
(subject, predicate, object_), context=self # type: ignore[arg-type]
(subject, predicate, object_), context=self.identifier # type: ignore[arg-type]
):
yield s, p, o

Expand Down Expand Up @@ -1904,7 +1906,7 @@ def __init__(
self.context_aware = True
self.default_union = True # Conjunctive!
self.default_context: _ContextType = Graph(
store=self.store, identifier=identifier or BNode(), base=default_graph_base
store=self.store, identifier=self.identifier, base=default_graph_base
)

def __str__(self) -> str:
Expand Down Expand Up @@ -1972,15 +1974,14 @@ def _spoc(
either triples or quads
"""
if triple_or_quad is None:
return (None, None, None, self.default_context if default else None)
return (None, None, None, self.identifier if default else None)
if len(triple_or_quad) == 3:
c = self.default_context if default else None
c = self.identifier if default else None
# type error: Too many values to unpack (3 expected, 4 provided)
(s, p, o) = triple_or_quad # type: ignore[misc]
elif len(triple_or_quad) == 4:
# type error: Need more than 3 values to unpack (4 expected)
(s, p, o, c) = triple_or_quad # type: ignore[misc]
c = self._graph(c)
return s, p, o, c

def __contains__(self, triple_or_quad: _TripleOrQuadSelectorType) -> bool:
Expand All @@ -2005,7 +2006,9 @@ def add(
_assertnode(s, p, o)

# type error: Argument "context" to "add" of "Store" has incompatible type "Optional[Graph]"; expected "Graph"
self.store.add((s, p, o), context=c, quoted=False) # type: ignore[arg-type]
self.store.add(
(s, p, o), context=c.identifier if isinstance(c, Graph) else c, quoted=False
) # type: ignore[arg-type]
return self

@overload
Expand All @@ -2032,7 +2035,9 @@ def addN( # noqa: N802
"""Add a sequence of triples with context"""

self.store.addN(
(s, p, o, self._graph(c)) for s, p, o, c in quads if _assertnode(s, p, o)
(s, p, o, c.identifier if isinstance(c, Graph) else c)
for s, p, o, c in quads
if _assertnode(s, p, o)
)
return self

Expand All @@ -2048,7 +2053,9 @@ def remove(self: _ConjunctiveGraphT, triple_or_quad: _TripleOrOptionalQuadType)
"""
s, p, o, c = self._spoc(triple_or_quad)

self.store.remove((s, p, o), context=c)
self.store.remove(
(s, p, o), context=c.identifier if isinstance(c, Graph) else c
)
return self

@overload
Expand Down Expand Up @@ -2089,14 +2096,14 @@ def triples(
"""

s, p, o, c = self._spoc(triple_or_quad)
context = self._graph(context or c)
context = context or c

if self.default_union:
if context == self.default_context:
if context == self.identifier:
context = None
else:
if context is None:
context = self.default_context
context = self.identifier

if isinstance(p, Path):
if context is None:
Expand All @@ -2115,9 +2122,11 @@ def quads(

s, p, o, c = self._spoc(triple_or_quad)

for (s, p, o), cg in self.store.triples((s, p, o), context=c):
for (s, p, o), cg in self.store.triples(
(s, p, o), context=c if isinstance(c, Graph) else c
):
for ctx in cg:
yield s, p, o, ctx
yield s, p, o, self._graph(ctx)

def triples_choices(
self,
Expand All @@ -2132,9 +2141,10 @@ def triples_choices(
s, p, o = triple
if context is None:
if not self.default_union:
context = self.default_context
context = self.identifier
else:
context = self._graph(context)
if isinstance(context, Graph):
context = context.identifier
# type error: Argument 1 to "triples_choices" of "Store" has incompatible type "Tuple[Union[List[Node], Node], Union[Node, List[Node]], Union[Node, List[Node]]]"; expected "Union[Tuple[List[Node], Node, Node], Tuple[Node, List[Node], Node], Tuple[Node, Node, List[Node]]]"
# type error note: unpacking discards type info
for (s1, p1, o1), cg in self.store.triples_choices((s, p, o), context=context): # type: ignore[arg-type]
Expand All @@ -2153,10 +2163,7 @@ def contexts(
"""
for context in self.store.contexts(triple):
if isinstance(context, Graph):
# TODO: One of these should never happen and probably
# should raise an exception rather than smoothing over
# the weirdness - see #225
yield context
raise Exception("Got graph object as context, not Identifier!")
else:
# type error: Statement is unreachable
yield self.get_context(context) # type: ignore[unreachable]
Expand Down Expand Up @@ -2184,7 +2191,10 @@ def get_context(

def remove_context(self, context: "_ContextType") -> None:
"""Removes the given context from the graph"""
self.store.remove((None, None, None), context)
self.store.remove(
(None, None, None),
context.identifier if isinstance(context, Graph) else context,
)

def context_id(self, uri: str, context_id: Optional[str] = None) -> URIRef:
"""URI#context"""
Expand Down Expand Up @@ -2403,14 +2413,16 @@ def __init__(

if not self.store.graph_aware:
raise Exception("DataSet must be backed by a graph-aware store!")
self.default_context = Graph(
store=self.store,
identifier=DATASET_DEFAULT_GRAPH_ID,
base=default_graph_base,
)

self.default_union = default_union

def add(self, triple_or_quad):
if len(triple_or_quad) == 4:
res = super(Dataset, self).add(triple_or_quad)
else:
res = super(Dataset, self).add(triple_or_quad + (DATASET_DEFAULT_GRAPH_ID,))
return res

def __str__(self) -> str:
pattern = (
"[a rdflib:Dataset;rdflib:storage " "[a rdflib:Store;rdfs:label '%s']]"
Expand All @@ -2437,6 +2449,8 @@ def graph(
identifier: Optional[Union[_ContextIdentifierType, _ContextType, str]] = None,
base: Optional[str] = None,
) -> Graph:
if isinstance(identifier, Graph):
identifier = identifier.identifier
if identifier is None:
from rdflib.term import _SKOLEM_DEFAULT_AUTHORITY, rdflib_skolem_genid

Expand All @@ -2450,7 +2464,7 @@ def graph(
g = self._graph(identifier)
g.base = base

self.store.add_graph(g)
self.store.add_graph(identifier)
return g

def parse(
Expand Down Expand Up @@ -2512,14 +2526,14 @@ def add_graph(
def remove_graph(
self: _DatasetT, g: Optional[Union[_ContextIdentifierType, _ContextType, str]]
) -> _DatasetT:
if not isinstance(g, Graph):
g = self.get_context(g)
if isinstance(g, Graph):
g = g.identifier

self.store.remove_graph(g)
if g is None or g == self.default_context:
if g is None or g == DATASET_DEFAULT_GRAPH_ID:
# default graph cannot be removed
# only triples deleted, so add it back in
self.store.add_graph(self.default_context)
self.store.add_graph(DATASET_DEFAULT_GRAPH_ID)
return self

def contexts(
Expand All @@ -2540,7 +2554,7 @@ def quads( # type: ignore[override]
) -> Generator[_OptionalIdentifiedQuadType, None, None]:
for s, p, o, c in super(Dataset, self).quads(quad):
# type error: Item "None" of "Optional[Graph]" has no attribute "identifier"
if c.identifier == self.default_context: # type: ignore[union-attr]
if c.identifier == DATASET_DEFAULT_GRAPH_ID: # type: ignore[union-attr]
yield s, p, o, None
else:
# type error: Item "None" of "Optional[Graph]" has no attribute "identifier" [union-attr]
Expand Down Expand Up @@ -2576,14 +2590,14 @@ def add(self: _GraphT, triple: "_TripleType") -> _GraphT:
assert isinstance(p, Node), "Predicate %s must be an rdflib term" % (p,)
assert isinstance(o, Node), "Object %s must be an rdflib term" % (o,)

self.store.add((s, p, o), self, quoted=True)
self.store.add((s, p, o), self.identifier, quoted=True)
return self

def addN(self: _GraphT, quads: Iterable["_QuadType"]) -> _GraphT: # noqa: N802
"""Add a sequence of triple with context"""

self.store.addN(
(s, p, o, c)
(s, p, o, c.identifier)
for s, p, o, c in quads
if isinstance(c, QuotedGraph)
and c.identifier is self.identifier
Expand Down
2 changes: 1 addition & 1 deletion rdflib/plugins/parsers/notation3.py
Original file line number Diff line number Diff line change
Expand Up @@ -2049,7 +2049,7 @@ def parse( # type: ignore[override]
elif not fa:
raise ParserError("Cannot parse N3 into non-formula-aware store.")

conj_graph = ConjunctiveGraph(store=graph.store)
conj_graph = ConjunctiveGraph(identifier=graph.identifier, store=graph.store)
conj_graph.default_context = graph # TODO: CG __init__ should have a
# default_context arg
# TODO: update N3Processor so that it can use conj_graph as the sink
Expand Down
4 changes: 2 additions & 2 deletions rdflib/plugins/sparql/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def evalDrop(ctx: QueryContext, u: CompValue) -> None:
"""
if ctx.dataset.store.graph_aware:
for g in _graphAll(ctx, u.graphiri):
ctx.dataset.store.remove_graph(g)
ctx.dataset.remove_graph(g)
else:
evalClear(ctx, u)

Expand Down Expand Up @@ -248,7 +248,7 @@ def evalMove(ctx: QueryContext, u: CompValue) -> None:

if ctx.dataset.store.graph_aware:
# type error: Argument 1 to "remove_graph" of "Store" has incompatible type "Optional[Graph]"; expected "Graph"
ctx.dataset.store.remove_graph(srcg) # type: ignore[arg-type]
ctx.dataset.remove_graph(srcg) # type: ignore[arg-type]
else:
# type error: Item "None" of "Optional[Graph]" has no attribute "remove"
srcg.remove((None, None, None)) # type: ignore[union-attr]
Expand Down
36 changes: 7 additions & 29 deletions rdflib/plugins/stores/auditable.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,7 @@ def add(
lock = destructiveOpLocks["add"]
lock = lock if lock else threading.RLock()
with lock:
context = (
context.__class__(self.store, context.identifier)
if context is not None
else None
)
ctxId = context.identifier if context is not None else None # noqa: N806
ctxId = context if context is not None else None # noqa: N806
if list(self.store.triples(triple, context)):
return # triple already in store, do nothing
self.reverseOps.append((s, p, o, ctxId, "remove"))
Expand All @@ -103,16 +98,11 @@ def remove(
with lock:
# Need to determine which quads will be removed if any term is a
# wildcard
context = (
context.__class__(self.store, context.identifier)
if context is not None
else None
)
ctxId = context.identifier if context is not None else None # noqa: N806
ctxId = context if context is not None else None # noqa: N806
if None in [subject, predicate, object_, context]:
if ctxId:
# type error: Item "None" of "Optional[Graph]" has no attribute "triples"
for s, p, o in context.triples((subject, predicate, object_)): # type: ignore[union-attr]
for (s, p, o), cg in self.store.triples((subject, predicate, object_), context):
try:
self.reverseOps.remove((s, p, o, ctxId, "remove"))
except ValueError:
Expand All @@ -123,10 +113,10 @@ def remove(
):
try:
# type error: Item "None" of "Optional[Graph]" has no attribute "identifier"
self.reverseOps.remove((s, p, o, ctx.identifier, "remove")) # type: ignore[union-attr]
self.reverseOps.remove((s, p, o, ctx, "remove")) # type: ignore[union-attr]
except ValueError:
# type error: Item "None" of "Optional[Graph]" has no attribute "identifier"
self.reverseOps.append((s, p, o, ctx.identifier, "add")) # type: ignore[union-attr]
self.reverseOps.append((s, p, o, ctx, "add")) # type: ignore[union-attr]
else:
if not list(self.triples((subject, predicate, object_), context)):
return # triple not present in store, do nothing
Expand All @@ -142,20 +132,10 @@ def triples(
self, triple: "_TriplePatternType", context: Optional["_ContextType"] = None
) -> Iterator[Tuple["_TripleType", Iterator[Optional["_ContextType"]]]]:
(su, pr, ob) = triple
context = (
context.__class__(self.store, context.identifier)
if context is not None
else None
)
for (s, p, o), cg in self.store.triples((su, pr, ob), context):
yield (s, p, o), cg

def __len__(self, context: Optional["_ContextType"] = None):
context = (
context.__class__(self.store, context.identifier)
if context is not None
else None
)
return self.store.__len__(context)

def contexts(
Expand Down Expand Up @@ -187,11 +167,9 @@ def rollback(self) -> None:
if op == "add":
# type error: Argument 2 to "Graph" has incompatible type "Optional[Node]"; expected "Union[IdentifiedNode, str, None]"
self.store.add(
(subject, predicate, obj), Graph(self.store, context) # type: ignore[arg-type]
)
(subject, predicate, obj), context) # type: ignore[arg-type]
else:
self.store.remove(
(subject, predicate, obj), Graph(self.store, context)
)
(subject, predicate, obj), context)

self.reverseOps = []
4 changes: 2 additions & 2 deletions rdflib/plugins/stores/sparqlstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ def triples( # type: ignore[override]
result = self._query(
query,
# type error: Item "None" of "Optional[Graph]" has no attribute "identifier"
default_graph=context.identifier if self._is_contextual(context) else None, # type: ignore[union-attr]
default_graph=context if self._is_contextual(context) else None, # type: ignore[union-attr]
)

if vars:
Expand Down Expand Up @@ -485,7 +485,7 @@ def _is_contextual(self, graph: Optional[Union["Graph", "str"]]) -> bool:
if isinstance(graph, str):
return graph != "__UNION__"
else:
return graph.identifier != DATASET_DEFAULT_GRAPH_ID
return graph != DATASET_DEFAULT_GRAPH_ID

def subjects(
self,
Expand Down
Loading