Mercurial > repos > shellac > sam_consensus_v3
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") |