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") |
