0001-data_source-handle-err-in-JSON-outputs-41195.patch
tests/test_datasource.py | ||
---|---|---|
296 | 296 |
assert 'Error loading JSON data source' in caplog.records[-1].message |
297 | 297 |
assert 'error' in caplog.records[-1].message |
298 | 298 | |
299 |
datasource = {'type': 'json', 'value': 'http://remote.example.net/json-list-err1'} |
|
300 |
assert data_sources.get_items(datasource) == [] |
|
301 |
assert 'Error reading JSON data source output (err 1)' in caplog.records[-1].message |
|
302 | ||
299 | 303 | |
300 | 304 |
def test_json_datasource_bad_url_scheme(caplog): |
301 | 305 |
datasource = {'type': 'json', 'value': ''} |
... | ... | |
496 | 500 |
assert urlopen.call_count == 3 |
497 | 501 | |
498 | 502 | |
503 |
def test_named_datasource_id_parameter(requests_pub): |
|
504 |
NamedDataSource.wipe() |
|
505 |
datasource = NamedDataSource(name='foobar') |
|
506 |
datasource.data_source = {'type': 'json', 'value': 'http://whatever/'} |
|
507 |
datasource.id_parameter = 'id' |
|
508 |
datasource.store() |
|
509 | ||
510 |
with mock.patch('wcs.qommon.misc.urlopen') as urlopen: |
|
511 |
value = [{'id': '1', 'text': 'foo'}] |
|
512 |
urlopen.side_effect = lambda *args: StringIO(json.dumps({'data': value})) |
|
513 |
assert datasource.get_structured_value('1') == value[0] |
|
514 |
assert urlopen.call_count == 1 |
|
515 |
assert urlopen.call_args[0][0] == 'http://whatever/?id=1' |
|
516 | ||
517 |
# try again, get from request.datasources_cache |
|
518 |
assert datasource.get_structured_value('1') == value[0] |
|
519 |
assert urlopen.call_count == 1 # no new call |
|
520 | ||
521 |
get_request().datasources_cache = {} |
|
522 |
with mock.patch('wcs.qommon.misc.urlopen') as urlopen: |
|
523 |
value = [{'id': '1', 'text': 'bar'}, {'id': '2', 'text': 'foo'}] |
|
524 |
urlopen.side_effect = lambda *args: StringIO(json.dumps({'data': value})) |
|
525 |
assert datasource.get_structured_value('1') == value[0] |
|
526 |
assert urlopen.call_count == 1 |
|
527 |
assert urlopen.call_args[0][0] == 'http://whatever/?id=1' |
|
528 | ||
529 |
get_request().datasources_cache = {} |
|
530 |
with mock.patch('wcs.qommon.misc.urlopen') as urlopen: |
|
531 |
value = [{'id': '1', 'text': 'foo'}] |
|
532 |
urlopen.side_effect = lambda *args: StringIO(json.dumps({'data': value, 'err': 0})) |
|
533 |
assert datasource.get_structured_value('1') == value[0] |
|
534 |
assert urlopen.call_count == 1 |
|
535 |
assert urlopen.call_args[0][0] == 'http://whatever/?id=1' |
|
536 | ||
537 |
get_request().datasources_cache = {} |
|
538 |
with mock.patch('wcs.qommon.misc.urlopen') as urlopen: |
|
539 |
value = [{'id': '1', 'text': 'foo'}] |
|
540 |
urlopen.side_effect = lambda *args: StringIO(json.dumps({'data': value, 'err': 1})) |
|
541 |
assert datasource.get_structured_value('1') is None |
|
542 |
assert urlopen.call_count == 1 |
|
543 |
assert urlopen.call_args[0][0] == 'http://whatever/?id=1' |
|
544 | ||
545 |
# no cache for errors |
|
546 |
assert datasource.get_structured_value('1') is None |
|
547 |
assert urlopen.call_count == 2 # called |
|
548 | ||
549 |
get_request().datasources_cache = {} |
|
550 |
with mock.patch('wcs.qommon.misc.urlopen') as urlopen: |
|
551 |
value = {'id': '1', 'text': 'foo'} # not a list |
|
552 |
urlopen.side_effect = lambda *args: StringIO(json.dumps({'data': value})) |
|
553 |
assert datasource.get_structured_value('1') is None |
|
554 |
assert urlopen.call_count == 1 |
|
555 |
assert urlopen.call_args[0][0] == 'http://whatever/?id=1' |
|
556 | ||
557 |
get_request().datasources_cache = {} |
|
558 |
with mock.patch('wcs.qommon.misc.urlopen') as urlopen: |
|
559 |
urlopen.side_effect = lambda *args: StringIO('not json') |
|
560 |
assert datasource.get_structured_value('1') is None |
|
561 |
assert urlopen.call_count == 1 |
|
562 |
assert urlopen.call_args[0][0] == 'http://whatever/?id=1' |
|
563 | ||
564 | ||
499 | 565 |
def test_named_datasource_in_formdef(): |
500 | 566 |
from wcs.formdef import FormDef |
501 | 567 |
datasource = NamedDataSource(name='foobar') |
tests/utilities.py | ||
---|---|---|
329 | 329 |
'http://remote.example.net/json-list': (200, '{"data": [{"id": "a", "text": "b"}]}', None), |
330 | 330 |
'http://remote.example.net/json-err0': (200, '{"data": "foo", "err": 0}', None), |
331 | 331 |
'http://remote.example.net/json-err1': (200, '{"data": "", "err": 1}', None), |
332 |
'http://remote.example.net/json-list-err1': (200, '{"data": [{"id": "a", "text": "b"}], "err": 1}', None), |
|
332 | 333 |
'http://remote.example.net/json-errstr': (200, '{"data": "", "err": "bug"}', None), |
333 | 334 |
'http://remote.example.net/json-errheader0': (200, '{"foo": "bar"}', |
334 | 335 |
{'x-error-code': '0'}), |
wcs/data_sources.py | ||
---|---|---|
201 | 201 |
entries = misc.json_loads(misc.urlopen(url).read()) |
202 | 202 |
if type(entries) is not dict: |
203 | 203 |
raise ValueError('not a json dict') |
204 |
if entries.get('err') not in (None, 0, "0"): |
|
205 |
raise ValueError('err %s' % entries['err']) |
|
204 | 206 |
if type(entries.get('data')) is not list: |
205 | 207 |
raise ValueError('not a json dict with a data list attribute') |
206 | 208 |
items = [] |
... | ... | |
374 | 376 | |
375 | 377 |
unsigned_url = url |
376 | 378 |
url = sign_url_auto_orig(url) |
377 |
resp = misc.urlopen(url).read() |
|
379 |
try: |
|
380 |
resp = misc.urlopen(url).read() |
|
381 |
resp = misc.json_loads(resp) |
|
382 |
if type(resp) is not dict: |
|
383 |
raise ValueError('not a json dict') |
|
384 |
if resp.get('err') not in (None, 0, "0"): |
|
385 |
raise ValueError('err %s' % resp['err']) |
|
386 |
if type(resp.get('data')) is not list: |
|
387 |
raise ValueError('not a json dict with a data list attribute') |
|
388 |
resp = resp['data'][0] |
|
389 |
except misc.ConnectionError as e: |
|
390 |
get_logger().warn('Error loading JSON data source (%s)' % str(e)) |
|
391 |
return None |
|
392 |
except (ValueError, TypeError) as e: |
|
393 |
get_logger().warn('Error reading JSON data source output (%s)' % str(e)) |
|
394 |
return None |
|
378 | 395 |
if hasattr(request, 'datasources_cache'): |
379 | 396 |
request.datasources_cache[unsigned_url] = resp |
380 | 397 |
return resp |
... | ... | |
388 | 405 |
def get_structured_value(self, option_id): |
389 | 406 |
value = None |
390 | 407 |
if self.type == 'json' and self.id_parameter: |
391 |
resp = self.load_json(self.id_parameter, option_id) |
|
392 |
response = misc.json_loads(resp) |
|
393 |
if response['data']: |
|
394 |
value = response['data'][0] |
|
408 |
value = self.load_json(self.id_parameter, option_id) |
|
395 | 409 |
else: |
396 | 410 |
structured_items = get_structured_items(self.data_source, mode='lazy') |
397 | 411 |
for item in structured_items: |
398 |
- |