Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/rdflib/plugins/sparql/sparql.py @ 0:26e78fe6e8c4 draft
"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
| author | shellac |
|---|---|
| date | Sat, 02 May 2020 07:14:21 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:26e78fe6e8c4 |
|---|---|
| 1 import collections | |
| 2 import itertools | |
| 3 import datetime | |
| 4 | |
| 5 from rdflib.namespace import NamespaceManager | |
| 6 from rdflib import Variable, BNode, Graph, ConjunctiveGraph, URIRef, Literal | |
| 7 from rdflib.term import Node | |
| 8 | |
| 9 from .parserutils import CompValue | |
| 10 | |
| 11 import rdflib.plugins.sparql | |
| 12 from rdflib.plugins.sparql.compat import Mapping, MutableMapping | |
| 13 | |
| 14 | |
| 15 class SPARQLError(Exception): | |
| 16 def __init__(self, msg=None): | |
| 17 Exception.__init__(self, msg) | |
| 18 | |
| 19 | |
| 20 class NotBoundError(SPARQLError): | |
| 21 def __init__(self, msg=None): | |
| 22 SPARQLError.__init__(self, msg) | |
| 23 | |
| 24 | |
| 25 class AlreadyBound(SPARQLError): | |
| 26 """Raised when trying to bind a variable that is already bound!""" | |
| 27 def __init__(self): | |
| 28 SPARQLError.__init__(self) | |
| 29 | |
| 30 | |
| 31 class SPARQLTypeError(SPARQLError): | |
| 32 def __init__(self, msg): | |
| 33 SPARQLError.__init__(self, msg) | |
| 34 | |
| 35 | |
| 36 class Bindings(MutableMapping): | |
| 37 | |
| 38 """ | |
| 39 | |
| 40 A single level of a stack of variable-value bindings. | |
| 41 Each dict keeps a reference to the dict below it, | |
| 42 any failed lookup is propegated back | |
| 43 | |
| 44 In python 3.3 this could be a collections.ChainMap | |
| 45 """ | |
| 46 | |
| 47 def __init__(self, outer=None, d=[]): | |
| 48 self._d = dict(d) | |
| 49 self.outer = outer | |
| 50 | |
| 51 def __getitem__(self, key): | |
| 52 try: | |
| 53 return self._d[key] | |
| 54 except KeyError: | |
| 55 if not self.outer: | |
| 56 raise | |
| 57 return self.outer[key] | |
| 58 | |
| 59 def __contains__(self, key): | |
| 60 try: | |
| 61 self[key] | |
| 62 return True | |
| 63 except KeyError: | |
| 64 return False | |
| 65 | |
| 66 def __setitem__(self, key, value): | |
| 67 self._d[key] = value | |
| 68 | |
| 69 def __delitem__(self, key): | |
| 70 raise Exception("DelItem is not implemented!") | |
| 71 | |
| 72 def __len__(self): | |
| 73 i = 0 | |
| 74 for x in self: | |
| 75 i += 1 | |
| 76 return i | |
| 77 | |
| 78 def __iter__(self): | |
| 79 d = self | |
| 80 while d is not None: | |
| 81 for i in dict.__iter__(d._d): | |
| 82 yield i | |
| 83 d = d.outer | |
| 84 | |
| 85 def __str__(self): | |
| 86 return "Bindings({"+", ".join((k, self[k]) for k in self)+"})" | |
| 87 | |
| 88 def __repr__(self): | |
| 89 return str(self) | |
| 90 | |
| 91 | |
| 92 class FrozenDict(Mapping): | |
| 93 """ | |
| 94 An immutable hashable dict | |
| 95 | |
| 96 Taken from http://stackoverflow.com/a/2704866/81121 | |
| 97 | |
| 98 """ | |
| 99 def __init__(self, *args, **kwargs): | |
| 100 self._d = dict(*args, **kwargs) | |
| 101 self._hash = None | |
| 102 | |
| 103 def __iter__(self): | |
| 104 return iter(self._d) | |
| 105 | |
| 106 def __len__(self): | |
| 107 return len(self._d) | |
| 108 | |
| 109 def __getitem__(self, key): | |
| 110 return self._d[key] | |
| 111 | |
| 112 def __hash__(self): | |
| 113 # It would have been simpler and maybe more obvious to | |
| 114 # use hash(tuple(sorted(self._d.iteritems()))) from this discussion | |
| 115 # so far, but this solution is O(n). I don't know what kind of | |
| 116 # n we are going to run into, but sometimes it's hard to resist the | |
| 117 # urge to optimize when it will gain improved algorithmic performance. | |
| 118 if self._hash is None: | |
| 119 self._hash = 0 | |
| 120 for key, value in self.items(): | |
| 121 self._hash ^= hash(key) | |
| 122 self._hash ^= hash(value) | |
| 123 return self._hash | |
| 124 | |
| 125 def project(self, vars): | |
| 126 return FrozenDict( | |
| 127 (x for x in self.items() if x[0] in vars)) | |
| 128 | |
| 129 def disjointDomain(self, other): | |
| 130 return not bool(set(self).intersection(other)) | |
| 131 | |
| 132 def compatible(self, other): | |
| 133 for k in self: | |
| 134 try: | |
| 135 if self[k] != other[k]: | |
| 136 return False | |
| 137 except KeyError: | |
| 138 pass | |
| 139 | |
| 140 return True | |
| 141 | |
| 142 def merge(self, other): | |
| 143 res = FrozenDict( | |
| 144 itertools.chain(iter(self.items()), iter(other.items()))) | |
| 145 | |
| 146 return res | |
| 147 | |
| 148 def __str__(self): | |
| 149 return str(self._d) | |
| 150 | |
| 151 def __repr__(self): | |
| 152 return repr(self._d) | |
| 153 | |
| 154 | |
| 155 class FrozenBindings(FrozenDict): | |
| 156 | |
| 157 def __init__(self, ctx, *args, **kwargs): | |
| 158 FrozenDict.__init__(self, *args, **kwargs) | |
| 159 self.ctx = ctx | |
| 160 | |
| 161 def __getitem__(self, key): | |
| 162 | |
| 163 if not isinstance(key, Node): | |
| 164 key = Variable(key) | |
| 165 | |
| 166 if not type(key) in (BNode, Variable): | |
| 167 return key | |
| 168 | |
| 169 return self._d[key] | |
| 170 | |
| 171 def project(self, vars): | |
| 172 return FrozenBindings( | |
| 173 self.ctx, (x for x in self.items() if x[0] in vars)) | |
| 174 | |
| 175 def merge(self, other): | |
| 176 res = FrozenBindings( | |
| 177 self.ctx, itertools.chain(iter(self.items()), iter(other.items()))) | |
| 178 | |
| 179 return res | |
| 180 | |
| 181 def _now(self): | |
| 182 return self.ctx.now | |
| 183 | |
| 184 def _bnodes(self): | |
| 185 return self.ctx.bnodes | |
| 186 | |
| 187 def _prologue(self): | |
| 188 return self.ctx.prologue | |
| 189 | |
| 190 prologue = property(_prologue) | |
| 191 bnodes = property(_bnodes) | |
| 192 now = property(_now) | |
| 193 | |
| 194 def forget(self, before, _except=None): | |
| 195 """ | |
| 196 return a frozen dict only of bindings made in self | |
| 197 since before | |
| 198 """ | |
| 199 if not _except : _except = [] | |
| 200 # bindings from initBindings are newer forgotten | |
| 201 return FrozenBindings(self.ctx, (x for x in self.items() if x[0] in _except or x[0] in self.ctx.initBindings or before[x[0]] is None)) | |
| 202 | |
| 203 def remember(self, these): | |
| 204 """ | |
| 205 return a frozen dict only of bindings in these | |
| 206 """ | |
| 207 return FrozenBindings(self.ctx, (x for x in self.items() if x[0] in these)) | |
| 208 | |
| 209 | |
| 210 class QueryContext(object): | |
| 211 | |
| 212 """ | |
| 213 Query context - passed along when evaluating the query | |
| 214 """ | |
| 215 | |
| 216 def __init__(self, graph=None, bindings=None, initBindings=None): | |
| 217 self.initBindings = initBindings | |
| 218 self.bindings = Bindings(d=bindings or []) | |
| 219 if initBindings: self.bindings.update(initBindings) | |
| 220 | |
| 221 if isinstance(graph, ConjunctiveGraph): | |
| 222 self._dataset = graph | |
| 223 if rdflib.plugins.sparql.SPARQL_DEFAULT_GRAPH_UNION: | |
| 224 self.graph = self.dataset | |
| 225 else: | |
| 226 self.graph = self.dataset.default_context | |
| 227 else: | |
| 228 self._dataset = None | |
| 229 self.graph = graph | |
| 230 | |
| 231 self.prologue = None | |
| 232 self.now = datetime.datetime.now() | |
| 233 | |
| 234 self.bnodes = collections.defaultdict(BNode) | |
| 235 | |
| 236 def clone(self, bindings=None): | |
| 237 r = QueryContext( | |
| 238 self._dataset if self._dataset is not None else self.graph, bindings or self.bindings, initBindings=self.initBindings) | |
| 239 r.prologue = self.prologue | |
| 240 r.graph = self.graph | |
| 241 r.bnodes = self.bnodes | |
| 242 return r | |
| 243 | |
| 244 def _get_dataset(self): | |
| 245 if self._dataset is None: | |
| 246 raise Exception( | |
| 247 'You performed a query operation requiring ' + | |
| 248 'a dataset (i.e. ConjunctiveGraph), but ' + | |
| 249 'operating currently on a single graph.') | |
| 250 return self._dataset | |
| 251 | |
| 252 dataset = property(_get_dataset, doc="current dataset") | |
| 253 | |
| 254 def load(self, source, default=False, **kwargs): | |
| 255 | |
| 256 def _load(graph, source): | |
| 257 try: | |
| 258 return graph.load(source, **kwargs) | |
| 259 except: | |
| 260 pass | |
| 261 try: | |
| 262 return graph.load(source, format='n3', **kwargs) | |
| 263 except: | |
| 264 pass | |
| 265 try: | |
| 266 return graph.load(source, format='nt', **kwargs) | |
| 267 except: | |
| 268 raise Exception( | |
| 269 "Could not load %s as either RDF/XML, N3 or NTriples" % ( | |
| 270 source)) | |
| 271 | |
| 272 if not rdflib.plugins.sparql.SPARQL_LOAD_GRAPHS: | |
| 273 # we are not loading - if we already know the graph | |
| 274 # being "loaded", just add it to the default-graph | |
| 275 if default: | |
| 276 self.graph += self.dataset.get_context(source) | |
| 277 else: | |
| 278 | |
| 279 if default: | |
| 280 _load(self.graph, source) | |
| 281 else: | |
| 282 _load(self.dataset, source) | |
| 283 | |
| 284 def __getitem__(self, key): | |
| 285 # in SPARQL BNodes are just labels | |
| 286 if not type(key) in (BNode, Variable): | |
| 287 return key | |
| 288 try: | |
| 289 return self.bindings[key] | |
| 290 except KeyError: | |
| 291 return None | |
| 292 | |
| 293 def get(self, key, default=None): | |
| 294 try: | |
| 295 return self[key] | |
| 296 except KeyError: | |
| 297 return default | |
| 298 | |
| 299 def solution(self, vars=None): | |
| 300 """ | |
| 301 Return a static copy of the current variable bindings as dict | |
| 302 """ | |
| 303 if vars: | |
| 304 return FrozenBindings( | |
| 305 self, ((k, v) | |
| 306 for k, v in self.bindings.items() | |
| 307 if k in vars)) | |
| 308 else: | |
| 309 return FrozenBindings(self, iter(self.bindings.items())) | |
| 310 | |
| 311 def __setitem__(self, key, value): | |
| 312 if key in self.bindings and self.bindings[key] != value: | |
| 313 raise AlreadyBound() | |
| 314 | |
| 315 self.bindings[key] = value | |
| 316 | |
| 317 def pushGraph(self, graph): | |
| 318 r = self.clone() | |
| 319 r.graph = graph | |
| 320 return r | |
| 321 | |
| 322 def push(self): | |
| 323 r = self.clone(Bindings(self.bindings)) | |
| 324 return r | |
| 325 | |
| 326 def clean(self): | |
| 327 return self.clone([]) | |
| 328 | |
| 329 # def pop(self): | |
| 330 # self.bindings = self.bindings.outer | |
| 331 # if self.bindings is None: | |
| 332 # raise Exception("We've bottomed out of the bindings stack!") | |
| 333 | |
| 334 def thaw(self, frozenbindings): | |
| 335 """ | |
| 336 Create a new read/write query context from the given solution | |
| 337 """ | |
| 338 c = self.clone(frozenbindings) | |
| 339 | |
| 340 return c | |
| 341 | |
| 342 | |
| 343 class Prologue(object): | |
| 344 | |
| 345 """ | |
| 346 A class for holding prefixing bindings and base URI information | |
| 347 """ | |
| 348 | |
| 349 def __init__(self): | |
| 350 self.base = None | |
| 351 self.namespace_manager = NamespaceManager( | |
| 352 Graph()) # ns man needs a store | |
| 353 | |
| 354 def resolvePName(self, prefix, localname): | |
| 355 ns = self.namespace_manager.store.namespace(prefix or "") | |
| 356 if ns is None: | |
| 357 raise Exception('Unknown namespace prefix : %s' % prefix) | |
| 358 return URIRef(ns + (localname or "")) | |
| 359 | |
| 360 def bind(self, prefix, uri): | |
| 361 self.namespace_manager.bind(prefix, uri, replace=True) | |
| 362 | |
| 363 def absolutize(self, iri): | |
| 364 | |
| 365 """ | |
| 366 Apply BASE / PREFIXes to URIs | |
| 367 (and to datatypes in Literals) | |
| 368 | |
| 369 TODO: Move resolving URIs to pre-processing | |
| 370 """ | |
| 371 | |
| 372 if isinstance(iri, CompValue): | |
| 373 if iri.name == 'pname': | |
| 374 return self.resolvePName(iri.prefix, iri.localname) | |
| 375 if iri.name == 'literal': | |
| 376 return Literal( | |
| 377 iri.string, lang=iri.lang, | |
| 378 datatype=self.absolutize(iri.datatype)) | |
| 379 elif isinstance(iri, URIRef) and not ':' in iri: | |
| 380 return URIRef(iri, base=self.base) | |
| 381 | |
| 382 return iri | |
| 383 | |
| 384 | |
| 385 class Query(object): | |
| 386 """ | |
| 387 A parsed and translated query | |
| 388 """ | |
| 389 | |
| 390 def __init__(self, prologue, algebra): | |
| 391 self.prologue = prologue | |
| 392 self.algebra = algebra |
