comparison env/lib/python3.7/site-packages/rdflib/query.py @ 5:9b1c78e6ba9c draft default tip

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