0001-data-sources-add-error-management-parameters-44054.patch
tests/form_pages/test_all.py | ||
---|---|---|
24 | 24 |
from wcs.qommon import force_str |
25 | 25 |
from wcs.qommon.emails import docutils |
26 | 26 |
from wcs.qommon.ident.password_accounts import PasswordAccount |
27 |
from wcs.qommon.misc import ConnectionError |
|
27 | 28 |
from wcs.carddef import CardDef |
28 | 29 |
from wcs.formdef import FormDef |
29 | 30 |
from wcs.workflows import ( |
... | ... | |
96 | 97 |
return pub |
97 | 98 | |
98 | 99 | |
100 |
@pytest.fixture |
|
101 |
def error_email(pub): |
|
102 |
pub.cfg['debug'] = {'error_email': 'errors@localhost.invalid'} |
|
103 |
pub.write_cfg() |
|
104 |
pub.set_config() |
|
105 | ||
106 | ||
99 | 107 |
def teardown_module(module): |
100 | 108 |
clean_temporary_pub() |
101 | 109 | |
... | ... | |
5662 | 5670 |
assert formdef.data_class().select()[0].data['0_display'] == 'world' |
5663 | 5671 | |
5664 | 5672 | |
5665 |
def test_item_field_autocomplete_json_source(http_requests, pub): |
|
5673 |
def test_item_field_autocomplete_json_source(http_requests, pub, error_email, emails):
|
|
5666 | 5674 |
user = create_user(pub) |
5667 | 5675 |
formdef = create_formdef() |
5668 | 5676 |
formdef.data_class().wipe() |
... | ... | |
5752 | 5760 |
# check unauthorized access |
5753 | 5761 |
resp2 = get_app(pub).get(select2_url + '?q=hell', status=403) |
5754 | 5762 | |
5763 |
# check error handling in autocomplete endpoint |
|
5764 |
formdef.data_class().wipe() |
|
5765 | ||
5766 |
app = get_app(pub) |
|
5767 |
with mock.patch('wcs.qommon.misc.urlopen') as urlopen: |
|
5768 |
urlopen.side_effect = ConnectionError('...') |
|
5769 |
resp = app.get('/test/') |
|
5770 |
assert urlopen.call_count == 0 |
|
5771 |
pq = resp.pyquery.remove_namespaces() |
|
5772 |
select2_url = pq('select').attr['data-select2-url'] |
|
5773 | ||
5774 |
assert emails.count() == 0 |
|
5775 |
resp2 = app.get(select2_url + '?q=hell') |
|
5776 |
assert urlopen.call_count == 1 |
|
5777 |
assert urlopen.call_args[0][0] == 'http://remote.example.net/json?q=hell' |
|
5778 |
assert resp2.json == {'data': [], 'err': '1'} |
|
5779 |
assert emails.count() == 0 |
|
5780 | ||
5781 |
data_source.notify_on_errors = True |
|
5782 |
data_source.store() |
|
5783 |
resp2 = app.get(select2_url + '?q=hell') |
|
5784 |
assert emails.count() == 1 |
|
5785 |
assert 'wcs.qommon.errors.ConnectionError: ...' in emails.get_latest('subject') |
|
5786 | ||
5787 |
data_source.notify_on_errors = False |
|
5788 |
data_source.store() |
|
5789 | ||
5755 | 5790 |
# simulate select2 mode, with qommon.forms.js adding an extra hidden widget |
5756 | 5791 |
resp.form.fields['f0_display'] = Hidden(form=resp.form, tag='input', name='f0_display', pos=10) |
5757 | 5792 |
resp.form['f0'].force_value('1') |
tests/test_datasource.py | ||
---|---|---|
53 | 53 |
return req |
54 | 54 | |
55 | 55 | |
56 |
@pytest.fixture |
|
57 |
def error_email(pub): |
|
58 |
pub.cfg['debug'] = {'error_email': 'errors@localhost.invalid'} |
|
59 |
pub.write_cfg() |
|
60 |
pub.set_config() |
|
61 | ||
62 | ||
56 | 63 |
def test_item_field_python_datasource(requests_pub): |
57 | 64 |
req = get_request() |
58 | 65 |
req.environ['REQUEST_METHOD'] = 'POST' |
... | ... | |
90 | 97 |
{'id': '2', 'text': 'bar'}, |
91 | 98 |
] |
92 | 99 | |
93 |
# invalid python expression |
|
94 |
datasource = {'type': 'formula', 'value': 'foobar'} |
|
95 |
assert data_sources.get_items(datasource) == [] |
|
96 | ||
97 |
# expression not iterable |
|
98 |
datasource = {'type': 'formula', 'value': '2'} |
|
99 |
assert data_sources.get_items(datasource) == [] |
|
100 | ||
101 | 100 |
# three-item tuples |
102 | 101 |
plain_list = [('1', 'foo', 'a'), ('2', 'bar', 'b')] |
103 | 102 |
datasource = {'type': 'formula', 'value': repr(plain_list)} |
... | ... | |
132 | 131 |
] |
133 | 132 | |
134 | 133 | |
134 |
def test_python_datasource_errors(pub, error_email, http_requests, emails, caplog): |
|
135 |
# invalid python expression |
|
136 |
datasource = {'type': 'formula', 'value': 'foobar', 'notify_on_errors': True} |
|
137 |
assert data_sources.get_items(datasource) == [] |
|
138 |
assert 'Failed to eval() Python data source' in emails.get_latest('subject') |
|
139 | ||
140 |
# expression not iterable |
|
141 |
datasource = {'type': 'formula', 'value': '2', 'notify_on_errors': True} |
|
142 |
assert data_sources.get_items(datasource) == [] |
|
143 |
assert 'gave a non-iterable result' in emails.get_latest('subject') |
|
144 | ||
145 | ||
135 | 146 |
def test_python_datasource_with_evalutils(pub): |
136 | 147 |
plain_list = [ |
137 | 148 |
{'id': 'foo', 'text': 'Foo', 'value': '2017-01-01'}, |
... | ... | |
365 | 376 |
] |
366 | 377 | |
367 | 378 | |
368 |
def test_json_datasource_bad_url(pub, http_requests, caplog):
|
|
379 |
def test_json_datasource_bad_url(pub, error_email, http_requests, emails, caplog):
|
|
369 | 380 |
datasource = {'type': 'json', 'value': 'http://remote.example.net/404'} |
370 | 381 |
assert data_sources.get_items(datasource) == [] |
371 |
assert 'Error loading JSON data source' in caplog.records[-1].message |
|
372 |
assert 'status: 404' in caplog.records[-1].message |
|
382 |
assert emails.count() == 0 |
|
373 | 383 | |
374 |
datasource = {'type': 'json', 'value': 'http://remote.example.net/xml'}
|
|
384 |
datasource = {'type': 'json', 'value': 'http://remote.example.net/404', 'notify_on_errors': True}
|
|
375 | 385 |
assert data_sources.get_items(datasource) == [] |
376 |
assert 'Error reading JSON data source output' in caplog.records[-1].message |
|
377 |
assert 'Expecting value:' in caplog.records[-1].message |
|
386 |
assert emails.count() == 1 |
|
387 |
assert 'error in HTTP request to http://remote.example.net/404 (status: 404)' in emails.get_latest( |
|
388 |
'subject' |
|
389 |
) |
|
378 | 390 | |
379 |
datasource = {'type': 'json', 'value': 'http://remote.example.net/connection-error'}
|
|
391 |
datasource = {'type': 'json', 'value': 'http://remote.example.net/xml', 'notify_on_errors': True}
|
|
380 | 392 |
assert data_sources.get_items(datasource) == [] |
381 |
assert 'Error loading JSON data source' in caplog.records[-1].message
|
|
382 |
assert 'error' in caplog.records[-1].message
|
|
393 |
assert emails.count() == 2
|
|
394 |
assert 'Error reading JSON data source' in emails.get_latest('subject')
|
|
383 | 395 | |
384 |
datasource = {'type': 'json', 'value': 'http://remote.example.net/json-list-err1'} |
|
396 |
datasource = { |
|
397 |
'type': 'json', |
|
398 |
'value': 'http://remote.example.net/connection-error', |
|
399 |
'notify_on_errors': True, |
|
400 |
} |
|
385 | 401 |
assert data_sources.get_items(datasource) == [] |
386 |
assert 'Error reading JSON data source output (err 1)' in caplog.records[-1].message
|
|
402 |
assert 'Error loading JSON data source' in emails.get_latest('subject')
|
|
387 | 403 | |
404 |
datasource = { |
|
405 |
'type': 'json', |
|
406 |
'value': 'http://remote.example.net/json-list-err1', |
|
407 |
'notify_on_errors': True, |
|
408 |
} |
|
409 |
assert data_sources.get_items(datasource) == [] |
|
410 |
assert 'Error reading JSON data source output (err 1)' in emails.get_latest('subject') |
|
388 | 411 | |
389 |
def test_json_datasource_bad_url_scheme(pub, caplog): |
|
390 |
datasource = {'type': 'json', 'value': ''} |
|
412 | ||
413 |
def test_json_datasource_bad_url_scheme(pub, error_email, emails): |
|
414 |
datasource = {'type': 'json', 'value': '', 'notify_on_errors': True} |
|
391 | 415 |
assert data_sources.get_items(datasource) == [] |
392 |
assert caplog.records[-1].message == 'Empty URL in JSON data source'
|
|
416 |
assert emails.count() == 0
|
|
393 | 417 | |
394 |
datasource = {'type': 'json', 'value': 'foo://bar'} |
|
418 |
datasource = {'type': 'json', 'value': 'foo://bar', 'notify_on_errors': True}
|
|
395 | 419 |
assert data_sources.get_items(datasource) == [] |
396 |
assert 'Error loading JSON data source' in caplog.records[-1].message
|
|
397 |
assert 'invalid scheme in URL' in caplog.records[-1].message
|
|
420 |
assert 'Error loading JSON data source' in emails.get_latest('subject')
|
|
421 |
assert 'invalid scheme in URL' in emails.get_latest('subject')
|
|
398 | 422 | |
399 |
datasource = {'type': 'json', 'value': '/bla/blo'} |
|
423 |
datasource = {'type': 'json', 'value': '/bla/blo', 'notify_on_errors': True}
|
|
400 | 424 |
assert data_sources.get_items(datasource) == [] |
401 |
assert 'Error loading JSON data source' in caplog.records[-1].message
|
|
402 |
assert 'invalid scheme in URL' in caplog.records[-1].message
|
|
425 |
assert 'Error loading JSON data source' in emails.get_latest('subject')
|
|
426 |
assert 'invalid scheme in URL' in emails.get_latest('subject')
|
|
403 | 427 | |
404 | 428 | |
405 | 429 |
def test_geojson_datasource(pub, requests_pub, http_requests): |
... | ... | |
741 | 765 |
] |
742 | 766 | |
743 | 767 | |
744 |
def test_geojson_datasource_bad_url(pub, http_requests, caplog):
|
|
745 |
datasource = {'type': 'geojson', 'value': 'http://remote.example.net/404'} |
|
768 |
def test_geojson_datasource_bad_url(pub, http_requests, error_email, emails):
|
|
769 |
datasource = {'type': 'geojson', 'value': 'http://remote.example.net/404', 'notify_on_errors': True}
|
|
746 | 770 |
assert data_sources.get_items(datasource) == [] |
747 |
assert 'Error loading JSON data source' in caplog.records[-1].message
|
|
748 |
assert 'status: 404' in caplog.records[-1].message
|
|
771 |
assert 'Error loading JSON data source' in emails.get_latest('subject')
|
|
772 |
assert 'status: 404' in emails.get_latest('subject')
|
|
749 | 773 | |
750 |
datasource = {'type': 'geojson', 'value': 'http://remote.example.net/xml'} |
|
774 |
datasource = {'type': 'geojson', 'value': 'http://remote.example.net/xml', 'notify_on_errors': True}
|
|
751 | 775 |
assert data_sources.get_items(datasource) == [] |
752 |
assert 'Error reading JSON data source output' in caplog.records[-1].message
|
|
753 |
assert 'Expecting value:' in caplog.records[-1].message
|
|
776 |
assert 'Error reading JSON data source output' in emails.get_latest('subject')
|
|
777 |
assert 'Expecting value:' in emails.get_latest('subject')
|
|
754 | 778 | |
755 |
datasource = {'type': 'geojson', 'value': 'http://remote.example.net/connection-error'} |
|
779 |
datasource = { |
|
780 |
'type': 'geojson', |
|
781 |
'value': 'http://remote.example.net/connection-error', |
|
782 |
'notify_on_errors': True, |
|
783 |
} |
|
756 | 784 |
assert data_sources.get_items(datasource) == [] |
757 |
assert 'Error loading JSON data source' in caplog.records[-1].message
|
|
758 |
assert 'error' in caplog.records[-1].message
|
|
785 |
assert 'Error loading JSON data source' in emails.get_latest('subject')
|
|
786 |
assert 'error' in emails.get_latest('subject')
|
|
759 | 787 | |
760 |
datasource = {'type': 'geojson', 'value': 'http://remote.example.net/json-list-err1'} |
|
788 |
datasource = { |
|
789 |
'type': 'geojson', |
|
790 |
'value': 'http://remote.example.net/json-list-err1', |
|
791 |
'notify_on_errors': True, |
|
792 |
} |
|
761 | 793 |
assert data_sources.get_items(datasource) == [] |
762 |
assert 'Error reading JSON data source output (err 1)' in caplog.records[-1].message
|
|
794 |
assert 'Error reading JSON data source output (err 1)' in emails.get_latest('subject')
|
|
763 | 795 | |
764 | 796 | |
765 |
def test_geojson_datasource_bad_url_scheme(pub, caplog):
|
|
797 |
def test_geojson_datasource_bad_url_scheme(pub, error_email, emails):
|
|
766 | 798 |
datasource = {'type': 'geojson', 'value': ''} |
767 | 799 |
assert data_sources.get_items(datasource) == [] |
768 |
assert caplog.records[-1].message == 'Empty URL in GeoJSON data source'
|
|
800 |
assert emails.count() == 0
|
|
769 | 801 | |
770 |
datasource = {'type': 'geojson', 'value': 'foo://bar'} |
|
802 |
datasource = {'type': 'geojson', 'value': 'foo://bar', 'notify_on_errors': True}
|
|
771 | 803 |
assert data_sources.get_items(datasource) == [] |
772 |
assert 'Error loading JSON data source' in caplog.records[-1].message
|
|
773 |
assert 'invalid scheme in URL' in caplog.records[-1].message
|
|
804 |
assert 'Error loading JSON data source' in emails.get_latest('subject')
|
|
805 |
assert 'invalid scheme in URL' in emails.get_latest('subject')
|
|
774 | 806 | |
775 |
datasource = {'type': 'geojson', 'value': '/bla/blo'} |
|
807 |
datasource = {'type': 'geojson', 'value': '/bla/blo', 'notify_on_errors': True}
|
|
776 | 808 |
assert data_sources.get_items(datasource) == [] |
777 |
assert 'Error loading JSON data source' in caplog.records[-1].message
|
|
778 |
assert 'invalid scheme in URL' in caplog.records[-1].message
|
|
809 |
assert 'Error loading JSON data source' in emails.get_latest('subject')
|
|
810 |
assert 'invalid scheme in URL' in emails.get_latest('subject')
|
|
779 | 811 | |
780 | 812 | |
781 | 813 |
def test_item_field_named_python_datasource(requests_pub): |
tests/utilities.py | ||
---|---|---|
245 | 245 |
class EmailsMocking(object): |
246 | 246 |
def create_smtp_server(self, *args, **kwargs): |
247 | 247 |
class MockSmtplibSMTP(object): |
248 |
def __init__(self, emails):
|
|
249 |
self.emails = emails
|
|
248 |
def __init__(self, mocking):
|
|
249 |
self.mocking = mocking
|
|
250 | 250 | |
251 | 251 |
def send_message(self, msg, msg_from, rcpts): |
252 | 252 |
return self.sendmail(msg_from, rcpts, msg.as_string()) |
... | ... | |
260 | 260 |
else: |
261 | 261 |
payload = msg.get_payload(decode=True) |
262 | 262 |
payloads = [payload] |
263 |
self.emails[force_text(subject)] = { |
|
263 |
self.mocking.emails[force_text(subject)] = {
|
|
264 | 264 |
'from': msg_from, |
265 | 265 |
'to': email.header.decode_header(msg['To'])[0][0], |
266 | 266 |
'payload': force_str(payload if payload else ''), |
267 | 267 |
'payloads': payloads, |
268 | 268 |
'msg': msg, |
269 |
'subject': force_text(subject), |
|
269 | 270 |
} |
270 |
self.emails[force_text(subject)]['email_rcpt'] = rcpts |
|
271 |
self.mocking.emails[force_text(subject)]['email_rcpt'] = rcpts |
|
272 |
self.mocking.latest_subject = force_text(subject) |
|
271 | 273 | |
272 | 274 |
def quit(self): |
273 | 275 |
pass |
274 | 276 | |
275 |
return MockSmtplibSMTP(self.emails)
|
|
277 |
return MockSmtplibSMTP(self) |
|
276 | 278 | |
277 | 279 |
def get(self, subject): |
278 | 280 |
return self.emails.get(subject) |
279 | 281 | |
282 |
def get_latest(self, part=None): |
|
283 |
email = self.emails.get(self.latest_subject, {}) |
|
284 |
if part: |
|
285 |
return email.get(part) if email else None |
|
286 |
return email |
|
287 | ||
280 | 288 |
def empty(self): |
281 | 289 |
self.emails.clear() |
282 | 290 | |
... | ... | |
287 | 295 |
self.wcs_create_smtp_server = sys.modules['wcs.qommon.emails'].create_smtp_server |
288 | 296 |
sys.modules['wcs.qommon.emails'].create_smtp_server = self.create_smtp_server |
289 | 297 |
self.emails = {} |
298 |
self.latest_subject = None |
|
290 | 299 |
return self |
291 | 300 | |
292 | 301 |
def __exit__(self, exc_type, exc_value, tb): |
... | ... | |
407 | 416 |
raise ConnectionError('error') |
408 | 417 | |
409 | 418 |
if raise_on_http_errors and not (200 <= status < 300): |
410 |
raise ConnectionError('error in HTTP request to (status: %s)' % status)
|
|
419 |
raise ConnectionError('error in HTTP request to %s (status: %s)' % (url, status))
|
|
411 | 420 | |
412 | 421 |
return FakeResponse(status, data, headers), status, data, None |
413 | 422 |
wcs/admin/data_sources.py | ||
---|---|---|
187 | 187 |
'data-dynamic-display-value': 'json', |
188 | 188 |
}, |
189 | 189 |
) |
190 |
form.add( |
|
191 |
CheckboxWidget, |
|
192 |
'notify_on_errors', |
|
193 |
title=_('Notify on errors'), |
|
194 |
value=self.datasource.notify_on_errors, |
|
195 |
) |
|
196 |
form.add( |
|
197 |
CheckboxWidget, |
|
198 |
'record_on_errors', |
|
199 |
title=_('Record on errors'), |
|
200 |
value=self.datasource.record_on_errors, |
|
201 |
) |
|
202 | ||
190 | 203 |
if not self.datasource.is_readonly(): |
191 | 204 |
form.add_submit('submit', _('Submit')) |
192 | 205 |
form.add_submit('cancel', _('Cancel')) |
... | ... | |
209 | 222 |
raise ValueError() |
210 | 223 | |
211 | 224 |
self.datasource.name = name |
212 |
self.datasource.description = form.get_widget('description').parse() |
|
213 |
self.datasource.data_source = form.get_widget('data_source') |
|
214 |
self.datasource.cache_duration = form.get_widget('cache_duration').parse() |
|
215 |
self.datasource.query_parameter = form.get_widget('query_parameter').parse() |
|
216 |
self.datasource.id_parameter = form.get_widget('id_parameter').parse() |
|
217 |
self.datasource.data_attribute = form.get_widget('data_attribute').parse() |
|
218 |
self.datasource.id_attribute = form.get_widget('id_attribute').parse() |
|
219 |
self.datasource.text_attribute = form.get_widget('text_attribute').parse() |
|
220 |
self.datasource.id_property = form.get_widget('id_property').parse() |
|
221 |
self.datasource.label_template_property = form.get_widget('label_template_property').parse() |
|
222 | 225 |
if slug_widget: |
223 | 226 |
self.datasource.slug = slug |
227 | ||
228 |
for widget in form.widgets: |
|
229 |
if widget.name in ('name', 'slug'): |
|
230 |
continue |
|
231 |
setattr(self.datasource, widget.name, widget.parse()) |
|
232 | ||
224 | 233 |
self.datasource.store() |
225 | 234 | |
226 | 235 |
wcs/api.py | ||
---|---|---|
17 | 17 |
import datetime |
18 | 18 |
import json |
19 | 19 |
import re |
20 |
import sys |
|
20 | 21 |
import time |
21 | 22 |
import urllib.parse |
22 | 23 | |
... | ... | |
29 | 30 | |
30 | 31 |
from .qommon import _ |
31 | 32 |
from .qommon import misc |
32 |
from .qommon.errors import AccessForbiddenError, TraversalError, UnknownNameIdAccessForbiddenError |
|
33 |
from .qommon.errors import ( |
|
34 |
AccessForbiddenError, |
|
35 |
TraversalError, |
|
36 |
UnknownNameIdAccessForbiddenError, |
|
37 |
ConnectionError, |
|
38 |
) |
|
33 | 39 |
from .qommon.form import ComputedExpressionWidget |
34 | 40 |
from .qommon.storage import Equal, NotEqual |
35 | 41 | |
... | ... | |
37 | 43 |
from wcs.conditions import Condition, ValidationError |
38 | 44 |
from wcs.carddef import CardDef |
39 | 45 |
from wcs.formdef import FormDef |
46 |
from wcs.data_sources import NamedDataSource |
|
40 | 47 |
from wcs.data_sources import get_object as get_data_source_object |
41 | 48 |
from wcs.roles import Role, logged_users_role |
42 | 49 |
from wcs.forms.common import FormStatusPage |
... | ... | |
1022 | 1029 |
url += urllib.parse.quote(get_request().form['q']) |
1023 | 1030 |
url = sign_url_auto_orig(url) |
1024 | 1031 |
get_response().set_content_type('application/json') |
1025 |
return misc.urlopen(url).read() |
|
1032 |
try: |
|
1033 |
return misc.urlopen(url).read() |
|
1034 |
except ConnectionError: |
|
1035 |
if 'data_source' in info: |
|
1036 |
data_source = NamedDataSource.get(info['data_source']) |
|
1037 |
exc_info = sys.exc_info() |
|
1038 |
get_publisher().notify_of_exception( |
|
1039 |
exc_info, |
|
1040 |
context='[DATASOURCE]', |
|
1041 |
notify=data_source.notify_on_errors, |
|
1042 |
record=data_source.record_on_errors, |
|
1043 |
) |
|
1044 |
return json.dumps({'data': [], 'err': '1'}) |
|
1026 | 1045 | |
1027 | 1046 |
# carddef_ref in info |
1028 | 1047 |
carddef_ref = info['carddef_ref'] |
wcs/data_sources.py | ||
---|---|---|
16 | 16 | |
17 | 17 |
import collections |
18 | 18 |
import hashlib |
19 |
import sys |
|
19 | 20 |
import urllib.parse |
20 | 21 |
import xml.etree.ElementTree as ET |
21 | 22 | |
... | ... | |
165 | 166 |
data_source = data_source or {} |
166 | 167 |
data_key = data_source.get('data_attribute') or 'data' |
167 | 168 |
geojson = data_source.get('type') == 'geojson' |
169 |
error_summary = None |
|
170 |
exc = None |
|
168 | 171 |
try: |
169 | 172 |
entries = misc.json_loads(misc.urlopen(url).read()) |
170 | 173 |
if not isinstance(entries, dict): |
... | ... | |
177 | 180 |
else: |
178 | 181 |
if not isinstance(entries.get(data_key), list): |
179 | 182 |
raise ValueError('not a json dict with a %s list attribute' % data_key) |
183 |
return entries |
|
180 | 184 |
except misc.ConnectionError as e: |
181 |
get_logger().warning('Error loading %s (%s)' % (log_message_part, str(e)))
|
|
182 |
return None
|
|
185 |
error_summary = 'Error loading %s (%s)' % (log_message_part, str(e))
|
|
186 |
exc = e
|
|
183 | 187 |
except (ValueError, TypeError) as e: |
184 |
get_logger().warning('Error reading %s output (%s)' % (log_message_part, str(e))) |
|
185 |
return None |
|
186 |
return entries |
|
188 |
error_summary = 'Error reading %s output (%s)' % (log_message_part, str(e)) |
|
189 |
exc = e |
|
190 | ||
191 |
if data_source and (data_source.get('record_on_errors') or data_source.get('notify_on_errors')): |
|
192 |
try: |
|
193 |
raise Exception(error_summary) from exc |
|
194 |
except Exception: |
|
195 |
exc_info = sys.exc_info() |
|
196 |
get_publisher().notify_of_exception( |
|
197 |
exc_info, |
|
198 |
context='[DATASOURCE]', |
|
199 |
notify=data_source.get('notify_on_errors'), |
|
200 |
record=data_source.get('record_on_errors'), |
|
201 |
) |
|
202 | ||
203 |
return None |
|
187 | 204 | |
188 | 205 | |
189 | 206 |
def request_json_items(url, data_source): |
... | ... | |
271 | 288 |
try: |
272 | 289 |
value = eval(data_source.get('value'), global_eval_dict, variables) |
273 | 290 |
if not isinstance(value, collections.Iterable): |
274 |
get_logger().warning( |
|
275 |
'Python data source (%r) gave a non-iterable result' % data_source.get('value') |
|
291 |
try: |
|
292 |
raise Exception( |
|
293 |
'Python data source (%r) gave a non-iterable result' % data_source.get('value') |
|
294 |
) |
|
295 |
except Exception: |
|
296 |
exc_info = sys.exc_info() |
|
297 |
get_publisher().notify_of_exception( |
|
298 |
exc_info, |
|
299 |
context='[DATASOURCE]', |
|
300 |
notify=data_source.get('notify_on_errors'), |
|
301 |
record=data_source.get('record_on_errors'), |
|
276 | 302 |
) |
277 | 303 |
return [] |
278 | 304 |
if len(value) == 0: |
... | ... | |
289 | 315 |
elif isinstance(value[0], str): |
290 | 316 |
return [{'id': x, 'text': x} for x in value] |
291 | 317 |
return value |
292 |
except: |
|
293 |
get_logger().warning('Failed to eval() Python data source (%r)' % data_source.get('value')) |
|
318 |
except Exception as exc: |
|
319 |
try: |
|
320 |
raise Exception( |
|
321 |
'Failed to eval() Python data source (%r)' % data_source.get('value') |
|
322 |
) from exc |
|
323 |
except Exception: |
|
324 |
exc_info = sys.exc_info() |
|
325 |
get_publisher().notify_of_exception( |
|
326 |
exc_info, |
|
327 |
context='[DATASOURCE]', |
|
328 |
notify=data_source.get('notify_on_errors'), |
|
329 |
record=data_source.get('record_on_errors'), |
|
330 |
) |
|
294 | 331 |
return [] |
295 | 332 |
elif data_source.get('type') in ['json', 'geojson']: |
296 | 333 |
# the content available at a json URL, it must answer with a dict with |
... | ... | |
299 | 336 |
geojson = data_source.get('type') == 'geojson' |
300 | 337 |
url = data_source.get('value') |
301 | 338 |
if not url: |
302 |
if geojson: |
|
303 |
get_logger().warning('Empty URL in GeoJSON data source') |
|
304 |
else: |
|
305 |
get_logger().warning('Empty URL in JSON data source') |
|
306 | 339 |
return [] |
307 | 340 |
url = url.strip() |
308 | 341 |
if Template.is_template_string(url): |
... | ... | |
382 | 415 |
label_template_property = None |
383 | 416 |
external = None |
384 | 417 |
external_status = None |
418 |
notify_on_errors = False |
|
419 |
record_on_errors = False |
|
385 | 420 | |
386 | 421 |
# declarations for serialization |
387 | 422 |
XML_NODES = [ |
... | ... | |
399 | 434 |
('external', 'str'), |
400 | 435 |
('external_status', 'str'), |
401 | 436 |
('data_source', 'data_source'), |
437 |
('notify_on_errors', 'bool'), |
|
438 |
('record_on_errors', 'bool'), |
|
402 | 439 |
] |
403 | 440 | |
404 | 441 |
def __init__(self, name=None): |
... | ... | |
417 | 454 |
{ |
418 | 455 |
'id_property': self.id_property, |
419 | 456 |
'label_template_property': self.label_template_property, |
457 |
'notify_on_errors': self.notify_on_errors, |
|
458 |
'record_on_errors': self.record_on_errors, |
|
420 | 459 |
} |
421 | 460 |
) |
422 | 461 |
return data_source |
... | ... | |
427 | 466 |
'data_attribute': self.data_attribute, |
428 | 467 |
'id_attribute': self.id_attribute, |
429 | 468 |
'text_attribute': self.text_attribute, |
469 |
'notify_on_errors': self.notify_on_errors, |
|
470 |
'record_on_errors': self.record_on_errors, |
|
430 | 471 |
} |
431 | 472 |
) |
432 | 473 |
return data_source |
... | ... | |
527 | 568 |
json_url = self.get_json_query_url() |
528 | 569 |
info = None |
529 | 570 |
if json_url: |
530 |
info = {'url': json_url} |
|
571 |
info = {'url': json_url, 'data_source': self.id}
|
|
531 | 572 |
return '/api/autocomplete/%s' % (get_session().get_data_source_query_info_token(info)) |
532 | 573 |
if self.type and self.type.startswith('carddef:'): |
533 | 574 |
parts = self.type.split(':') |
wcs/templates/wcs/backoffice/data-source.html | ||
---|---|---|
19 | 19 |
<h3>{% trans "Configuration" %}</h3> |
20 | 20 |
<ul> |
21 | 21 |
<li>{% trans "Type of source:" %} {{ datasource.type_label }}</li> |
22 |
{% if datasource.data_source.type == 'json' or datasource.data_source.type == 'jsonp' %} |
|
22 |
{% if datasource.data_source.type == 'json' or datasource.data_source.type == 'jsonp' or datasource.data_source.type == 'geojson' %}
|
|
23 | 23 |
<li>{% trans "URL:" %} <a href="{{ datasource.get_variadic_url }}">{{ datasource.data_source.value }}</a></li> |
24 | 24 |
{% elif datasource.data_source.type == 'formula' %} |
25 | 25 |
<li>{% trans "Python Expression:" %} {{ datasource.data_source.value }}</li> |
... | ... | |
27 | 27 |
{% if datasource.cache_duration %} |
28 | 28 |
<li>{% trans "Cache Duration:" %} {{ datasource.humanized_cache_duration }} |
29 | 29 |
{% endif %} |
30 |
<li>{% trans "Notify on errors:" %} {{ datasource.notify_on_errors|yesno }}</li> |
|
31 |
<li>{% trans "Record on errors:" %} {{ datasource.record_on_errors|yesno }}</li> |
|
30 | 32 |
</ul> |
31 | 33 |
</div> |
32 | 34 | |
33 |
- |