Skip to content

Commit c1f1a14

Browse files
committed
Move Store API to work with identifiers, not graphs
All add/remove methods now raise an Exception if passed a graph. The Graph API works on Graph objects and will pack/unpack as required.
1 parent 661a289 commit c1f1a14

File tree

7 files changed

+76
-70
lines changed

7 files changed

+76
-70
lines changed

rdflib/graph.py

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -389,12 +389,12 @@ def add(self, triple):
389389
"Predicate %s must be an rdflib term" % (p,)
390390
assert isinstance(o, Node), \
391391
"Object %s must be an rdflib term" % (o,)
392-
self.__store.add((s, p, o), self, quoted=False)
392+
self.__store.add((s, p, o), self.identifier, quoted=False)
393393

394394
def addN(self, quads):
395395
"""Add a sequence of triple with context"""
396396

397-
self.__store.addN((s, p, o, c) for s, p, o, c in quads
397+
self.__store.addN((s, p, o, c.identifier) for s, p, o, c in quads
398398
if isinstance(c, Graph)
399399
and c.identifier is self.identifier
400400
and _assertnode(s,p,o)
@@ -406,7 +406,7 @@ def remove(self, triple):
406406
If the triple does not provide a context attribute, removes the triple
407407
from all contexts.
408408
"""
409-
self.__store.remove(triple, context=self)
409+
self.__store.remove(triple, context=self.identifier)
410410

411411
def triples(self, triple):
412412
"""Generator over the triple store
@@ -419,7 +419,7 @@ def triples(self, triple):
419419
for _s, _o in p.eval(self, s, o):
420420
yield (_s, p, _o)
421421
else:
422-
for (s, p, o), cg in self.__store.triples((s, p, o), context=self):
422+
for (s, p, o), cg in self.__store.triples((s, p, o), context=self.identifier):
423423
yield (s, p, o)
424424

425425
@format_doctest_out
@@ -498,7 +498,7 @@ def __len__(self):
498498
If context is specified then the number of triples in the context is
499499
returned instead.
500500
"""
501-
return self.__store.__len__(context=self)
501+
return self.__store.__len__(context=self.identifier)
502502

503503
def __iter__(self):
504504
"""Iterates over all triples in the store"""
@@ -645,7 +645,7 @@ def predicate_objects(self, subject=None):
645645
def triples_choices(self, triple, context=None):
646646
subject, predicate, object_ = triple
647647
for (s, p, o), cg in self.store.triples_choices(
648-
(subject, predicate, object_), context=self):
648+
(subject, predicate, object_), context=self.identifier):
649649
yield (s, p, o)
650650

651651
def value(self, subject=None, predicate=RDF.value, object=None,
@@ -1296,7 +1296,8 @@ def __init__(self, store='default', identifier=None):
12961296
self.context_aware = True
12971297
self.default_union = True # Conjunctive!
12981298
self.default_context = Graph(store=self.store,
1299-
identifier=identifier or BNode())
1299+
identifier=self.identifier)
1300+
13001301

13011302
def __str__(self):
13021303
pattern = ("[a rdflib:ConjunctiveGraph;rdflib:storage "
@@ -1309,13 +1310,12 @@ def _spoc(self, triple_or_quad, default=False):
13091310
either triples or quads
13101311
"""
13111312
if triple_or_quad is None:
1312-
return (None, None, None, self.default_context if default else None)
1313+
return (None, None, None, self.identifier if default else None)
13131314
if len(triple_or_quad) == 3:
1314-
c = self.default_context if default else None
1315+
c = self.identifier if default else None
13151316
(s, p, o) = triple_or_quad
13161317
elif len(triple_or_quad) == 4:
13171318
(s, p, o, c) = triple_or_quad
1318-
c = self._graph(c)
13191319
return s,p,o,c
13201320

13211321

@@ -1339,7 +1339,9 @@ def add(self, triple_or_quad):
13391339

13401340
_assertnode(s,p,o)
13411341

1342-
self.store.add((s, p, o), context=c, quoted=False)
1342+
self.store.add((s, p, o),
1343+
context=c.identifier if isinstance(c, Graph) else c,
1344+
quoted=False)
13431345

13441346
def _graph(self, c):
13451347
if c is None: return None
@@ -1353,8 +1355,9 @@ def addN(self, quads):
13531355
"""Add a sequence of triples with context"""
13541356

13551357
self.store.addN(
1356-
(s, p, o, self._graph(c)) for s, p, o, c in quads if
1357-
_assertnode(s, p, o)
1358+
(s, p, o,
1359+
c.identifier if isinstance(c, Graph) else c)
1360+
for s, p, o, c in quads if _assertnode(s, p, o)
13581361
)
13591362

13601363
def remove(self, triple_or_quad):
@@ -1368,7 +1371,8 @@ def remove(self, triple_or_quad):
13681371
"""
13691372
s,p,o,c = self._spoc(triple_or_quad)
13701373

1371-
self.store.remove((s, p, o), context=c)
1374+
self.store.remove((s, p, o),
1375+
context=c.identifier if isinstance(c, Graph) else c)
13721376

13731377
def triples(self, triple_or_quad, context=None):
13741378
"""
@@ -1380,14 +1384,14 @@ def triples(self, triple_or_quad, context=None):
13801384
"""
13811385

13821386
s,p,o,c = self._spoc(triple_or_quad)
1383-
context = self._graph(context or c)
1387+
context = context or c
13841388

13851389
if self.default_union:
1386-
if context==self.default_context:
1390+
if context == self.identifier:
13871391
context = None
13881392
else:
13891393
if context is None:
1390-
context = self.default_context
1394+
context = self.identifier
13911395

13921396
if isinstance(p, Path):
13931397
if context is None:
@@ -1404,18 +1408,19 @@ def quads(self, triple_or_quad=None):
14041408

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

1407-
for (s, p, o), cg in self.store.triples((s, p, o), context=c):
1411+
for (s, p, o), cg in self.store.triples((s, p, o),
1412+
context=c if isinstance(c, Graph) else c ):
14081413
for ctx in cg:
1409-
yield s, p, o, ctx
1414+
yield s, p, o, self._graph(ctx)
14101415

14111416
def triples_choices(self, triple, context=None):
14121417
"""Iterate over all the triples in the entire conjunctive graph"""
14131418
s, p, o = triple
14141419
if context is None:
14151420
if not self.default_union:
1416-
context=self.default_context
1421+
context=self.identifier
14171422
else:
1418-
context = self._graph(context)
1423+
if isinstance(context, Graph): context = context.identifier
14191424

14201425
for (s1, p1, o1), cg in self.store.triples_choices((s, p, o),
14211426
context=context):
@@ -1432,10 +1437,7 @@ def contexts(self, triple=None):
14321437
"""
14331438
for context in self.store.contexts(triple):
14341439
if isinstance(context, Graph):
1435-
# TODO: One of these should never happen and probably
1436-
# should raise an exception rather than smoothing over
1437-
# the weirdness - see #225
1438-
yield context
1440+
raise Exception("Got graph object as context, not Identifier!")
14391441
else:
14401442
yield self.get_context(context)
14411443

@@ -1449,7 +1451,8 @@ def get_context(self, identifier, quoted=False):
14491451

14501452
def remove_context(self, context):
14511453
"""Removes the given context from the graph"""
1452-
self.store.remove((None, None, None), context)
1454+
self.store.remove((None, None, None),
1455+
context.identifier if isinstance(context, Graph) else context)
14531456

14541457
def context_id(self, uri, context_id=None):
14551458
"""URI#context"""
@@ -1600,17 +1603,20 @@ def __init__(self, store='default', default_union=False):
16001603

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

16051607
self.default_union = default_union
16061608

1609+
def add(self, triple_or_quad):
1610+
if len(triple_or_quad)==4: super(Dataset, self).add(triple_or_quad)
1611+
else: super(Dataset, self).add(triple_or_quad+(DATASET_DEFAULT_GRAPH_ID,))
16071612

16081613
def __str__(self):
16091614
pattern = ("[a rdflib:Dataset;rdflib:storage "
16101615
"[a rdflib:Store;rdfs:label '%s']]")
16111616
return pattern % self.store.__class__.__name__
16121617

16131618
def graph(self, identifier=None):
1619+
if isinstance(identifier, Graph): identifier = identifier.identifier
16141620
if identifier is None:
16151621
from rdflib.term import rdflib_skolem_genid
16161622
self.bind(
@@ -1620,7 +1626,7 @@ def graph(self, identifier=None):
16201626

16211627
g = self._graph(identifier)
16221628

1623-
self.store.add_graph(g)
1629+
self.store.add_graph(identifier)
16241630
return g
16251631

16261632
def parse(self, source=None, publicID=None, format="xml",
@@ -1634,14 +1640,14 @@ def add_graph(self, g):
16341640
return self.graph(g)
16351641

16361642
def remove_graph(self, g):
1637-
if not isinstance(g, Graph):
1638-
g = self.get_context(g)
1643+
if isinstance(g, Graph):
1644+
g = g.identifier
16391645

16401646
self.store.remove_graph(g)
1641-
if g is None or g == self.default_context:
1647+
if g is None or g == DATASET_DEFAULT_GRAPH_ID:
16421648
# default graph cannot be removed
16431649
# only triples deleted, so add it back in
1644-
self.store.add_graph(self.default_context)
1650+
self.store.add_graph(DATASET_DEFAULT_GRAPH_ID)
16451651

16461652
def contexts(self, triple=None):
16471653
default = False
@@ -1655,7 +1661,7 @@ def contexts(self, triple=None):
16551661

16561662
def quads(self, quad):
16571663
for s, p, o, c in super(Dataset, self).quads(quad):
1658-
if c.identifier==self.default_context:
1664+
if c.identifier == DATASET_DEFAULT_GRAPH_ID:
16591665
yield (s, p, o, None)
16601666
else:
16611667
yield (s, p, o, c.identifier)
@@ -1680,13 +1686,13 @@ def add(self, triple):
16801686
assert isinstance(o, Node), \
16811687
"Object %s must be an rdflib term" % (o,)
16821688

1683-
self.store.add((s, p, o), self, quoted=True)
1689+
self.store.add((s, p, o), self.identifier, quoted=True)
16841690

16851691
def addN(self, quads):
16861692
"""Add a sequence of triple with context"""
16871693

16881694
self.store.addN(
1689-
(s, p, o, c) for s, p, o, c in quads
1695+
(s, p, o, c.identifier) for s, p, o, c in quads
16901696
if isinstance(c, QuotedGraph)
16911697
and c.identifier is self.identifier
16921698
and _assertnode(s, p, o)

rdflib/plugins/parsers/notation3.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1900,7 +1900,7 @@ def parse(self, source, graph, encoding="utf-8"):
19001900
assert graph.store.context_aware # is this implied by formula_aware
19011901
assert graph.store.formula_aware
19021902

1903-
conj_graph = ConjunctiveGraph(store=graph.store)
1903+
conj_graph = ConjunctiveGraph(identifier=graph.identifier, store=graph.store)
19041904
conj_graph.default_context = graph # TODO: CG __init__ should have a
19051905
# default_context arg
19061906
# TODO: update N3Processor so that it can use conj_graph as the sink

rdflib/plugins/sparql/update.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def evalDrop(ctx, u):
7070
"""
7171
if ctx.dataset.store.graph_aware:
7272
for g in _graphAll(ctx, u.graphiri):
73-
ctx.dataset.store.remove_graph(g)
73+
ctx.dataset.remove_graph(g)
7474
else:
7575
evalClear(ctx, u)
7676

@@ -227,7 +227,7 @@ def evalMove(ctx, u):
227227
dstg += srcg
228228

229229
if ctx.dataset.store.graph_aware:
230-
ctx.dataset.store.remove_graph(srcg)
230+
ctx.dataset.remove_graph(srcg)
231231
else:
232232
srcg.remove((None, None, None))
233233

rdflib/plugins/stores/auditable.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ def add(self, triple, context, quoted=False):
5353
lock = destructiveOpLocks['add']
5454
lock = lock if lock else threading.RLock()
5555
with lock:
56-
context = context.__class__(self.store, context.identifier) if context is not None else None
57-
ctxId = context.identifier if context is not None else None
56+
ctxId = context if context is not None else None
5857
if list(self.store.triples(triple, context)):
5958
return # triple already in store, do nothing
6059
self.reverseOps.append((s, p, o, ctxId, 'remove'))
@@ -71,21 +70,20 @@ def remove(self, spo, context=None):
7170
with lock:
7271
# Need to determine which quads will be removed if any term is a
7372
# wildcard
74-
context = context.__class__(self.store, context.identifier) if context is not None else None
75-
ctxId = context.identifier if context is not None else None
73+
ctxId = context if context is not None else None
7674
if None in [subject, predicate, object_, context]:
7775
if ctxId:
78-
for s, p, o in context.triples((subject, predicate, object_)):
76+
for (s, p, o), cg in self.store.triples((subject, predicate, object_), context):
7977
try:
8078
self.reverseOps.remove((s, p, o, ctxId, 'remove'))
8179
except ValueError:
8280
self.reverseOps.append((s, p, o, ctxId, 'add'))
8381
else:
8482
for s, p, o, ctx in ConjunctiveGraph(self.store).quads((subject, predicate, object_)):
8583
try:
86-
self.reverseOps.remove((s, p, o, ctx.identifier, 'remove'))
84+
self.reverseOps.remove((s, p, o, ctx, 'remove'))
8785
except ValueError:
88-
self.reverseOps.append((s, p, o, ctx.identifier, 'add'))
86+
self.reverseOps.append((s, p, o, ctx, 'add'))
8987
else:
9088
if not list(self.triples((subject, predicate, object_), context)):
9189
return # triple not present in store, do nothing
@@ -97,12 +95,10 @@ def remove(self, spo, context=None):
9795

9896
def triples(self, triple, context=None):
9997
(su, pr, ob) = triple
100-
context = context.__class__(self.store, context.identifier) if context is not None else None
10198
for (s, p, o), cg in self.store.triples((su, pr, ob), context):
10299
yield (s, p, o), cg
103100

104101
def __len__(self, context=None):
105-
context = context.__class__(self.store, context.identifier) if context is not None else None
106102
return self.store.__len__(context)
107103

108104
def contexts(self, triple=None):
@@ -131,9 +127,9 @@ def rollback(self):
131127
for subject, predicate, obj, context, op in self.reverseOps:
132128
if op == 'add':
133129
self.store.add(
134-
(subject, predicate, obj), Graph(self.store, context))
130+
(subject, predicate, obj), context)
135131
else:
136132
self.store.remove(
137-
(subject, predicate, obj), Graph(self.store, context))
133+
(subject, predicate, obj), context)
138134

139135
self.reverseOps = []

rdflib/store.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
UNKNOWN = None
3737

3838
from rdflib.events import Dispatcher, Event
39+
from rdflib.term import URIRef, BNode, Literal, Variable, Statement, Identifier
40+
41+
3942

4043
from .py3compat import cPickle
4144
from .py3compat import BytesIO
@@ -147,18 +150,13 @@ def __init__(self, configuration=None, identifier=None):
147150

148151
def __get_node_pickler(self):
149152
if self.__node_pickler is None:
150-
from rdflib.term import URIRef
151-
from rdflib.term import BNode
152-
from rdflib.term import Literal
153-
from rdflib.graph import Graph, QuotedGraph
154-
from rdflib.term import Variable
155-
from rdflib.term import Statement
156153
self.__node_pickler = np = NodePickler()
154+
from rdflib.graph import QuotedGraph # here to avoid circular import
155+
157156
np.register(self, "S")
158157
np.register(URIRef, "U")
159158
np.register(BNode, "B")
160159
np.register(Literal, "L")
161-
np.register(Graph, "G")
162160
np.register(QuotedGraph, "Q")
163161
np.register(Variable, "V")
164162
np.register(Statement, "s")
@@ -211,6 +209,8 @@ def add(self, triple, context, quoted=False):
211209
be an error for the quoted argument to be True when the store is not
212210
formula-aware.
213211
"""
212+
if not isinstance(context, Identifier): raise Exception("Trying to add to a context that isn't an identifier: %s"%context)
213+
214214
self.dispatcher.dispatch(
215215
TripleAddedEvent(
216216
triple=triple, context=context))
@@ -229,6 +229,8 @@ def addN(self, quads):
229229

230230
def remove(self, triple, context=None):
231231
""" Remove the set of triples matching the pattern from the store """
232+
if context is not None and not isinstance(context, Identifier): raise Exception("Trying to remove from a context that isn't an identifier: %s"%context)
233+
232234
self.dispatcher.dispatch(
233235
TripleRemovedEvent(
234236
triple=triple, context=context))

0 commit comments

Comments
 (0)