comparison env/lib/python3.9/site-packages/rdflib/query.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 import os
6 import itertools
7 import shutil
8 import tempfile
9 import warnings
10 import types
11
12 from six import BytesIO
13 from six import PY2
14 from six import text_type
15 from six.moves.urllib.parse import urlparse
16
17 __all__ = ['Processor', 'Result', 'ResultParser', 'ResultSerializer',
18 'ResultException']
19
20
21 class Processor(object):
22 """
23 Query plugin interface.
24
25 This module is useful for those wanting to write a query processor
26 that can plugin to rdf. If you are wanting to execute a query you
27 likely want to do so through the Graph class query method.
28
29 """
30
31 def __init__(self, graph):
32 pass
33
34 def query(self, strOrQuery, initBindings={}, initNs={}, DEBUG=False):
35 pass
36
37
38 class UpdateProcessor(object):
39 """
40 Update plugin interface.
41
42 This module is useful for those wanting to write an update
43 processor that can plugin to rdflib. If you are wanting to execute
44 an update statement you likely want to do so through the Graph
45 class update method.
46
47 .. versionadded:: 4.0
48
49 """
50
51 def __init__(self, graph):
52 pass
53
54 def update(self, strOrQuery, initBindings={}, initNs={}):
55 pass
56
57
58 class ResultException(Exception):
59 pass
60
61
62 class EncodeOnlyUnicode(object):
63 """
64 This is a crappy work-around for
65 http://bugs.python.org/issue11649
66
67
68 """
69
70 def __init__(self, stream):
71 self.__stream = stream
72
73 def write(self, arg):
74 if isinstance(arg, text_type):
75 self.__stream.write(arg.encode("utf-8"))
76 else:
77 self.__stream.write(arg)
78
79 def __getattr__(self, name):
80 return getattr(self.__stream, name)
81
82
83 class ResultRow(tuple):
84 """
85 a single result row
86 allows accessing bindings as attributes or with []
87
88 >>> from rdflib import URIRef, Variable
89 >>> rr=ResultRow({ Variable('a'): URIRef('urn:cake') }, [Variable('a')])
90
91 >>> rr[0]
92 rdflib.term.URIRef(u'urn:cake')
93 >>> rr[1]
94 Traceback (most recent call last):
95 ...
96 IndexError: tuple index out of range
97
98 >>> rr.a
99 rdflib.term.URIRef(u'urn:cake')
100 >>> rr.b
101 Traceback (most recent call last):
102 ...
103 AttributeError: b
104
105 >>> rr['a']
106 rdflib.term.URIRef(u'urn:cake')
107 >>> rr['b']
108 Traceback (most recent call last):
109 ...
110 KeyError: 'b'
111
112 >>> rr[Variable('a')]
113 rdflib.term.URIRef(u'urn:cake')
114
115 .. versionadded:: 4.0
116
117 """
118
119 def __new__(cls, values, labels):
120
121 instance = super(ResultRow, cls).__new__(
122 cls, (values.get(v) for v in labels))
123 instance.labels = dict((text_type(x[1]), x[0])
124 for x in enumerate(labels))
125 return instance
126
127 def __getattr__(self, name):
128 if name not in self.labels:
129 raise AttributeError(name)
130 return tuple.__getitem__(self, self.labels[name])
131
132 def __getitem__(self, name):
133 try:
134 return tuple.__getitem__(self, name)
135 except TypeError:
136 if name in self.labels:
137 return tuple.__getitem__(self, self.labels[name])
138 if text_type(name) in self.labels: # passing in variable object
139 return tuple.__getitem__(self, self.labels[text_type(name)])
140 raise KeyError(name)
141
142 def get(self, name, default=None):
143 try:
144 return self[name]
145 except KeyError:
146 return default
147
148 def asdict(self):
149 return dict((v, self[v]) for v in self.labels if self[v] is not None)
150
151
152 class Result(object):
153 """
154 A common class for representing query result.
155
156 There is a bit of magic here that makes this appear like different
157 Python objects, depending on the type of result.
158
159 If the type is "SELECT", iterating will yield lists of ResultRow objects
160
161 If the type is "ASK", iterating will yield a single bool (or
162 bool(result) will return the same bool)
163
164 If the type is "CONSTRUCT" or "DESCRIBE" iterating will yield the
165 triples.
166
167 len(result) also works.
168
169 """
170
171 def __init__(self, type_):
172
173 if type_ not in ('CONSTRUCT', 'DESCRIBE', 'SELECT', 'ASK'):
174 raise ResultException('Unknown Result type: %s' % type_)
175
176 self.type = type_
177 self.vars = None
178 self._bindings = None
179 self._genbindings = None
180 self.askAnswer = None
181 self.graph = None
182
183 def _get_bindings(self):
184 if self._genbindings:
185 self._bindings += list(self._genbindings)
186 self._genbindings = None
187
188 return self._bindings
189
190 def _set_bindings(self, b):
191 if isinstance(b, (types.GeneratorType, itertools.islice)):
192 self._genbindings = b
193 self._bindings = []
194 else:
195 self._bindings = b
196
197 bindings = property(
198 _get_bindings, _set_bindings, doc="a list of variable bindings as dicts")
199
200 @staticmethod
201 def parse(source=None, format=None, content_type=None, **kwargs):
202 from rdflib import plugin
203
204 if format:
205 plugin_key = format
206 elif content_type:
207 plugin_key = content_type.split(";", 1)[0]
208 else:
209 plugin_key = 'xml'
210
211 parser = plugin.get(plugin_key, ResultParser)()
212
213 return parser.parse(source, content_type=content_type, **kwargs)
214
215 def serialize(
216 self, destination=None, encoding="utf-8", format='xml', **args):
217
218 if self.type in ('CONSTRUCT', 'DESCRIBE'):
219 return self.graph.serialize(
220 destination, encoding=encoding, format=format, **args)
221
222 """stolen wholesale from graph.serialize"""
223 from rdflib import plugin
224 serializer = plugin.get(format, ResultSerializer)(self)
225 if destination is None:
226 stream = BytesIO()
227 stream2 = EncodeOnlyUnicode(stream)
228 serializer.serialize(stream2, encoding=encoding, **args)
229 return stream.getvalue()
230 if hasattr(destination, "write"):
231 stream = destination
232 serializer.serialize(stream, encoding=encoding, **args)
233 else:
234 location = destination
235 scheme, netloc, path, params, query, fragment = urlparse(location)
236 if netloc != "":
237 print("WARNING: not saving as location" +
238 "is not a local file reference")
239 return
240 fd, name = tempfile.mkstemp()
241 stream = os.fdopen(fd, 'wb')
242 serializer.serialize(stream, encoding=encoding, **args)
243 stream.close()
244 if hasattr(shutil, "move"):
245 shutil.move(name, path)
246 else:
247 shutil.copy(name, path)
248 os.remove(name)
249
250 def __len__(self):
251 if self.type == 'ASK':
252 return 1
253 elif self.type == 'SELECT':
254 return len(self.bindings)
255 else:
256 return len(self.graph)
257
258 def __bool__(self):
259 if self.type == 'ASK':
260 return self.askAnswer
261 else:
262 return len(self) > 0
263
264 if PY2:
265 __nonzero__ = __bool__
266
267 def __iter__(self):
268 if self.type in ("CONSTRUCT", "DESCRIBE"):
269 for t in self.graph:
270 yield t
271 elif self.type == 'ASK':
272 yield self.askAnswer
273 elif self.type == 'SELECT':
274 # this iterates over ResultRows of variable bindings
275
276 if self._genbindings:
277 for b in self._genbindings:
278 if b: # don't add a result row in case of empty binding {}
279 self._bindings.append(b)
280 yield ResultRow(b, self.vars)
281 self._genbindings = None
282 else:
283 for b in self._bindings:
284 if b: # don't add a result row in case of empty binding {}
285 yield ResultRow(b, self.vars)
286
287 def __getattr__(self, name):
288 if self.type in ("CONSTRUCT", "DESCRIBE") and self.graph is not None:
289 return self.graph.__getattr__(self, name)
290 elif self.type == 'SELECT' and name == 'result':
291 warnings.warn(
292 "accessing the 'result' attribute is deprecated."
293 " Iterate over the object instead.",
294 DeprecationWarning, stacklevel=2)
295 # copied from __iter__, above
296 return [(tuple(b[v] for v in self.vars)) for b in self.bindings]
297 else:
298 raise AttributeError(
299 "'%s' object has no attribute '%s'" % (self, name))
300
301 def __eq__(self, other):
302 try:
303 if self.type != other.type:
304 return False
305 if self.type == 'ASK':
306 return self.askAnswer == other.askAnswer
307 elif self.type == 'SELECT':
308 return self.vars == other.vars \
309 and self.bindings == other.bindings
310 else:
311 return self.graph == other.graph
312
313 except:
314 return False
315
316
317 class ResultParser(object):
318
319 def __init__(self):
320 pass
321
322 def parse(self, source, **kwargs):
323 """return a Result object"""
324 pass # abstract
325
326
327 class ResultSerializer(object):
328
329 def __init__(self, result):
330 self.result = result
331
332 def serialize(self, stream, encoding="utf-8", **kwargs):
333 """return a string properly serialized"""
334 pass # abstract