diff --git a/swh/web/ui/tests/views/test_api.py b/swh/web/ui/tests/views/test_api.py --- a/swh/web/ui/tests/views/test_api.py +++ b/swh/web/ui/tests/views/test_api.py @@ -40,16 +40,16 @@ def generic_api_lookup_nothing_is_found(self): # given def test_generic_lookup_fn(sha1, another_unused_arg): - assert another_unused_arg == 'unused arg' + assert another_unused_arg == 'unused_arg' assert sha1 == 'sha1' return None # when with self.assertRaises(NotFoundExc) as cm: - api._api_lookup('sha1', test_generic_lookup_fn, - 'This will be raised because None is returned.', - lambda x: x, - 'unused arg') + api._api_lookup( + test_generic_lookup_fn, 'sha1', 'unused_arg', + notfound_msg='This will be raised because None is returned.') + self.assertIn('This will be raised because None is returned.', cm.exception.args[0]) @@ -62,12 +62,11 @@ # when actual_result = api._api_lookup( - 'something', - test_generic_lookup_fn_1, - 'This is not the error message you are looking for. Move along.', - lambda x: x * 2, - 'some param 0', - 'some param 1') + test_generic_lookup_fn_1, 'something', 'some param 0', + 'some param 1', + notfound_msg=('This is not the error message you are looking for. ' + 'Move along.'), + enrich_fn=lambda x: x * 2) self.assertEqual(actual_result, [4, 6, 8]) @@ -80,11 +79,10 @@ # when actual_result = api._api_lookup( - 'something', - test_generic_lookup_fn_2, - 'Not the error message you are looking for, it is. ' - 'Along, you move!', - lambda x: ''. join(['=', x, '='])) + test_generic_lookup_fn_2, 'something', + notfound_msg=('Not the error message you are looking for, it is. ' + 'Along, you move!'), + enrich_fn=lambda x: ''. join(['=', x, '='])) self.assertEqual(actual_result, ['=a=', '=b=', '=c=']) @@ -97,10 +95,9 @@ # when actual_result = api._api_lookup( - 'crit', - test_generic_lookup_fn_3, - 'Move!', - lambda x: x - 1) + test_generic_lookup_fn_3, 'crit', + notfound_msg='Move!', + enrich_fn=lambda x: x - 1) self.assertEqual(actual_result, [3, 4, 5]) @@ -117,10 +114,9 @@ # when actual_result = api._api_lookup( - '123', - test_generic_lookup_fn_4, - 'Nothing to do', - test_enrich_data) + test_generic_lookup_fn_4, '123', + notfound_msg='Nothing to do', + enrich_fn=test_enrich_data) self.assertEqual(actual_result, {'a': 100}) @@ -2476,9 +2472,9 @@ def api_lookup_not_found(self): # when with self.assertRaises(exc.NotFoundExc) as e: - api._api_lookup('something', - lambda x: None, - 'this is the error message raised as it is None') + api._api_lookup( + lambda x: None, 'something', + notfound_msg='this is the error message raised as it is None') self.assertEqual(e.exception.args[0], 'this is the error message raised as it is None') @@ -2486,19 +2482,17 @@ @istest def api_lookup_with_result(self): # when - actual_result = api._api_lookup('something', - lambda x: x + '!', - 'this is the error which won\'t be ' - 'used here') + actual_result = api._api_lookup( + lambda x: x + '!', 'something', + notfound_msg='this is the error which won\'t be used here') self.assertEqual(actual_result, 'something!') @istest def api_lookup_with_result_as_map(self): # when - actual_result = api._api_lookup([1, 2, 3], - lambda x: map(lambda y: y+1, x), - 'this is the error which won\'t be ' - 'used here') + actual_result = api._api_lookup( + lambda x: map(lambda y: y+1, x), [1, 2, 3], + notfound_msg='this is the error which won\'t be used here') self.assertEqual(actual_result, [2, 3, 4]) diff --git a/swh/web/ui/views/api.py b/swh/web/ui/views/api.py --- a/swh/web/ui/views/api.py +++ b/swh/web/ui/views/api.py @@ -3,6 +3,8 @@ # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information +import functools + from types import GeneratorType from flask import render_template, request, url_for @@ -34,6 +36,41 @@ pointing to it""" +def _api_lookup(lookup_fn, *args, + notfound_msg='Object not found', + enrich_fn=lambda x: x): + """Capture a redundant behavior of: + - looking up the backend with a criteria (be it an identifier or checksum) + passed to the function lookup_fn + - if nothing is found, raise an NotFoundExc exception with error + message notfound_msg. + - Otherwise if something is returned: + - either as list, map or generator, map the enrich_fn function to it + and return the resulting data structure as list. + - either as dict and pass to enrich_fn and return the dict enriched. + + Args: + - criteria: discriminating criteria to lookup + - lookup_fn: function expects one criteria and optional supplementary + *args. + - notfound_msg: if nothing matching the criteria is found, + raise NotFoundExc with this error message. + - enrich_fn: Function to use to enrich the result returned by + lookup_fn. Default to the identity function if not provided. + - *args: supplementary arguments to pass to lookup_fn. + + Raises: + NotFoundExp or whatever `lookup_fn` raises. + + """ + res = lookup_fn(*args) + if not res: + raise NotFoundExc(notfound_msg) + if isinstance(res, (map, list, GeneratorType)): + return [enrich_fn(x) for x in res] + return enrich_fn(res) + + @app.route('/api/1/') def api_endpoints(): """Display the list of opened api endpoints. @@ -107,9 +144,8 @@ return ov r = _api_lookup( - origin_id, - _lookup_origin_visits, - error_msg_if_not_found='No origin %s found' % origin_id, + _lookup_origin_visits, origin_id, + notfound_msg='No origin {} found'.format(origin_id), enrich_fn=_enrich_origin_visit) if r: @@ -167,11 +203,10 @@ return ov return _api_lookup( - origin_id, - service.lookup_origin_visit, - 'No visit %s for origin %s found' % (visit_id, origin_id), - _enrich_origin_visit, - visit_id) + service.lookup_origin_visit, origin_id, visit_id, + notfound_msg=('No visit {} for origin {} found' + .format(visit_id, origin_id)), + enrich_fn=_enrich_origin_visit) @app.route('/api/1/content/symbol/', methods=['POST']) @@ -211,11 +246,9 @@ return service.lookup_expression(exp, last_sha1, per_page) symbols = _api_lookup( - q, - lookup_fn=lookup_exp, - error_msg_if_not_found='No indexed raw content match expression \'' - '%s\'.' % q, - enrich_fn=lambda x: utils.enrich_content(x, top_url=True)) + lookup_exp, q, + notfound_msg="No indexed raw content match expression '{}'.".format(q), + enrich_fn=functools.partial(utils.enrich_content, top_url=True)) if symbols: l = len(symbols) @@ -311,43 +344,6 @@ return response -def _api_lookup(criteria, - lookup_fn, - error_msg_if_not_found, - enrich_fn=lambda x: x, - *args): - """Capture a redundant behavior of: - - looking up the backend with a criteria (be it an identifier or checksum) - passed to the function lookup_fn - - if nothing is found, raise an NotFoundExc exception with error - message error_msg_if_not_found. - - Otherwise if something is returned: - - either as list, map or generator, map the enrich_fn function to it - and return the resulting data structure as list. - - either as dict and pass to enrich_fn and return the dict enriched. - - Args: - - criteria: discriminating criteria to lookup - - lookup_fn: function expects one criteria and optional supplementary - *args. - - error_msg_if_not_found: if nothing matching the criteria is found, - raise NotFoundExc with this error message. - - enrich_fn: Function to use to enrich the result returned by - lookup_fn. Default to the identity function if not provided. - - *args: supplementary arguments to pass to lookup_fn. - - Raises: - NotFoundExp or whatever `lookup_fn` raises. - - """ - res = lookup_fn(criteria, *args) - if not res: - raise NotFoundExc(error_msg_if_not_found) - if isinstance(res, (map, list, GeneratorType)): - return [enrich_fn(x) for x in res] - return enrich_fn(res) - - @app.route('/api/1/origin//') @app.route('/api/1/origin//url/') @doc.route('/api/1/origin/') @@ -397,8 +393,8 @@ return origin return _api_lookup( - ori_dict, lookup_fn=service.lookup_origin, - error_msg_if_not_found=error_msg, + service.lookup_origin, ori_dict, + notfound_msg=error_msg, enrich_fn=_enrich_origin) @@ -416,8 +412,8 @@ """ return _api_lookup( - person_id, lookup_fn=service.lookup_person, - error_msg_if_not_found='Person with id %s not found.' % person_id) + service.lookup_person, person_id, + notfound_msg='Person with id {} not found.'.format(person_id)) @app.route('/api/1/release//') @@ -441,9 +437,8 @@ """ error_msg = 'Release with sha1_git %s not found.' % sha1_git return _api_lookup( - sha1_git, - lookup_fn=service.lookup_release, - error_msg_if_not_found=error_msg, + service.lookup_release, sha1_git, + notfound_msg=error_msg, enrich_fn=utils.enrich_release) @@ -588,15 +583,11 @@ """ ts = utils.parse_timestamp(ts) return _api_lookup( - origin_id, - service.lookup_revision_by, - 'Revision with (origin_id: %s, branch_name: %s' - ', ts: %s) not found.' % (origin_id, - branch_name, - ts), - utils.enrich_revision, - branch_name, - ts) + service.lookup_revision_by, origin_id, branch_name, ts, + notfound_msg=('Revision with (origin_id: {}, branch_name: {}' + ', ts: {}) not found.'.format(origin_id, + branch_name, ts)), + enrich_fn=utils.enrich_revision) @app.route('/api/1/revision//prev//') @@ -620,10 +611,9 @@ return utils.enrich_revision(revision, context) return _api_lookup( - sha1_git, - service.lookup_revision, - 'Revision with sha1_git %s not found.' % sha1_git, - _enrich_revision) + service.lookup_revision, sha1_git, + notfound_msg='Revision with sha1_git %s not found.' % sha1_git, + enrich_fn=_enrich_revision) @app.route('/api/1/revision//') @@ -645,10 +635,9 @@ """ return _api_lookup( - sha1_git, - service.lookup_revision, - 'Revision with sha1_git %s not found.' % sha1_git, - utils.enrich_revision) + service.lookup_revision, sha1_git, + notfound_msg='Revision with sha1_git {} not found.'.format(sha1_git), + enrich_fn=utils.enrich_revision) @app.route('/api/1/revision//raw/') @@ -739,9 +728,8 @@ return service.lookup_revision_log(s, limit) error_msg = 'Revision with sha1_git %s not found.' % sha1_git - rev_get = _api_lookup(sha1_git, - lookup_fn=lookup_revision_log_with_limit, - error_msg_if_not_found=error_msg, + rev_get = _api_lookup(lookup_revision_log_with_limit, sha1_git, + notfound_msg=error_msg, enrich_fn=utils.enrich_revision) l = len(rev_get) @@ -767,10 +755,10 @@ else: rev_forward_ids = prev_sha1s.split('/') - rev_forward = _api_lookup(rev_forward_ids, - lookup_fn=service.lookup_revision_multiple, - error_msg_if_not_found=error_msg, - enrich_fn=utils.enrich_revision) + rev_forward = _api_lookup( + service.lookup_revision_multiple, rev_forward_ids, + notfound_msg=error_msg, + enrich_fn=utils.enrich_revision) revisions = rev_forward + rev_backward result.update({ @@ -834,12 +822,10 @@ error_msg += ', branch name %s' % branch_name error_msg += (' and time stamp %s.' % ts) if ts else '.' - rev_get = _api_lookup(origin_id, - lookup_revision_log_by_with_limit, - error_msg, - utils.enrich_revision, - branch_name, - ts) + rev_get = _api_lookup( + lookup_revision_log_by_with_limit, origin_id, branch_name, ts, + notfound_msg=error_msg, + enrich_fn=utils.enrich_revision) l = len(rev_get) if l == per_page+1: revisions = rev_get[:-1] @@ -903,18 +889,15 @@ error_msg_path = ('Entry with path %s relative to directory ' 'with sha1_git %s not found.') % (path, sha1_git) return _api_lookup( - sha1_git, - service.lookup_directory_with_path, - error_msg_path, - utils.enrich_directory, - path) + service.lookup_directory_with_path, sha1_git, path, + notfound_msg=error_msg_path, + enrich_fn=utils.enrich_directory) else: error_msg_nopath = 'Directory with sha1_git %s not found.' % sha1_git return _api_lookup( - sha1_git, - service.lookup_directory, - error_msg_nopath, - utils.enrich_directory) + service.lookup_directory, sha1_git, + notfound_msg=error_msg_nopath, + enrich_fn=utils.enrich_directory) @app.route('/api/1/content//provenance/') @@ -948,9 +931,8 @@ return p return _api_lookup( - q, - lookup_fn=service.lookup_content_provenance, - error_msg_if_not_found='Content with %s not found.' % q, + service.lookup_content_provenance, q, + notfound_msg='Content with {} not found.'.format(q), enrich_fn=_enrich_revision) @@ -970,10 +952,8 @@ """ return _api_lookup( - q, - lookup_fn=service.lookup_content_filetype, - error_msg_if_not_found='No filetype information found ' - 'for content %s.' % q, + service.lookup_content_filetype, q, + notfound_msg='No filetype information found for content {}.'.format(q), enrich_fn=utils.enrich_metadata_endpoint) @@ -994,10 +974,8 @@ """ return _api_lookup( - q, - lookup_fn=service.lookup_content_language, - error_msg_if_not_found='No language information found ' - 'for content %s.' % q, + service.lookup_content_language, q, + notfound_msg='No language information found for content {}.'.format(q), enrich_fn=utils.enrich_metadata_endpoint) @@ -1017,10 +995,8 @@ """ return _api_lookup( - q, - lookup_fn=service.lookup_content_license, - error_msg_if_not_found='No license information found ' - 'for content %s.' % q, + service.lookup_content_license, q, + notfound_msg='No license information found for content {}.'.format(q), enrich_fn=utils.enrich_metadata_endpoint) @@ -1041,10 +1017,8 @@ """ return _api_lookup( - q, - lookup_fn=service.lookup_content_ctags, - error_msg_if_not_found='No ctags symbol found ' - 'for content %s.' % q, + service.lookup_content_ctags, q, + notfound_msg='No ctags symbol found for content {}.'.format(q), enrich_fn=utils.enrich_metadata_endpoint) @@ -1108,9 +1082,8 @@ """ return _api_lookup( - q, - lookup_fn=service.lookup_content, - error_msg_if_not_found='Content with %s not found.' % q, + service.lookup_content, q, + notfound_msg='Content with {} not found.'.format(q), enrich_fn=utils.enrich_content) @@ -1129,7 +1102,6 @@ """ return _api_lookup( - uuid, - lookup_fn=service.lookup_entity_by_uuid, - error_msg_if_not_found="Entity with uuid '%s' not found." % uuid, + service.lookup_entity_by_uuid, uuid, + notfound_msg="Entity with uuid '%s' not found." % uuid, enrich_fn=utils.enrich_entity)