comparison env/lib/python3.9/site-packages/rdflib/store.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 from __future__ import absolute_import
2 from __future__ import division
3 from __future__ import print_function
4
5 from six import BytesIO
6 from six.moves import cPickle
7 from rdflib.events import Dispatcher, Event
8 """
9 ============
10 rdflib.store
11 ============
12
13 Types of store
14 --------------
15
16 ``Context-aware``: An RDF store capable of storing statements within contexts
17 is considered context-aware. Essentially, such a store is able to partition
18 the RDF model it represents into individual, named, and addressable
19 sub-graphs.
20
21 Relevant Notation3 reference regarding formulae, quoted statements, and such:
22 http://www.w3.org/DesignIssues/Notation3.html
23
24 ``Formula-aware``: An RDF store capable of distinguishing between statements
25 that are asserted and statements that are quoted is considered formula-aware.
26
27 ``Transaction-capable``: capable of providing transactional integrity to the
28 RDF operations performed on it.
29
30 ``Graph-aware``: capable of keeping track of empty graphs.
31
32 ------
33 """
34
35
36 # Constants representing the state of a Store (returned by the open method)
37 VALID_STORE = 1
38 CORRUPTED_STORE = 0
39 NO_STORE = -1
40 UNKNOWN = None
41
42
43 Pickler = cPickle.Pickler
44 Unpickler = cPickle.Unpickler
45 UnpicklingError = cPickle.UnpicklingError
46
47 __all__ = ['StoreCreatedEvent', 'TripleAddedEvent', 'TripleRemovedEvent',
48 'NodePickler', 'Store']
49
50
51 class StoreCreatedEvent(Event):
52 """
53 This event is fired when the Store is created, it has the following
54 attribute:
55
56 - ``configuration``: string used to create the store
57
58 """
59
60
61 class TripleAddedEvent(Event):
62 """
63 This event is fired when a triple is added, it has the following
64 attributes:
65
66 - the ``triple`` added to the graph
67 - the ``context`` of the triple, if any
68 - the ``graph`` to which the triple was added
69 """
70
71
72 class TripleRemovedEvent(Event):
73 """
74 This event is fired when a triple is removed, it has the following
75 attributes:
76
77 - the ``triple`` removed from the graph
78 - the ``context`` of the triple, if any
79 - the ``graph`` from which the triple was removed
80 """
81
82
83 class NodePickler(object):
84 def __init__(self):
85 self._objects = {}
86 self._ids = {}
87 self._get_object = self._objects.__getitem__
88
89 def _get_ids(self, key):
90 try:
91 return self._ids.get(key)
92 except TypeError:
93 return None
94
95 def register(self, object, id):
96 self._objects[id] = object
97 self._ids[object] = id
98
99 def loads(self, s):
100 up = Unpickler(BytesIO(s))
101 up.persistent_load = self._get_object
102 try:
103 return up.load()
104 except KeyError as e:
105 raise UnpicklingError("Could not find Node class for %s" % e)
106
107 def dumps(self, obj, protocol=None, bin=None):
108 src = BytesIO()
109 p = Pickler(src)
110 p.persistent_id = self._get_ids
111 p.dump(obj)
112 return src.getvalue()
113
114 def __getstate__(self):
115 state = self.__dict__.copy()
116 del state['_get_object']
117 state.update({
118 '_ids': tuple(self._ids.items()),
119 '_objects': tuple(self._objects.items())
120 })
121 return state
122
123 def __setstate__(self, state):
124 self.__dict__.update(state)
125 self._ids = dict(self._ids)
126 self._objects = dict(self._objects)
127 self._get_object = self._objects.__getitem__
128
129
130 class Store(object):
131 # Properties
132 context_aware = False
133 formula_aware = False
134 transaction_aware = False
135 graph_aware = False
136
137 def __init__(self, configuration=None, identifier=None):
138 """
139 identifier: URIRef of the Store. Defaults to CWD
140 configuration: string containing infomation open can use to
141 connect to datastore.
142 """
143 self.__node_pickler = None
144 self.dispatcher = Dispatcher()
145 if configuration:
146 self.open(configuration)
147
148 def __get_node_pickler(self):
149 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
156 self.__node_pickler = np = NodePickler()
157 np.register(self, "S")
158 np.register(URIRef, "U")
159 np.register(BNode, "B")
160 np.register(Literal, "L")
161 np.register(Graph, "G")
162 np.register(QuotedGraph, "Q")
163 np.register(Variable, "V")
164 np.register(Statement, "s")
165 return self.__node_pickler
166 node_pickler = property(__get_node_pickler)
167
168 # Database management methods
169 def create(self, configuration):
170 self.dispatcher.dispatch(
171 StoreCreatedEvent(configuration=configuration))
172
173 def open(self, configuration, create=False):
174 """
175 Opens the store specified by the configuration string. If
176 create is True a store will be created if it does not already
177 exist. If create is False and a store does not already exist
178 an exception is raised. An exception is also raised if a store
179 exists, but there is insufficient permissions to open the
180 store. This should return one of:
181 VALID_STORE, CORRUPTED_STORE, or NO_STORE
182 """
183 return UNKNOWN
184
185 def close(self, commit_pending_transaction=False):
186 """
187 This closes the database connection. The commit_pending_transaction
188 parameter specifies whether to commit all pending transactions before
189 closing (if the store is transactional).
190 """
191
192 def destroy(self, configuration):
193 """
194 This destroys the instance of the store identified by the
195 configuration string.
196 """
197
198 def gc(self):
199 """
200 Allows the store to perform any needed garbage collection
201 """
202 pass
203
204 # RDF APIs
205 def add(self, triple, context, quoted=False):
206 """
207 Adds the given statement to a specific context or to the model. The
208 quoted argument is interpreted by formula-aware stores to indicate
209 this statement is quoted/hypothetical It should be an error to not
210 specify a context and have the quoted argument be True. It should also
211 be an error for the quoted argument to be True when the store is not
212 formula-aware.
213 """
214 self.dispatcher.dispatch(
215 TripleAddedEvent(
216 triple=triple, context=context))
217
218 def addN(self, quads):
219 """
220 Adds each item in the list of statements to a specific context. The
221 quoted argument is interpreted by formula-aware stores to indicate this
222 statement is quoted/hypothetical. Note that the default implementation
223 is a redirect to add
224 """
225 for s, p, o, c in quads:
226 assert c is not None, \
227 "Context associated with %s %s %s is None!" % (s, p, o)
228 self.add((s, p, o), c)
229
230 def remove(self, triple, context=None):
231 """ Remove the set of triples matching the pattern from the store """
232 self.dispatcher.dispatch(
233 TripleRemovedEvent(
234 triple=triple, context=context))
235
236 def triples_choices(self, triple, context=None):
237 """
238 A variant of triples that can take a list of terms instead of a single
239 term in any slot. Stores can implement this to optimize the response
240 time from the default 'fallback' implementation, which will iterate
241 over each term in the list and dispatch to triples
242 """
243 subject, predicate, object_ = triple
244 if isinstance(object_, list):
245 assert not isinstance(
246 subject, list), "object_ / subject are both lists"
247 assert not isinstance(
248 predicate, list), "object_ / predicate are both lists"
249 if object_:
250 for obj in object_:
251 for (s1, p1, o1), cg in self.triples(
252 (subject, predicate, obj), context):
253 yield (s1, p1, o1), cg
254 else:
255 for (s1, p1, o1), cg in self.triples(
256 (subject, predicate, None), context):
257 yield (s1, p1, o1), cg
258
259 elif isinstance(subject, list):
260 assert not isinstance(
261 predicate, list), "subject / predicate are both lists"
262 if subject:
263 for subj in subject:
264 for (s1, p1, o1), cg in self.triples(
265 (subj, predicate, object_), context):
266 yield (s1, p1, o1), cg
267 else:
268 for (s1, p1, o1), cg in self.triples(
269 (None, predicate, object_), context):
270 yield (s1, p1, o1), cg
271
272 elif isinstance(predicate, list):
273 assert not isinstance(
274 subject, list), "predicate / subject are both lists"
275 if predicate:
276 for pred in predicate:
277 for (s1, p1, o1), cg in self.triples(
278 (subject, pred, object_), context):
279 yield (s1, p1, o1), cg
280 else:
281 for (s1, p1, o1), cg in self.triples(
282 (subject, None, object_), context):
283 yield (s1, p1, o1), cg
284
285 def triples(self, triple_pattern, context=None):
286 """
287 A generator over all the triples matching the pattern. Pattern can
288 include any objects for used for comparing against nodes in the store,
289 for example, REGEXTerm, URIRef, Literal, BNode, Variable, Graph,
290 QuotedGraph, Date? DateRange?
291
292 :param context: A conjunctive query can be indicated by either
293 providing a value of None, or a specific context can be
294 queries by passing a Graph instance (if store is context aware).
295 """
296 subject, predicate, object = triple_pattern
297
298 # variants of triples will be done if / when optimization is needed
299
300 def __len__(self, context=None):
301 """
302 Number of statements in the store. This should only account for non-
303 quoted (asserted) statements if the context is not specified,
304 otherwise it should return the number of statements in the formula or
305 context given.
306
307 :param context: a graph instance to query or None
308 """
309
310 def contexts(self, triple=None):
311 """
312 Generator over all contexts in the graph. If triple is specified,
313 a generator over all contexts the triple is in.
314
315 if store is graph_aware, may also return empty contexts
316
317 :returns: a generator over Nodes
318 """
319
320 def query(self, query, initNs, initBindings, queryGraph, **kwargs):
321 """
322 If stores provide their own SPARQL implementation, override this.
323
324 queryGraph is None, a URIRef or '__UNION__'
325 If None the graph is specified in the query-string/object
326 If URIRef it specifies the graph to query,
327 If '__UNION__' the union of all named graphs should be queried
328 (This is used by ConjunctiveGraphs
329 Values other than None obviously only makes sense for
330 context-aware stores.)
331
332 """
333
334 raise NotImplementedError
335
336 def update(self, update, initNs, initBindings, queryGraph, **kwargs):
337 """
338 If stores provide their own (SPARQL) Update implementation,
339 override this.
340
341 queryGraph is None, a URIRef or '__UNION__'
342 If None the graph is specified in the query-string/object
343 If URIRef it specifies the graph to query,
344 If '__UNION__' the union of all named graphs should be queried
345 (This is used by ConjunctiveGraphs
346 Values other than None obviously only makes sense for
347 context-aware stores.)
348
349 """
350
351 raise NotImplementedError
352
353 # Optional Namespace methods
354
355 def bind(self, prefix, namespace):
356 """ """
357
358 def prefix(self, namespace):
359 """ """
360
361 def namespace(self, prefix):
362 """ """
363
364 def namespaces(self):
365 """ """
366 if False:
367 yield None
368
369 # Optional Transactional methods
370
371 def commit(self):
372 """ """
373
374 def rollback(self):
375 """ """
376
377 # Optional graph methods
378
379 def add_graph(self, graph):
380 """
381 Add a graph to the store, no effect if the graph already
382 exists.
383 :param graph: a Graph instance
384 """
385 raise Exception("Graph method called on non-graph_aware store")
386
387 def remove_graph(self, graph):
388 """
389 Remove a graph from the store, this shoud also remove all
390 triples in the graph
391
392 :param graphid: a Graph instance
393 """
394 raise Exception("Graph method called on non-graph_aware store")