diff --git a/swh/web/ui/tests/test_renderers.py b/swh/web/ui/tests/test_renderers.py
index b22ae942f..b7a83ca73 100644
--- a/swh/web/ui/tests/test_renderers.py
+++ b/swh/web/ui/tests/test_renderers.py
@@ -1,231 +1,239 @@
# Copyright (C) 2015 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
import json
import unittest
import yaml
from flask_api.mediatypes import MediaType
from nose.tools import istest
from unittest.mock import patch
from swh.web.ui import renderers
class RendererTestCase(unittest.TestCase):
@patch('swh.web.ui.renderers.request')
@istest
def swh_filter_renderer_do_nothing(self, mock_request):
# given
mock_request.args = {}
swh_filter_renderer = renderers.SWHFilterEnricher()
input_data = {'a': 'some-data'}
# when
actual_data = swh_filter_renderer.filter_by_fields(input_data)
# then
self.assertEquals(actual_data, input_data)
@patch('swh.web.ui.renderers.utils')
@patch('swh.web.ui.renderers.request')
@istest
def swh_filter_renderer_do_filter(self, mock_request, mock_utils):
# given
mock_request.args = {'fields': 'a,c'}
mock_utils.filter_field_keys.return_value = {'a': 'some-data'}
swh_filter_renderer = renderers.SWHFilterEnricher()
input_data = {'a': 'some-data',
'b': 'some-other-data'}
# when
actual_data = swh_filter_renderer.filter_by_fields(input_data)
# then
self.assertEquals(actual_data, {'a': 'some-data'})
mock_utils.filter_field_keys.assert_called_once_with(input_data,
{'a', 'c'})
@patch('swh.web.ui.renderers.request')
@istest
def yaml_renderer_without_filter(self, mock_request):
# given
mock_request.args = {}
yaml_renderer = renderers.YAMLRenderer()
input_data = {'target': 'sha1-dir',
'type': 'dir',
'dir-id': 'dir-id-sha1-git'}
expected_data = input_data
# when
actual_data = yaml_renderer.render(input_data, 'application/yaml')
# then
self.assertEqual(yaml.load(actual_data), expected_data)
@patch('swh.web.ui.renderers.request')
@istest
def yaml_renderer(self, mock_request):
# given
mock_request.args = {'fields': 'type,target'}
yaml_renderer = renderers.YAMLRenderer()
input_data = {'target': 'sha1-dir',
'type': 'dir',
'dir-id': 'dir-id-sha1-git'}
expected_data = {'target': 'sha1-dir', 'type': 'dir'}
# when
actual_data = yaml_renderer.render(input_data, 'application/yaml')
# then
self.assertEqual(yaml.load(actual_data), expected_data)
@patch('swh.web.ui.renderers.request')
@istest
def json_renderer_basic(self, mock_request):
# given
mock_request.args = {}
json_renderer = renderers.SWHJSONRenderer()
input_data = {'target': 'sha1-dir',
'type': 'dir',
'dir-id': 'dir-id-sha1-git'}
expected_data = input_data
# when
actual_data = json_renderer.render(input_data, MediaType(
'application/json'))
# then
self.assertEqual(json.loads(actual_data), expected_data)
@patch('swh.web.ui.renderers.request')
@istest
def json_renderer_basic_with_filter(self, mock_request):
# given
mock_request.args = {'fields': 'target'}
json_renderer = renderers.SWHJSONRenderer()
input_data = {'target': 'sha1-dir',
'type': 'dir',
'dir-id': 'dir-id-sha1-git'}
expected_data = {'target': 'sha1-dir'}
# when
actual_data = json_renderer.render(input_data, MediaType(
'application/json'))
# then
self.assertEqual(json.loads(actual_data), expected_data)
@patch('swh.web.ui.renderers.request')
@istest
def json_renderer_basic_with_filter_and_jsonp(self, mock_request):
# given
mock_request.args = {'fields': 'target',
'callback': 'jsonpfn'}
json_renderer = renderers.SWHJSONRenderer()
input_data = {'target': 'sha1-dir',
'type': 'dir',
'dir-id': 'dir-id-sha1-git'}
# when
actual_data = json_renderer.render(input_data, MediaType(
'application/json'))
# then
self.assertEqual(actual_data, 'jsonpfn({"target": "sha1-dir"})')
@patch('swh.web.ui.renderers.request')
@istest
def jsonp_enricher_basic_with_filter_and_jsonp(self, mock_request):
# given
mock_request.args = {'callback': 'jsonpfn'}
jsonp_enricher = renderers.JSONPEnricher()
# when
actual_output = jsonp_enricher.enrich_with_jsonp({'output': 'test'})
# then
self.assertEqual(actual_output, "jsonpfn({'output': 'test'})")
@patch('swh.web.ui.renderers.request')
@istest
def jsonp_enricher_do_nothing(self, mock_request):
# given
mock_request.args = {}
jsonp_enricher = renderers.JSONPEnricher()
# when
actual_output = jsonp_enricher.enrich_with_jsonp({'output': 'test'})
# then
self.assertEqual(actual_output, {'output': 'test'})
@istest
def urlize_api_links(self):
# update api link with html links content with links
content = '{"url": "/api/1/abc/"}'
expected_content = '{"url": "/api/1/abc/"}'
self.assertEquals(renderers.urlize_api_links(content),
expected_content)
# update /browse link with html links content with links
content = '{"url": "/browse/def/"}'
expected_content = '{"url": "' \
'/browse/def/"}'
self.assertEquals(renderers.urlize_api_links(content),
expected_content)
# will do nothing since it's not an api url
other_content = '{"url": "/something/api/1/other"}'
self.assertEquals(renderers.urlize_api_links(other_content),
other_content)
+ @istest
+ def revision_id_from_url(self):
+ url = ('/browse/revision/9ba4bcb645898d562498ea66a0df958ef0e7a68c/'
+ 'prev/9ba4bcb645898d562498ea66a0df958ef0e7aaaa/')
+
+ expected_id = '9ba4bcb645898d562498ea66a0df958ef0e7a68c'
+ self.assertEqual(renderers.revision_id_from_url(url), expected_id)
+
@istest
def safe_docstring_display(self):
# update api link with html links content with links
docstring = """
Show all revisions (~git log) starting from
sha1_git.
The first element returned is the given sha1_git.
Args:
sha1_git: the revision's hash
Returns:
Information on the revision if found.
Raises:
BadInputExc in case of unknown algo_hash or bad hash
NotFoundExc if the revision is not found.
Example:
blah
"""
expected_docstring = """Show all revisions (~git log) starting from
sha1_git.
The first element returned is the given sha1_git.
Args:
sha1_git: the revision's hash
Returns:
Information on the revision if found.
Raises:
BadInputExc in case of unknown algo_hash or bad hash
NotFoundExc if the revision is not found.
Example:
blah"""
self.assertEquals(renderers.safe_docstring_display(docstring),
expected_docstring)
diff --git a/swh/web/ui/tests/views/test_browse.py b/swh/web/ui/tests/views/test_browse.py
index e08ce4896..930909e11 100644
--- a/swh/web/ui/tests/views/test_browse.py
+++ b/swh/web/ui/tests/views/test_browse.py
@@ -1,1710 +1,1730 @@
# Copyright (C) 2015 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
from nose.tools import istest
from unittest.mock import patch
from swh.web.ui.exc import BadInputExc, NotFoundExc
from .. import test_app
class FileMock():
def __init__(self, filename):
self.filename = filename
class SearchView(test_app.SWHViewTestCase):
render_template = False
+ @patch('swh.web.ui.apidoc.APIUrls')
+ @istest
+ def browse_api_doc(self, mock_api_urls):
+ # given
+ endpoints = {
+ '/a/doc/endpoint/': 'relevant documentation',
+ '/some/other/endpoint/': 'more docstrings'}
+ mock_api_urls.apidoc_routes = endpoints
+
+ # when
+ rv = self.client.get('/api/1/doc/')
+
+ # then
+ self.assertEquals(rv.status_code, 200)
+ self.assertIsNotNone(
+ self.get_context_variable('doc_routes'),
+ sorted(endpoints.items())
+ )
+ self.assert_template_used('api.html')
+
@istest
def search_default(self):
# when
rv = self.client.get('/search/')
self.assertEqual(rv.status_code, 200)
self.assertEqual(self.get_context_variable('message'), '')
self.assertEqual(self.get_context_variable('search_res'), None)
self.assert_template_used('search.html')
@patch('swh.web.ui.views.browse.api')
@istest
def search_get_query_hash_not_found(self, mock_api):
# given
mock_api.api_search.return_value = {
'search_res': [{
'filename': None,
'sha1': 'sha1:456',
'found': False}],
'search_stats': {'nbfiles': 1, 'pct': 100}}
# when
rv = self.client.get('/search/?q=sha1:456')
self.assertEqual(rv.status_code, 200)
self.assertEqual(self.get_context_variable('message'), '')
self.assertEqual(self.get_context_variable('search_res'), [
{'filename': None,
'sha1': 'sha1:456',
'found': False}])
self.assert_template_used('search.html')
mock_api.api_search.assert_called_once_with('sha1:456')
@patch('swh.web.ui.views.browse.api')
@istest
def search_get_query_hash_bad_input(self, mock_api):
# given
mock_api.api_search.side_effect = BadInputExc('error msg')
# when
rv = self.client.get('/search/?q=sha1_git:789')
self.assertEqual(rv.status_code, 200)
self.assertEqual(self.get_context_variable('message'), 'error msg')
self.assertEqual(self.get_context_variable('search_res'), None)
self.assert_template_used('search.html')
mock_api.api_search.assert_called_once_with('sha1_git:789')
@patch('swh.web.ui.views.browse.api')
@istest
def search_get_query_hash_found(self, mock_api):
# given
mock_api.api_search.return_value = {
'search_res': [{
'filename': None,
'sha1': 'sha1:123',
'found': True}],
'search_stats': {'nbfiles': 1, 'pct': 100}}
# when
rv = self.client.get('/search/?q=sha1:123')
self.assertEqual(rv.status_code, 200)
self.assertEqual(self.get_context_variable('message'), '')
self.assertEqual(len(self.get_context_variable('search_res')), 1)
resp = self.get_context_variable('search_res')[0]
self.assertTrue(resp is not None)
self.assertEqual(resp['sha1'], 'sha1:123')
self.assertEqual(resp['found'], True)
self.assert_template_used('search.html')
mock_api.api_search.assert_called_once_with('sha1:123')
@patch('swh.web.ui.views.browse.request')
@patch('swh.web.ui.views.browse.api')
@istest
def search_post_hashes_bad_input(self, mock_api, mock_request):
# given
mock_request.form = {'a': ['456caf10e9535160d90e874b45aa426de762f19f'],
'b': ['745bab676c8f3cec8016e0c39ea61cf57e518865']}
mock_request.method = 'POST'
mock_api.api_search.side_effect = BadInputExc(
'error bad input')
# when (mock_request completes the post request)
rv = self.client.post('/search/')
# then
self.assertEqual(rv.status_code, 200)
self.assertEqual(self.get_context_variable('search_stats'),
{'nbfiles': 0, 'pct': 0})
self.assertEqual(self.get_context_variable('search_res'), None)
self.assertEqual(self.get_context_variable('message'),
'error bad input')
self.assert_template_used('search.html')
@patch('swh.web.ui.views.browse.request')
@patch('swh.web.ui.views.browse.api')
@istest
def search_post_hashes_none(self, mock_api, mock_request):
# given
mock_request.form = {'a': ['456caf10e9535160d90e874b45aa426de762f19f'],
'b': ['745bab676c8f3cec8016e0c39ea61cf57e518865']}
mock_request.method = 'POST'
mock_api.api_search.return_value = {
'search_stats': {'nbfiles': 2, 'pct': 0},
'search_res': [{'filename': 'a',
'sha1': '456caf10e9535160d90e874b45aa426de762f19f',
'found': False},
{'filename': 'b',
'sha1': '745bab676c8f3cec8016e0c39ea61cf57e518865',
'found': False}]}
# when (mock_request completes the post request)
rv = self.client.post('/search/')
# then
self.assertEqual(rv.status_code, 200)
self.assertIsNotNone(self.get_context_variable('search_res'))
self.assertTrue(self.get_context_variable('search_stats') is not None)
self.assertEqual(len(self.get_context_variable('search_res')), 2)
stats = self.get_context_variable('search_stats')
self.assertEqual(stats['nbfiles'], 2)
self.assertEqual(stats['pct'], 0)
a, b = self.get_context_variable('search_res')
self.assertEqual(a['found'], False)
self.assertEqual(b['found'], False)
self.assertEqual(self.get_context_variable('message'), '')
self.assert_template_used('search.html')
@patch('swh.web.ui.views.browse.request')
@patch('swh.web.ui.views.browse.api')
@istest
def search_post_hashes_some(self, mock_api, mock_request):
# given
mock_request.form = {'a': '456caf10e9535160d90e874b45aa426de762f19f',
'b': '745bab676c8f3cec8016e0c39ea61cf57e518865'}
mock_request.method = 'POST'
mock_api.api_search.return_value = {
'search_stats': {'nbfiles': 2, 'pct': 50},
'search_res': [{'filename': 'a',
'sha1': '456caf10e9535160d90e874b45aa426de762f19f',
'found': False},
{'filename': 'b',
'sha1': '745bab676c8f3cec8016e0c39ea61cf57e518865',
'found': True}]}
# when (mock_request completes the post request)
rv = self.client.post('/search/')
# then
self.assertEqual(rv.status_code, 200)
self.assertIsNotNone(self.get_context_variable('search_res'))
self.assertEqual(len(self.get_context_variable('search_res')), 2)
self.assertTrue(self.get_context_variable('search_stats') is not None)
stats = self.get_context_variable('search_stats')
self.assertEqual(stats['nbfiles'], 2)
self.assertEqual(stats['pct'], 50)
self.assertEqual(self.get_context_variable('message'), '')
a, b = self.get_context_variable('search_res')
self.assertEqual(a['found'], False)
self.assertEqual(b['found'], True)
self.assert_template_used('search.html')
class ContentView(test_app.SWHViewTestCase):
render_template = False
@patch('swh.web.ui.views.browse.api')
@istest
def browse_content_ko_not_found(self, mock_api):
# given
mock_api.api_content_metadata.side_effect = NotFoundExc(
'Not found!')
# when
rv = self.client.get('/browse/content/sha1:sha1-hash/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('content.html')
self.assertEqual(self.get_context_variable('message'),
'Not found!')
self.assertIsNone(self.get_context_variable('content'))
mock_api.api_content_metadata.assert_called_once_with(
'sha1:sha1-hash')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_content_ko_bad_input(self, mock_api):
# given
mock_api.api_content_metadata.side_effect = BadInputExc(
'Bad input!')
# when
rv = self.client.get('/browse/content/sha1:sha1-hash/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('content.html')
self.assertEqual(self.get_context_variable('message'),
'Bad input!')
self.assertIsNone(self.get_context_variable('content'))
mock_api.api_content_metadata.assert_called_once_with(
'sha1:sha1-hash')
@patch('swh.web.ui.views.browse.service')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_content(self, mock_api, mock_service):
# given
stub_content = {'sha1': 'sha1_hash'}
mock_api.api_content_metadata.return_value = stub_content
mock_service.lookup_content_raw.return_value = {'data': b'blah'}
expected_content = {'sha1': 'sha1_hash',
'data': 'blah'}
# when
rv = self.client.get('/browse/content/sha1:sha1-hash/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('content.html')
self.assertIsNone(self.get_context_variable('message'))
self.assertEqual(self.get_context_variable('content'),
expected_content)
mock_service.lookup_content_raw.assert_called_once_with(
'sha1:sha1-hash')
mock_api.api_content_metadata.assert_called_once_with(
'sha1:sha1-hash')
@patch('swh.web.ui.views.browse.redirect')
@patch('swh.web.ui.views.browse.url_for')
@istest
def browse_content_raw(self, mock_urlfor, mock_redirect):
# given
stub_content_raw = b'some-data'
mock_urlfor.return_value = '/api/content/sha1:sha1-hash/raw/'
mock_redirect.return_value = stub_content_raw
# when
rv = self.client.get('/browse/content/sha1:sha1-hash/raw/')
self.assertEqual(rv.status_code, 200)
self.assertEqual(rv.data, stub_content_raw)
mock_urlfor.assert_called_once_with('api_content_raw',
q='sha1:sha1-hash')
mock_redirect.assert_called_once_with(
'/api/content/sha1:sha1-hash/raw/')
class DirectoryView(test_app.SWHViewTestCase):
render_template = False
@patch('swh.web.ui.views.browse.api')
@istest
def browse_directory_ko_bad_input(self, mock_api):
# given
mock_api.api_directory.side_effect = BadInputExc(
'Invalid hash')
# when
rv = self.client.get('/browse/directory/sha2-invalid/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('directory.html')
self.assertEqual(self.get_context_variable('message'),
'Invalid hash')
self.assertEqual(self.get_context_variable('files'), [])
mock_api.api_directory.assert_called_once_with(
'sha2-invalid')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_directory_empty_result(self, mock_api):
# given
mock_api.api_directory.return_value = []
# when
rv = self.client.get('/browse/directory/some-sha1/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('directory.html')
self.assertEqual(self.get_context_variable('message'),
'Listing for directory some-sha1:')
self.assertEqual(self.get_context_variable('files'), [])
mock_api.api_directory.assert_called_once_with(
'some-sha1')
@patch('swh.web.ui.views.browse.service')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_directory_relative_file(self, mock_api, mock_service):
# given
stub_entry = {
'sha256': '240',
'type': 'file'
}
mock_service.lookup_directory_with_path.return_value = stub_entry
stub_file = {
'sha1_git': '123',
'sha1': '456',
'status': 'visible',
'data_url': '/api/1/content/890',
'length': 42,
'ctime': 'Thu, 01 Oct 2015 12:13:53 GMT',
'target': 'file.txt',
'sha256': '148'
}
mock_api.api_content_metadata.return_value = stub_file
mock_service.lookup_content_raw.return_value = {
'data': 'this is my file'}
# when
rv = self.client.get('/browse/directory/sha1/path/to/file/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('content.html')
self.assertIsNotNone(self.get_context_variable('content'))
content = self.get_context_variable('content')
# change caused by call to prepare_data_for_view
self.assertEqual(content['data_url'], '/browse/content/890')
self.assertEqual(content['data'], 'this is my file')
mock_api.api_content_metadata.assert_called_once_with('sha256:240')
mock_service.lookup_content_raw.assert_called_once_with('sha256:240')
@patch('swh.web.ui.views.browse.service')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_directory_relative_dir(self, mock_api, mock_service):
# given
mock_service.lookup_directory_with_path.return_value = {
'sha256': '240',
'target': 'abcd',
'type': 'dir'
}
stub_directory_ls = [
{'type': 'dir',
'target': '123',
'name': 'some-dir-name'},
{'type': 'file',
'sha1': '654',
'name': 'some-filename'},
{'type': 'dir',
'target': '987',
'name': 'some-other-dirname'}
]
mock_api.api_directory.return_value = stub_directory_ls
# when
rv = self.client.get('/browse/directory/sha1/path/to/dir/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('directory.html')
self.assertIsNotNone(self.get_context_variable('files'))
self.assertEqual(len(self.get_context_variable('files')),
len(stub_directory_ls))
mock_api.api_directory.assert_called_once_with('abcd')
@patch('swh.web.ui.views.browse.service')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_directory_relative_not_found(self, mock_api, mock_service):
# given
mock_service.lookup_directory_with_path.side_effect = NotFoundExc(
'Directory entry not found.')
# when
rv = self.client.get('/browse/directory/some-sha1/some/path/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('directory.html')
self.assertEqual(self.get_context_variable('message'),
'Directory entry not found.')
@patch('swh.web.ui.views.browse.api')
@patch('swh.web.ui.views.browse.utils')
@istest
def browse_directory(self, mock_utils, mock_api):
# given
stub_directory_ls = [
{'type': 'dir',
'target': '123',
'name': 'some-dir-name'},
{'type': 'file',
'sha1': '654',
'name': 'some-filename'},
{'type': 'dir',
'target': '987',
'name': 'some-other-dirname'}
]
mock_api.api_directory.return_value = stub_directory_ls
stub_directory_map = [
{'link': '/path/to/url/dir/123',
'name': 'some-dir-name'},
{'link': '/path/to/url/file/654',
'name': 'some-filename'},
{'link': '/path/to/url/dir/987',
'name': 'some-other-dirname'}
]
mock_utils.prepare_data_for_view.return_value = stub_directory_map
# when
rv = self.client.get('/browse/directory/some-sha1/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('directory.html')
self.assertEqual(self.get_context_variable('message'),
'Listing for directory some-sha1:')
self.assertEqual(self.get_context_variable('files'),
stub_directory_map)
mock_api.api_directory.assert_called_once_with(
'some-sha1')
mock_utils.prepare_data_for_view.assert_called_once_with(
stub_directory_ls)
class ContentWithOriginView(test_app.SWHViewTestCase):
render_template = False
@patch('swh.web.ui.views.browse.api')
# @istest
def browse_content_with_origin_content_ko_not_found(self, mock_api):
# given
mock_api.api_content_checksum_to_origin.side_effect = NotFoundExc(
'Not found!')
# when
rv = self.client.get('/browse/content/sha256:some-sha256/origin/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('content-with-origin.html')
self.assertEqual(self.get_context_variable('message'),
'Not found!')
mock_api.api_content_checksum_to_origin.assert_called_once_with(
'sha256:some-sha256')
@patch('swh.web.ui.views.browse.api')
# @istest
def browse_content_with_origin_ko_bad_input(self, mock_api):
# given
mock_api.api_content_checksum_to_origin.side_effect = BadInputExc(
'Invalid hash')
# when
rv = self.client.get('/browse/content/sha256:some-sha256/origin/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('content-with-origin.html')
self.assertEqual(
self.get_context_variable('message'), 'Invalid hash')
mock_api.api_content_checksum_to_origin.assert_called_once_with(
'sha256:some-sha256')
@patch('swh.web.ui.views.browse.api')
# @istest
def browse_content_with_origin(self, mock_api):
# given
mock_api.api_content_checksum_to_origin.return_value = {
'origin_type': 'ftp',
'origin_url': '/some/url',
'revision': 'revision-hash',
'branch': 'master',
'path': '/path/to',
}
# when
rv = self.client.get('/browse/content/sha256:some-sha256/origin/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('content-with-origin.html')
self.assertEqual(
self.get_context_variable('message'),
"The content with hash sha256:some-sha256 has been seen on " +
"origin with type 'ftp'\n" +
"at url '/some/url'. The revision was identified at " +
"'revision-hash' on branch 'master'.\n" +
"The file's path referenced was '/path/to'.")
mock_api.api_content_checksum_to_origin.assert_called_once_with(
'sha256:some-sha256')
class OriginView(test_app.SWHViewTestCase):
render_template = False
@patch('swh.web.ui.views.browse.api')
@istest
def browse_origin_ko_not_found(self, mock_api):
# given
mock_api.api_origin.side_effect = NotFoundExc('Not found!')
# when
rv = self.client.get('/browse/origin/1/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('origin.html')
self.assertEqual(self.get_context_variable('origin_id'), 1)
self.assertEqual(
self.get_context_variable('message'),
'Not found!')
mock_api.api_origin.assert_called_once_with(1)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_origin_ko_bad_input(self, mock_api):
# given
mock_api.api_origin.side_effect = BadInputExc('wrong input')
# when
rv = self.client.get('/browse/origin/426/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('origin.html')
self.assertEqual(self.get_context_variable('origin_id'), 426)
mock_api.api_origin.assert_called_once_with(426)
@patch('swh.web.ui.views.browse.api')
@patch('swh.web.ui.views.browse.url_for')
@istest
def browse_origin_found(self, mock_url_for, mock_api):
# given
def url_for_test(fn, **args):
if fn == 'browse_revision_with_origin':
return '/browse/revision/origin/%s/' % args['origin_id']
elif fn == 'api_origin_visits':
return '/api/1/stat/visits/%s/' % args['origin_id']
mock_url_for.side_effect = url_for_test
mock_origin = {'type': 'git',
'lister': None,
'project': None,
'url': 'rsync://some/url',
'id': 426}
mock_api.api_origin.return_value = mock_origin
# when
rv = self.client.get('/browse/origin/426/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('origin.html')
self.assertEqual(self.get_context_variable('origin_id'), 426)
self.assertEqual(self.get_context_variable('origin'), mock_origin)
self.assertEqual(self.get_context_variable('browse_url'),
'/browse/revision/origin/426/')
self.assertEqual(self.get_context_variable('visit_url'),
'/api/1/stat/visits/426/')
mock_api.api_origin.assert_called_once_with(426)
class PersonView(test_app.SWHViewTestCase):
render_template = False
@patch('swh.web.ui.views.browse.api')
@istest
def browse_person_ko_not_found(self, mock_api):
# given
mock_api.api_person.side_effect = NotFoundExc('not found')
# when
rv = self.client.get('/browse/person/1/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('person.html')
self.assertEqual(self.get_context_variable('person_id'), 1)
self.assertEqual(
self.get_context_variable('message'),
'not found')
mock_api.api_person.assert_called_once_with(1)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_person_ko_bad_input(self, mock_api):
# given
mock_api.api_person.side_effect = BadInputExc('wrong input')
# when
rv = self.client.get('/browse/person/426/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('person.html')
self.assertEqual(self.get_context_variable('person_id'), 426)
mock_api.api_person.assert_called_once_with(426)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_person(self, mock_api):
# given
mock_person = {'type': 'git',
'lister': None,
'project': None,
'url': 'rsync://some/url',
'id': 426}
mock_api.api_person.return_value = mock_person
# when
rv = self.client.get('/browse/person/426/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('person.html')
self.assertEqual(self.get_context_variable('person_id'), 426)
self.assertEqual(self.get_context_variable('person'), mock_person)
mock_api.api_person.assert_called_once_with(426)
class ReleaseView(test_app.SWHViewTestCase):
render_template = False
@patch('swh.web.ui.views.browse.api')
@istest
def browse_release_ko_not_found(self, mock_api):
# given
mock_api.api_release.side_effect = NotFoundExc('not found!')
# when
rv = self.client.get('/browse/release/1/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('release.html')
self.assertEqual(self.get_context_variable('sha1_git'), '1')
self.assertEqual(
self.get_context_variable('message'),
'not found!')
mock_api.api_release.assert_called_once_with('1')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_release_ko_bad_input(self, mock_api):
# given
mock_api.api_release.side_effect = BadInputExc('wrong input')
# when
rv = self.client.get('/browse/release/426/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('release.html')
self.assertEqual(self.get_context_variable('sha1_git'), '426')
mock_api.api_release.assert_called_once_with('426')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_release(self, mock_api):
# given
self.maxDiff = None
mock_release = {
"date": "Sun, 05 Jul 2015 18:02:06 GMT",
"id": "1e951912027ea6873da6985b91e50c47f645ae1a",
"target": "d770e558e21961ad6cfdf0ff7df0eb5d7d4f0754",
"target_url": '/browse/revision/d770e558e21961ad6cfdf0ff7df0'
'eb5d7d4f0754/',
"synthetic": False,
"target_type": "revision",
"author": {
"email": "torvalds@linux-foundation.org",
"name": "Linus Torvalds"
},
"message": "Linux 4.2-rc1\n",
"name": "v4.2-rc1"
}
mock_api.api_release.return_value = mock_release
expected_release = {
"date": "Sun, 05 Jul 2015 18:02:06 GMT",
"id": "1e951912027ea6873da6985b91e50c47f645ae1a",
"target_url": '/browse/revision/d770e558e21961ad6cfdf0ff7df0'
'eb5d7d4f0754/',
"target": 'd770e558e21961ad6cfdf0ff7df0eb5d7d4f0754',
"synthetic": False,
"target_type": "revision",
"author": {
"email": "torvalds@linux-foundation.org",
"name": "Linus Torvalds"
},
"message": "Linux 4.2-rc1\n",
"name": "v4.2-rc1"
}
# when
rv = self.client.get('/browse/release/426/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('release.html')
self.assertEqual(self.get_context_variable('sha1_git'), '426')
self.assertEqual(self.get_context_variable('release'),
expected_release)
mock_api.api_release.assert_called_once_with('426')
class RevisionView(test_app.SWHViewTestCase):
render_template = False
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_ko_not_found(self, mock_api):
# given
mock_api.api_revision.side_effect = NotFoundExc('Not found!')
# when
rv = self.client.get('/browse/revision/1/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision.html')
self.assertEqual(self.get_context_variable('sha1_git'), '1')
self.assertEqual(
self.get_context_variable('message'),
'Not found!')
self.assertIsNone(self.get_context_variable('revision'))
mock_api.api_revision.assert_called_once_with('1', None)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_ko_bad_input(self, mock_api):
# given
mock_api.api_revision.side_effect = BadInputExc('wrong input!')
# when
rv = self.client.get('/browse/revision/426/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision.html')
self.assertEqual(self.get_context_variable('sha1_git'), '426')
self.assertEqual(
self.get_context_variable('message'),
'wrong input!')
self.assertIsNone(self.get_context_variable('revision'))
mock_api.api_revision.assert_called_once_with('426', None)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision(self, mock_api):
# given
stub_revision = {
'id': 'd770e558e21961ad6cfdf0ff7df0eb5d7d4f0754',
'date': 'Sun, 05 Jul 2015 18:01:52 GMT',
'committer': {
'email': 'torvalds@linux-foundation.org',
'name': 'Linus Torvalds'
},
'committer_date': 'Sun, 05 Jul 2015 18:01:52 GMT',
'type': 'git',
'author': {
'email': 'torvalds@linux-foundation.org',
'name': 'Linus Torvalds'
},
'message': 'Linux 4.2-rc1\n',
'synthetic': False,
'directory_url': '/api/1/directory/'
'2a1dbabeed4dcf1f4a4c441993b2ffc9d972780b/',
'parent_url': [
'/api/1/revision/a585d2b738bfa26326b3f1f40f0f1eda0c067ccf/'
],
}
mock_api.api_revision.return_value = stub_revision
expected_revision = {
'id': 'd770e558e21961ad6cfdf0ff7df0eb5d7d4f0754',
'date': 'Sun, 05 Jul 2015 18:01:52 GMT',
'committer': {
'email': 'torvalds@linux-foundation.org',
'name': 'Linus Torvalds'
},
'committer_date': 'Sun, 05 Jul 2015 18:01:52 GMT',
'type': 'git',
'author': {
'email': 'torvalds@linux-foundation.org',
'name': 'Linus Torvalds'
},
'message': 'Linux 4.2-rc1\n',
'synthetic': False,
'parent_url': [
'/browse/revision/a585d2b738bfa26326b3f1f40f0f1eda0c067ccf/'
],
'directory_url': '/browse/directory/2a1dbabeed4dcf1f4a4c441993b2f'
'fc9d972780b/',
}
# when
rv = self.client.get('/browse/revision/426/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision.html')
self.assertEqual(self.get_context_variable('sha1_git'), '426')
self.assertEqual(self.get_context_variable('revision'),
expected_revision)
self.assertIsNone(self.get_context_variable('message'))
mock_api.api_revision.assert_called_once_with('426', None)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_raw_message(self, mock_api):
# given
sha1 = 'd770e558e21961ad6cfdf0ff7df0eb5d7d4f0754'
# when
rv = self.client.get('/browse/revision/'
'd770e558e21961ad6cfdf0ff7df0eb5d7d4f0754/raw/')
self.assertRedirects(
rv, '/api/1/revision/%s/raw/' % sha1)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_log_ko_not_found(self, mock_api):
# given
mock_api.api_revision_log.side_effect = NotFoundExc('Not found!')
# when
rv = self.client.get('/browse/revision/sha1/log/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-log.html')
self.assertEqual(self.get_context_variable('sha1_git'), 'sha1')
self.assertEqual(
self.get_context_variable('message'),
'Not found!')
self.assertEqual(self.get_context_variable('revisions'), [])
mock_api.api_revision_log.assert_called_once_with('sha1', None)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_log_ko_bad_input(self, mock_api):
# given
mock_api.api_revision_log.side_effect = BadInputExc('wrong input!')
# when
rv = self.client.get('/browse/revision/426/log/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-log.html')
self.assertEqual(self.get_context_variable('sha1_git'), '426')
self.assertEqual(
self.get_context_variable('message'),
'wrong input!')
self.assertEqual(self.get_context_variable('revisions'), [])
mock_api.api_revision_log.assert_called_once_with('426', None)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_log(self, mock_api):
# given
stub_revisions = {
'revisions': [{
'id': 'd770e558e21961ad6cfdf0ff7df0eb5d7d4f0754',
'date': 'Sun, 05 Jul 2015 18:01:52 GMT',
'committer': {
'email': 'torvalds@linux-foundation.org',
'name': 'Linus Torvalds'
},
'committer_date': 'Sun, 05 Jul 2015 18:01:52 GMT',
'type': 'git',
'author': {
'email': 'torvalds@linux-foundation.org',
'name': 'Linus Torvalds'
},
'message': 'Linux 4.2-rc1\n',
'synthetic': False,
'directory_url': '/api/1/directory/'
'2a1dbabeed4dcf1f4a4c441993b2ffc9d972780b/',
'parent_url': [
'/api/1/revision/a585d2b738bfa26326b3f1f40f0f1eda0c067ccf/'
],
}],
'next_revs_url': '/api/1/revision/1234/log/'
}
mock_api.api_revision_log.return_value = stub_revisions
# when
rv = self.client.get('/browse/revision/426/log/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-log.html')
self.assertEqual(self.get_context_variable('sha1_git'), '426')
self.assertTrue(
isinstance(self.get_context_variable('revisions'), map))
self.assertEqual(
self.get_context_variable('next_revs_url'),
'/browse/revision/1234/log/')
self.assertIsNone(self.get_context_variable('message'))
mock_api.api_revision_log.assert_called_once_with('426', None)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_log_by_ko_not_found(self, mock_api):
# given
mock_api.api_revision_log_by.side_effect = NotFoundExc('Not found!')
# when
rv = self.client.get('/browse/revision/origin/9/log/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-log.html')
self.assertEqual(self.get_context_variable('origin_id'), 9)
self.assertEqual(
self.get_context_variable('message'),
'Not found!')
self.assertEqual(self.get_context_variable('revisions'), [])
mock_api.api_revision_log_by.assert_called_once_with(
9, 'refs/heads/master', None)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_log_by_ko_bad_input(self, mock_api):
# given
mock_api.api_revision_log.side_effect = BadInputExc('wrong input!')
# when
rv = self.client.get('/browse/revision/abcd/log/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-log.html')
self.assertEqual(self.get_context_variable('sha1_git'), 'abcd')
self.assertEqual(
self.get_context_variable('message'),
'wrong input!')
self.assertEqual(self.get_context_variable('revisions'), [])
mock_api.api_revision_log.assert_called_once_with('abcd', None)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_log_by(self, mock_api):
# given
stub_revisions = [{
'id': 'd770e558e21961ad6cfdf0ff7df0eb5d7d4f0754',
'date': 'Sun, 05 Jul 2015 18:01:52 GMT',
'committer': {
'email': 'torvalds@linux-foundation.org',
'name': 'Linus Torvalds'
},
'committer_date': 'Sun, 05 Jul 2015 18:01:52 GMT',
'type': 'git',
'author': {
'email': 'torvalds@linux-foundation.org',
'name': 'Linus Torvalds'
},
'message': 'Linux 4.2-rc1\n',
'synthetic': False,
'directory_url': '/api/1/directory/'
'2a1dbabeed4dcf1f4a4c441993b2ffc9d972780b/',
'parent_url': [
'/api/1/revision/a585d2b738bfa26326b3f1f40f0f1eda0c067ccf/'
],
}]
mock_api.api_revision_log_by.return_value = stub_revisions
# when
rv = self.client.get('/browse/revision/origin/2/log/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-log.html')
self.assertEqual(self.get_context_variable('origin_id'), 2)
self.assertTrue(
isinstance(self.get_context_variable('revisions'), map))
self.assertIsNone(self.get_context_variable('message'))
mock_api.api_revision_log_by.assert_called_once_with(
2, 'refs/heads/master', None)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_history_ko_not_found(self, mock_api):
# given
mock_api.api_revision_history.side_effect = NotFoundExc(
'Not found')
# when
rv = self.client.get('/browse/revision/1/history/2/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision.html')
self.assertEqual(self.get_context_variable('sha1_git_root'), '1')
self.assertEqual(self.get_context_variable('sha1_git'), '2')
self.assertEqual(
self.get_context_variable('message'),
'Not found')
mock_api.api_revision_history.assert_called_once_with(
'1', '2')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_history_ko_bad_input(self, mock_api):
# given
mock_api.api_revision_history.side_effect = BadInputExc(
'Input incorrect')
# when
rv = self.client.get('/browse/revision/321/history/654/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision.html')
self.assertEqual(self.get_context_variable('sha1_git_root'), '321')
self.assertEqual(self.get_context_variable('sha1_git'), '654')
self.assertEqual(
self.get_context_variable('message'),
'Input incorrect')
mock_api.api_revision_history.assert_called_once_with(
'321', '654')
@istest
def browse_revision_history_ok_same_sha1(self):
# when
rv = self.client.get('/browse/revision/10/history/10/')
# then
self.assertEqual(rv.status_code, 302)
@patch('swh.web.ui.views.browse.utils')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_history(self, mock_api, mock_utils):
# given
stub_revision = {'id': 'some-rev'}
mock_api.api_revision_history.return_value = stub_revision
expected_revision = {
'id': 'some-rev-id',
'author': {'name': 'foo', 'email': 'bar'},
'committer': {'name': 'foo', 'email': 'bar'}
}
mock_utils.prepare_data_for_view.return_value = expected_revision
# when
rv = self.client.get('/browse/revision/426/history/789/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision.html')
self.assertEqual(self.get_context_variable('sha1_git_root'), '426')
self.assertEqual(self.get_context_variable('sha1_git'), '789')
self.assertEqual(self.get_context_variable('revision'),
expected_revision)
mock_api.api_revision_history.assert_called_once_with(
'426', '789')
mock_utils.prepare_data_for_view.assert_called_once_with(stub_revision)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_directory_ko_not_found(self, mock_api):
# given
mock_api.api_revision_directory.side_effect = NotFoundExc('Not found!')
# when
rv = self.client.get('/browse/revision/1/directory/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-directory.html')
self.assertEqual(self.get_context_variable('sha1_git'), '1')
self.assertEqual(self.get_context_variable('path'), '.')
self.assertIsNone(self.get_context_variable('result'))
self.assertEqual(
self.get_context_variable('message'),
"Not found!")
mock_api.api_revision_directory.assert_called_once_with(
'1', None, with_data=True)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_directory_ko_bad_input(self, mock_api):
# given
mock_api.api_revision_directory.side_effect = BadInputExc('Bad input!')
# when
rv = self.client.get('/browse/revision/10/directory/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-directory.html')
self.assertEqual(self.get_context_variable('sha1_git'), '10')
self.assertEqual(self.get_context_variable('path'), '.')
self.assertIsNone(self.get_context_variable('result'))
self.assertEqual(
self.get_context_variable('message'),
"Bad input!")
mock_api.api_revision_directory.assert_called_once_with(
'10', None, with_data=True)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_directory(self, mock_api):
# given
stub_result0 = {
'type': 'dir',
'revision': '100',
'content': [
{
'id': 'some-result',
'type': 'file',
'name': 'blah',
},
{
'id': 'some-other-result',
'type': 'dir',
'name': 'foo',
}
]
}
mock_api.api_revision_directory.return_value = stub_result0
stub_result1 = {
'type': 'dir',
'revision': '100',
'content':
[
{
'id': 'some-result',
'type': 'file',
'name': 'blah',
},
{
'id': 'some-other-result',
'type': 'dir',
'name': 'foo',
}
]
}
# when
rv = self.client.get('/browse/revision/100/directory/some/path/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-directory.html')
self.assertEqual(self.get_context_variable('sha1_git'), '100')
self.assertEqual(self.get_context_variable('revision'), '100')
self.assertEqual(self.get_context_variable('path'), 'some/path')
self.assertIsNone(self.get_context_variable('message'))
self.assertEqual(self.get_context_variable('result'), stub_result1)
mock_api.api_revision_directory.assert_called_once_with(
'100', 'some/path', with_data=True)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_history_directory_ko_not_found(self, mock_api):
# given
mock_api.api_revision_history_directory.side_effect = NotFoundExc(
'not found')
# when
rv = self.client.get('/browse/revision/123/history/456/directory/a/b/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-directory.html')
self.assertEqual(self.get_context_variable('sha1_git_root'), '123')
self.assertEqual(self.get_context_variable('sha1_git'), '456')
self.assertEqual(self.get_context_variable('path'), 'a/b')
self.assertEqual(self.get_context_variable('message'), 'not found')
self.assertIsNone(self.get_context_variable('result'))
mock_api.api_revision_history_directory.assert_called_once_with(
'123', '456', 'a/b', with_data=True)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_history_directory_ko_bad_input(self, mock_api):
# given
mock_api.api_revision_history_directory.side_effect = BadInputExc(
'bad input')
# when
rv = self.client.get('/browse/revision/123/history/456/directory/a/c/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-directory.html')
self.assertEqual(self.get_context_variable('sha1_git_root'), '123')
self.assertEqual(self.get_context_variable('sha1_git'), '456')
self.assertEqual(self.get_context_variable('path'), 'a/c')
self.assertEqual(self.get_context_variable('message'), 'bad input')
self.assertIsNone(self.get_context_variable('result'))
mock_api.api_revision_history_directory.assert_called_once_with(
'123', '456', 'a/c', with_data=True)
@patch('swh.web.ui.views.browse.service')
@istest
def browse_revision_history_directory_ok_no_trailing_slash_so_redirect(
self, mock_service):
# when
rv = self.client.get('/browse/revision/1/history/2/directory/path/to')
# then
self.assertEqual(rv.status_code, 301)
@patch('swh.web.ui.views.browse.service')
@istest
def browse_revision_history_directory_ok_same_sha1_redirects(
self, mock_service):
# when
rv = self.client.get('/browse/revision/1/history/1/directory/path/to')
# then
self.assertEqual(rv.status_code, 301)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_history_directory(self, mock_api):
# given
stub_result0 = {
'type': 'dir',
'revision': '1000',
'content': [{
'id': 'some-result',
'type': 'file',
'name': 'blah'
}]
}
mock_api.api_revision_history_directory.return_value = stub_result0
stub_result1 = {
'type': 'dir',
'revision': '1000',
'content': [{
'id': 'some-result',
'type': 'file',
'name': 'blah'
}]
}
# when
rv = self.client.get('/browse/revision/100/history/999/directory/'
'path/to/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-directory.html')
self.assertEqual(self.get_context_variable('sha1_git_root'), '100')
self.assertEqual(self.get_context_variable('sha1_git'), '999')
self.assertEqual(self.get_context_variable('revision'), '1000')
self.assertEqual(self.get_context_variable('path'), 'path/to')
self.assertIsNone(self.get_context_variable('message'))
self.assertEqual(self.get_context_variable('result'), stub_result1)
mock_api.api_revision_history_directory.assert_called_once_with(
'100', '999', 'path/to', with_data=True)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_history_through_origin_ko_bad_input(self, mock_api):
# given
mock_api.api_revision_history_through_origin.side_effect = BadInputExc(
'Problem input.') # noqa
# when
rv = self.client.get('/browse/revision/origin/99'
'/history/123/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision.html')
self.assertIsNone(self.get_context_variable('revision'))
self.assertEqual(self.get_context_variable('message'),
'Problem input.')
mock_api.api_revision_history_through_origin.assert_called_once_with(
99, 'refs/heads/master', None, '123')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_history_through_origin_ko_not_found(self, mock_api):
# given
mock_api.api_revision_history_through_origin.side_effect = NotFoundExc(
'Not found.')
# when
rv = self.client.get('/browse/revision/origin/999/'
'branch/dev/history/123/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision.html')
self.assertIsNone(self.get_context_variable('revision'))
self.assertEqual(self.get_context_variable('message'),
'Not found.')
mock_api.api_revision_history_through_origin.assert_called_once_with(
999, 'dev', None, '123')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_history_through_origin_ko_other_error(self, mock_api):
# given
mock_api.api_revision_history_through_origin.side_effect = ValueError(
'Other Error.')
# when
rv = self.client.get('/browse/revision/origin/438'
'/branch/scratch'
'/ts/2016'
'/history/789/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision.html')
self.assertIsNone(self.get_context_variable('revision'))
self.assertEqual(self.get_context_variable('message'),
'Other Error.')
mock_api.api_revision_history_through_origin.assert_called_once_with(
438, 'scratch', '2016', '789')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_history_through_origin(self, mock_api):
# given
stub_rev = {
'id': 'some-id',
'author': {},
'committer': {}
}
mock_api.api_revision_history_through_origin.return_value = stub_rev
# when
rv = self.client.get('/browse/revision/origin/99/history/123/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision.html')
self.assertEqual(self.get_context_variable('revision'), stub_rev)
self.assertIsNone(self.get_context_variable('message'))
mock_api.api_revision_history_through_origin.assert_called_once_with(
99, 'refs/heads/master', None, '123')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_with_origin_ko_not_found(self, mock_api):
# given
mock_api.api_revision_with_origin.side_effect = NotFoundExc(
'Not found')
# when
rv = self.client.get('/browse/revision/origin/1/')
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision.html')
self.assertIsNone(self.get_context_variable('revision'))
self.assertEqual(self.get_context_variable('message'), 'Not found')
mock_api.api_revision_with_origin.assert_called_once_with(
1, 'refs/heads/master', None)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_with_origin_ko_bad_input(self, mock_api):
# given
mock_api.api_revision_with_origin.side_effect = BadInputExc(
'Bad Input')
# when
rv = self.client.get('/browse/revision/origin/1000/branch/dev/')
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision.html')
self.assertIsNone(self.get_context_variable('revision'))
self.assertEqual(self.get_context_variable('message'), 'Bad Input')
mock_api.api_revision_with_origin.assert_called_once_with(
1000, 'dev', None)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_with_origin_ko_other(self, mock_api):
# given
mock_api.api_revision_with_origin.side_effect = ValueError(
'Other')
# when
rv = self.client.get('/browse/revision/origin/1999'
'/branch/scratch/master'
'/ts/1990-01-10/')
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision.html')
self.assertIsNone(self.get_context_variable('revision'))
self.assertEqual(self.get_context_variable('message'), 'Other')
mock_api.api_revision_with_origin.assert_called_once_with(
1999, 'scratch/master', '1990-01-10')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_with_origin(self, mock_api):
# given
stub_rev = {'id': 'some-id',
'author': {},
'committer': {}}
mock_api.api_revision_with_origin.return_value = stub_rev
# when
rv = self.client.get('/browse/revision/origin/1/')
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision.html')
self.assertEqual(self.get_context_variable('revision'), stub_rev)
self.assertIsNone(self.get_context_variable('message'))
mock_api.api_revision_with_origin.assert_called_once_with(
1, 'refs/heads/master', None)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_directory_through_origin_ko_not_found(self, mock_api):
# given
mock_api.api_directory_through_revision_origin.side_effect = BadInputExc( # noqa
'this is not the robot you are looking for')
# when
rv = self.client.get('/browse/revision/origin/2'
'/directory/')
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-directory.html')
self.assertIsNone(self.get_context_variable('result'))
self.assertEqual(self.get_context_variable('message'),
'this is not the robot you are looking for')
mock_api.api_directory_through_revision_origin.assert_called_once_with( # noqa
2, 'refs/heads/master', None, None, with_data=True)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_directory_through_origin_ko_bad_input(self, mock_api):
# given
mock_api.api_directory_through_revision_origin.side_effect = BadInputExc( # noqa
'Bad Robot')
# when
rv = self.client.get('/browse/revision/origin/2'
'/directory/')
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-directory.html')
self.assertIsNone(self.get_context_variable('result'))
self.assertEqual(self.get_context_variable('message'), 'Bad Robot')
mock_api.api_directory_through_revision_origin.assert_called_once_with(
2, 'refs/heads/master', None, None, with_data=True)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_directory_through_origin_ko_other(self, mock_api):
# given
mock_api.api_directory_through_revision_origin.side_effect = ValueError( # noqa
'Other bad stuff')
# when
rv = self.client.get('/browse/revision/origin/2'
'/directory/')
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-directory.html')
self.assertIsNone(self.get_context_variable('result'))
self.assertEqual(self.get_context_variable('message'),
'Other bad stuff')
mock_api.api_directory_through_revision_origin.assert_called_once_with(
2, 'refs/heads/master', None, None, with_data=True)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_revision_directory_through_origin(self, mock_api):
# given
stub_res = {'id': 'some-id',
'revision': 'some-rev-id',
'type': 'dir',
'content': 'some-content'}
mock_api.api_directory_through_revision_origin.return_value = stub_res
# when
rv = self.client.get('/browse/revision/origin/2'
'/branch/dev'
'/ts/2013-20-20 10:02'
'/directory/some/file/')
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-directory.html')
self.assertEqual(self.get_context_variable('result'), stub_res)
self.assertIsNone(self.get_context_variable('message'))
mock_api.api_directory_through_revision_origin.assert_called_once_with(
2, 'dev', '2013-20-20 10:02', 'some/file', with_data=True)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_directory_through_revision_with_origin_history_ko_not_found(
self, mock_api):
mock_api.api_directory_through_revision_with_origin_history.side_effect = NotFoundExc( # noqa
'Not found!')
# when
rv = self.client.get('/browse/revision/origin/987'
'/history/sha1git'
'/directory/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-directory.html')
self.assertIsNone(self.get_context_variable('result'))
self.assertEqual(self.get_context_variable('message'), 'Not found!')
self.assertEqual(self.get_context_variable('path'), '.')
mock_api.api_directory_through_revision_with_origin_history.assert_called_once_with( # noqa
987, 'refs/heads/master', None, 'sha1git', None, with_data=True)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_directory_through_revision_with_origin_history_ko_bad_input(
self, mock_api):
mock_api.api_directory_through_revision_with_origin_history.side_effect = BadInputExc( # noqa
'Bad input! Bleh!')
# when
rv = self.client.get('/browse/revision/origin/798'
'/branch/refs/heads/dev'
'/ts/2012-11-11'
'/history/1234'
'/directory/some/path/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-directory.html')
self.assertIsNone(self.get_context_variable('result'))
self.assertEqual(self.get_context_variable('message'),
'Bad input! Bleh!')
self.assertEqual(self.get_context_variable('path'), 'some/path')
mock_api.api_directory_through_revision_with_origin_history.assert_called_once_with( # noqa
798, 'refs/heads/dev', '2012-11-11', '1234', 'some/path',
with_data=True)
@patch('swh.web.ui.views.browse.api')
@istest
def browse_directory_through_revision_with_origin_history(
self, mock_api):
stub_dir = {'type': 'dir',
'content': [],
'revision': 'specific-rev-id'}
mock_api.api_directory_through_revision_with_origin_history.return_value = stub_dir # noqa
# when
rv = self.client.get('/browse/revision/origin/101010'
'/ts/1955-11-12'
'/history/54628'
'/directory/emacs-24.5/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('revision-directory.html')
self.assertEqual(self.get_context_variable('result'), stub_dir)
self.assertIsNone(self.get_context_variable('message'))
self.assertEqual(self.get_context_variable('path'), 'emacs-24.5')
mock_api.api_directory_through_revision_with_origin_history.assert_called_once_with( # noqa
101010, 'refs/heads/master', '1955-11-12', '54628', 'emacs-24.5',
with_data=True)
class EntityView(test_app.SWHViewTestCase):
render_template = False
@patch('swh.web.ui.views.browse.api')
@istest
def browse_entity_ko_not_found(self, mock_api):
# given
mock_api.api_entity_by_uuid.side_effect = NotFoundExc('Not found!')
# when
rv = self.client.get('/browse/entity/'
'5f4d4c51-498a-4e28-88b3-b3e4e8396cba/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('entity.html')
self.assertEqual(self.get_context_variable('entities'), [])
self.assertEqual(self.get_context_variable('message'), 'Not found!')
mock_api.api_entity_by_uuid.assert_called_once_with(
'5f4d4c51-498a-4e28-88b3-b3e4e8396cba')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_entity_ko_bad_input(self, mock_api):
# given
mock_api.api_entity_by_uuid.side_effect = BadInputExc('wrong input!')
# when
rv = self.client.get('/browse/entity/blah-blah-uuid/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('entity.html')
self.assertEqual(self.get_context_variable('entities'), [])
self.assertEqual(self.get_context_variable('message'), 'wrong input!')
mock_api.api_entity_by_uuid.assert_called_once_with(
'blah-blah-uuid')
@patch('swh.web.ui.views.browse.api')
@istest
def browse_entity(self, mock_api):
# given
stub_entities = [
{'id': '5f4d4c51-5a9b-4e28-88b3-b3e4e8396cba'}]
mock_api.api_entity_by_uuid.return_value = stub_entities
# when
rv = self.client.get('/browse/entity/'
'5f4d4c51-5a9b-4e28-88b3-b3e4e8396cba/')
# then
self.assertEqual(rv.status_code, 200)
self.assert_template_used('entity.html')
self.assertEqual(self.get_context_variable('entities'), stub_entities)
self.assertIsNone(self.get_context_variable('message'))
mock_api.api_entity_by_uuid.assert_called_once_with(
'5f4d4c51-5a9b-4e28-88b3-b3e4e8396cba')
diff --git a/swh/web/ui/views/browse.py b/swh/web/ui/views/browse.py
index 95e1da18a..f6e03d18f 100644
--- a/swh/web/ui/views/browse.py
+++ b/swh/web/ui/views/browse.py
@@ -1,846 +1,859 @@
# Copyright (C) 2015 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
from encodings.aliases import aliases
from flask import render_template, request, url_for, redirect
from flask.ext.api.decorators import set_renderers
from flask.ext.api.renderers import HTMLRenderer
from swh.core.hashutil import ALGORITHMS
-from .. import service, utils
+from .. import service, utils, apidoc
from ..exc import BadInputExc, NotFoundExc
from ..main import app
from . import api
hash_filter_keys = ALGORITHMS
+@app.route('/api/1/doc/')
+@set_renderers(HTMLRenderer)
+def api_doc():
+ """Render the API's documentation.
+ """
+ routes = apidoc.APIUrls.get_app_endpoints()
+ # Return a list of routes with consistent ordering
+ env = {
+ 'doc_routes': sorted(routes.items())
+ }
+ return render_template('api.html', **env)
+
+
@app.route('/search/', methods=['GET', 'POST'])
@set_renderers(HTMLRenderer)
def search():
"""Search for hashes in swh-storage.
One form to submit either:
- hash query to look up in swh storage
- file hashes calculated client-side to be queried in swh storage
- both
Returns:
dict representing data to look for in swh storage.
The following keys are returned:
- search_stats: {'nbfiles': X, 'pct': Y} the number of total
queried files and percentage of files not in storage respectively
- responses: array of {'filename': X, 'sha1': Y, 'found': Z}
- messages: General messages.
TODO:
Batch-process with all checksums, not just sha1
"""
env = {'search_res': None,
'search_stats': None,
'message': []}
search_stats = {'nbfiles': 0, 'pct': 0}
search_res = None
message = ''
# Get with a single hash request
if request.method == 'GET':
data = request.args
q = data.get('q')
if q:
try:
search = api.api_search(q)
search_res = search['search_res']
search_stats = search['search_stats']
except BadInputExc as e:
message = str(e)
# Post form submission with many hash requests
elif request.method == 'POST':
try:
search = api.api_search(None)
search_res = search['search_res']
search_stats = search['search_stats']
except BadInputExc as e:
message = str(e)
env['search_stats'] = search_stats
env['search_res'] = search_res
env['message'] = message
return render_template('search.html', **env)
@app.route('/browse/content//')
@set_renderers(HTMLRenderer)
def browse_content(q):
"""Given a hash and a checksum, display the content's meta-data.
Args:
q is of the form algo_hash:hash with algo_hash in
(sha1, sha1_git, sha256)
Returns:
Information on one possible origin for such content.
Raises:
BadInputExc in case of unknown algo_hash or bad hash
NotFoundExc if the content is not found.
"""
env = {'q': q,
'message': None,
'content': None}
encoding = request.args.get('encoding', 'utf8')
if encoding not in aliases:
env['message'] = 'Encoding %s not supported.' \
'Supported Encodings: %s' % (
encoding, list(aliases.keys()))
return render_template('content.html', **env)
try:
content = api.api_content_metadata(q)
content_raw = service.lookup_content_raw(q)
if content_raw:
content['data'] = content_raw['data']
env['content'] = utils.prepare_data_for_view(content,
encoding=encoding)
except (NotFoundExc, BadInputExc) as e:
env['message'] = str(e)
return render_template('content.html', **env)
@app.route('/browse/content//raw/')
def browse_content_raw(q):
"""Given a hash and a checksum, display the content's raw data.
Args:
q is of the form algo_hash:hash with algo_hash in
(sha1, sha1_git, sha256)
Returns:
Information on one possible origin for such content.
Raises:
BadInputExc in case of unknown algo_hash or bad hash
NotFoundExc if the content is not found.
"""
return redirect(url_for('api_content_raw', q=q))
def _origin_seen(q, data):
"""Given an origin, compute a message string with the right information.
Args:
origin: a dictionary with keys:
- origin: a dictionary with type and url keys
- occurrence: a dictionary with a validity range
Returns:
Message as a string
"""
origin_type = data['origin_type']
origin_url = data['origin_url']
revision = data['revision']
branch = data['branch']
path = data['path']
return """The content with hash %s has been seen on origin with type '%s'
at url '%s'. The revision was identified at '%s' on branch '%s'.
The file's path referenced was '%s'.""" % (q,
origin_type,
origin_url,
revision,
branch,
path)
# @app.route('/browse/content//origin/')
@set_renderers(HTMLRenderer)
def browse_content_with_origin(q):
"""Show content information.
Args:
- q: query string of the form with
`algo_hash` in sha1, sha1_git, sha256.
This means that several different URLs (at least one per
HASH_ALGO) will point to the same content sha: the sha with
'hash' format
Returns:
The content's information at for a given checksum.
"""
env = {'q': q}
try:
origin = api.api_content_checksum_to_origin(q)
message = _origin_seen(q, origin)
except (NotFoundExc, BadInputExc) as e:
message = str(e)
env['message'] = message
return render_template('content-with-origin.html', **env)
@app.route('/browse/directory//')
@app.route('/browse/directory///')
@set_renderers(HTMLRenderer)
def browse_directory(sha1_git, path=None):
"""Show directory information.
Args:
- sha1_git: the directory's sha1 git identifier. If path
is set, the base directory for the relative path to the entry
- path: the path to the requested entry, relative to
the directory pointed by sha1_git
Returns:
The content's information at sha1_git, or at sha1_git/path if
path is set.
"""
env = {'sha1_git': sha1_git,
'files': []}
try:
if path:
env['message'] = ('Listing for directory with path %s from %s:'
% (path, sha1_git))
dir_or_file = service.lookup_directory_with_path(
sha1_git, path)
if dir_or_file['type'] == 'file':
fsha = 'sha256:%s' % dir_or_file['sha256']
content = api.api_content_metadata(fsha)
content_raw = service.lookup_content_raw(fsha)
if content_raw: # FIXME: currently assuming utf8 encoding
content['data'] = content_raw['data']
env['content'] = utils.prepare_data_for_view(
content, encoding='utf-8')
return render_template('content.html', **env)
else:
directory_files = api.api_directory(dir_or_file['target'])
env['files'] = utils.prepare_data_for_view(directory_files)
else:
env['message'] = "Listing for directory %s:" % sha1_git
directory_files = api.api_directory(sha1_git)
env['files'] = utils.prepare_data_for_view(directory_files)
except (NotFoundExc, BadInputExc) as e:
env['message'] = str(e)
return render_template('directory.html', **env)
@app.route('/browse/origin//')
@set_renderers(HTMLRenderer)
def browse_origin(origin_id):
"""Browse origin with id id.
"""
browse_url = url_for('browse_revision_with_origin', origin_id=origin_id)
visit_url = url_for('api_origin_visits', origin_id=origin_id)
env = {'browse_url': browse_url,
'visit_url': visit_url,
'origin_id': origin_id,
'origin': None}
try:
env['origin'] = api.api_origin(origin_id)
except (NotFoundExc, BadInputExc) as e:
env['message'] = str(e)
return render_template('origin.html', **env)
@app.route('/browse/person//')
@set_renderers(HTMLRenderer)
def browse_person(person_id):
"""Browse person with id id.
"""
env = {'person_id': person_id,
'person': None,
'message': None}
try:
env['person'] = api.api_person(person_id)
except (NotFoundExc, BadInputExc) as e:
env['message'] = str(e)
return render_template('person.html', **env)
@app.route('/browse/release//')
@set_renderers(HTMLRenderer)
def browse_release(sha1_git):
"""Browse release with sha1_git.
"""
env = {'sha1_git': sha1_git,
'message': None,
'release': None}
try:
rel = api.api_release(sha1_git)
env['release'] = utils.prepare_data_for_view(rel)
except (NotFoundExc, BadInputExc) as e:
env['message'] = str(e)
return render_template('release.html', **env)
@app.route('/browse/revision//')
@app.route('/browse/revision//prev//')
@set_renderers(HTMLRenderer)
def browse_revision(sha1_git, prev_sha1s=None):
"""Browse the revision with git SHA1 sha1_git_cur, while optionally keeping
the context from which we came as a list of previous (i.e. later)
revisions' sha1s.
Args:
sha1_git: the requested revision's sha1_git.
prev_sha1s: an optional string of /-separated sha1s representing our
context, ordered by descending revision date.
Returns:
Information about revision of git SHA1 sha1_git_cur, with relevant URLS
pointing to the context augmented with sha1_git_cur.
Example:
GET /browse/revision/
"""
env = {'sha1_git': sha1_git,
'message': None,
'revision': None}
try:
rev = api.api_revision(sha1_git, prev_sha1s)
env['revision'] = utils.prepare_data_for_view(rev)
except (NotFoundExc, BadInputExc) as e:
env['message'] = str(e)
return render_template('revision.html', **env)
@app.route('/browse/revision//raw/')
def browse_revision_raw_message(sha1_git):
"""Given a sha1_git, display the corresponding revision's raw message.
"""
return redirect(url_for('api_revision_raw_message', sha1_git=sha1_git))
@app.route('/browse/revision//log/')
@app.route('/browse/revision//prev//log/')
@set_renderers(HTMLRenderer)
def browse_revision_log(sha1_git, prev_sha1s=None):
"""Browse revision with sha1_git's log. If the navigation path through the
commit tree is specified, we intersect the earliest revision's log with the
revisions the user browsed through - ie the path taken to the specified
revision.
Args:
sha1_git: the current revision's SHA1_git checksum
prev_sha1s: optionally, the path through which we want log information
"""
env = {'sha1_git': sha1_git,
'sha1_url': '/browse/revision/%s/' % sha1_git,
'message': None,
'revisions': []}
try:
revision_data = api.api_revision_log(sha1_git, prev_sha1s)
revisions = revision_data['revisions']
next_revs_url = revision_data['next_revs_url']
env['revisions'] = map(utils.prepare_data_for_view, revisions)
env['next_revs_url'] = utils.prepare_data_for_view(next_revs_url)
except (NotFoundExc, BadInputExc) as e:
env['message'] = str(e)
return render_template('revision-log.html', **env)
@app.route('/browse/revision'
'/origin//log/')
@app.route('/browse/revision'
'/origin/'
'/branch//log/')
@app.route('/browse/revision'
'/origin/'
'/branch/'
'/ts//log/')
@app.route('/browse/revision'
'/origin/'
'/ts//log/')
@set_renderers(HTMLRenderer)
def browse_revision_log_by(origin_id,
branch_name='refs/heads/master',
timestamp=None):
"""Browse the revision described by origin, branch name and timestamp's
log
Args:
origin_id: the revision's origin
branch_name: the revision's branch
timestamp: the requested timeframe for the revision
Returns:
The revision log of the described revision as a list of revisions
if it is found.
"""
env = {'sha1_git': None,
'origin_id': origin_id,
'origin_url': '/browse/origin/%d/' % origin_id,
'branch_name': branch_name,
'timestamp': timestamp,
'message': None,
'revisions': []}
try:
revisions = api.api_revision_log_by(
origin_id, branch_name, timestamp)
env['revisions'] = map(utils.prepare_data_for_view, revisions)
except (NotFoundExc, BadInputExc) as e:
env['message'] = str(e)
return render_template('revision-log.html', **env)
@app.route('/browse/revision//prev//')
@set_renderers(HTMLRenderer)
def browse_with_rev_context(sha1_git_cur, sha1s):
"""Browse the revision with git SHA1 sha1_git_cur, while keeping the context
from which we came as a list of previous (i.e. later) revisions' sha1s.
Args:
sha1_git_cur: the requested revision's sha1_git.
sha1s: a string of /-separated sha1s representing our context, ordered
by descending revision date.
Returns:
Information about revision of git SHA1 sha1_git_cur, with relevant URLS
pointing to the context augmented with sha1_git_cur.
Example:
GET /browse/revision/
"""
env = {'sha1_git': sha1_git_cur,
'message': None,
'revision': None}
try:
revision = api.api_revision(
sha1_git_cur, sha1s)
env['revision'] = utils.prepare_data_for_view(revision)
except (BadInputExc, NotFoundExc) as e:
env['message'] = str(e)
return render_template('revision.html', **env)
@app.route('/browse/revision//history//')
@set_renderers(HTMLRenderer)
def browse_revision_history(sha1_git_root, sha1_git):
"""Display information about revision sha1_git, limited to the
sub-graph of all transitive parents of sha1_git_root.
In other words, sha1_git is an ancestor of sha1_git_root.
Args:
sha1_git_root: latest revision of the browsed history.
sha1_git: one of sha1_git_root's ancestors.
limit: optional query parameter to limit the revisions log
(default to 100). For now, note that this limit could impede the
transitivity conclusion about sha1_git not being an ancestor of
sha1_git_root (even if it is).
Returns:
Information on sha1_git if it is an ancestor of sha1_git_root
including children leading to sha1_git_root.
"""
env = {'sha1_git_root': sha1_git_root,
'sha1_git': sha1_git,
'message': None,
'keys': [],
'revision': None}
if sha1_git == sha1_git_root:
return redirect(url_for('browse_revision',
sha1_git=sha1_git))
try:
revision = api.api_revision_history(sha1_git_root,
sha1_git)
env['revision'] = utils.prepare_data_for_view(revision)
except (BadInputExc, NotFoundExc) as e:
env['message'] = str(e)
return render_template('revision.html', **env)
@app.route('/browse/revision//directory/')
@app.route('/browse/revision//directory//')
@set_renderers(HTMLRenderer)
def browse_revision_directory(sha1_git, path=None):
"""Browse directory from revision with sha1_git.
"""
env = {
'sha1_git': sha1_git,
'path': '.' if not path else path,
'message': None,
'result': None
}
encoding = request.args.get('encoding', 'utf8')
if encoding not in aliases:
env['message'] = 'Encoding %s not supported.' \
'Supported Encodings: %s' % (
encoding, list(aliases.keys()))
return render_template('revision-directory.html', **env)
try:
result = api.api_revision_directory(sha1_git, path, with_data=True)
result['content'] = utils.prepare_data_for_view(result['content'],
encoding=encoding)
env['revision'] = result['revision']
env['result'] = result
except (BadInputExc, NotFoundExc) as e:
env['message'] = str(e)
return render_template('revision-directory.html', **env)
@app.route('/browse/revision/'
'/history/'
'/directory/')
@app.route('/browse/revision/'
'/history/'
'/directory//')
@set_renderers(HTMLRenderer)
def browse_revision_history_directory(sha1_git_root, sha1_git, path=None):
"""Return information about directory pointed to by the revision
defined as: revision sha1_git, limited to the sub-graph of all
transitive parents of sha1_git_root.
Args:
sha1_git_root: latest revision of the browsed history.
sha1_git: one of sha1_git_root's ancestors.
path: optional directory pointed to by that revision.
limit: optional query parameter to limit the revisions log
(default to 100). For now, note that this limit could impede the
transitivity conclusion about sha1_git not being an ancestor of
sha1_git_root (even if it is).
Returns:
Information on the directory pointed to by that revision.
Raises:
BadInputExc in case of unknown algo_hash or bad hash.
NotFoundExc if either revision is not found or if sha1_git is not an
ancestor of sha1_git_root or the path referenced does not exist
"""
env = {
'sha1_git_root': sha1_git_root,
'sha1_git': sha1_git,
'path': '.' if not path else path,
'message': None,
'result': None
}
encoding = request.args.get('encoding', 'utf8')
if encoding not in aliases:
env['message'] = 'Encoding %s not supported.' \
'Supported Encodings: %s' % (
encoding, list(aliases.keys()))
return render_template('revision-directory.html', **env)
if sha1_git == sha1_git_root:
return redirect(url_for('browse_revision_directory',
sha1_git=sha1_git,
path=path,
encoding=encoding),
code=301)
try:
result = api.api_revision_history_directory(sha1_git_root,
sha1_git,
path,
with_data=True)
env['revision'] = result['revision']
env['content'] = utils.prepare_data_for_view(result['content'],
encoding=encoding)
env['result'] = result
except (BadInputExc, NotFoundExc) as e:
env['message'] = str(e)
return render_template('revision-directory.html', **env)
@app.route('/browse/revision'
'/origin/'
'/history/'
'/directory/')
@app.route('/browse/revision'
'/origin/'
'/history/'
'/directory//')
@app.route('/browse/revision'
'/origin/'
'/branch/'
'/history/'
'/directory/')
@app.route('/browse/revision'
'/origin/'
'/branch/'
'/history/'
'/directory//')
@app.route('/browse/revision'
'/origin/'
'/ts/'
'/history/'
'/directory/')
@app.route('/browse/revision'
'/origin/'
'/ts/'
'/history/'
'/directory//')
@app.route('/browse/revision'
'/origin/'
'/branch/'
'/ts/'
'/history/'
'/directory/')
@app.route('/browse/revision'
'/origin/'
'/branch/'
'/ts/'
'/history/'
'/directory//')
@set_renderers(HTMLRenderer)
def browse_directory_through_revision_with_origin_history(
origin_id,
branch_name="refs/heads/master",
ts=None,
sha1_git=None,
path=None):
env = {
'origin_id': origin_id,
'branch_name': branch_name,
'ts': ts,
'sha1_git': sha1_git,
'path': '.' if not path else path,
'message': None,
'result': None
}
encoding = request.args.get('encoding', 'utf8')
if encoding not in aliases:
env['message'] = (('Encoding %s not supported.'
'Supported Encodings: %s') % (
encoding, list(aliases.keys())))
return render_template('revision-directory.html', **env)
try:
result = api.api_directory_through_revision_with_origin_history(
origin_id, branch_name, ts, sha1_git, path, with_data=True)
env['revision'] = result['revision']
env['content'] = utils.prepare_data_for_view(result['content'],
encoding=encoding)
env['result'] = result
except (BadInputExc, NotFoundExc) as e:
env['message'] = str(e)
return render_template('revision-directory.html', **env)
@app.route('/browse/revision'
'/origin/')
@app.route('/browse/revision'
'/origin//')
@app.route('/browse/revision'
'/origin/'
'/branch//')
@app.route('/browse/revision'
'/origin/'
'/branch/'
'/ts//')
@app.route('/browse/revision'
'/origin/'
'/ts//')
@set_renderers(HTMLRenderer)
def browse_revision_with_origin(origin_id,
branch_name="refs/heads/master",
ts=None):
"""Instead of having to specify a (root) revision by SHA1_GIT, users
might want to specify a place and a time. In SWH a "place" is an
origin; a "time" is a timestamp at which some place has been
observed by SWH crawlers.
Args:
origin_id: origin's identifier (default to 1).
branch_name: the optional branch for the given origin (default
to master).
timestamp: optional timestamp (default to the nearest time
crawl of timestamp).
Returns:
Information on the revision if found.
Raises:
BadInputExc in case of unknown algo_hash or bad hash.
NotFoundExc if the revision is not found.
"""
env = {'message': None,
'revision': None}
try:
revision = api.api_revision_with_origin(origin_id,
branch_name,
ts)
env['revision'] = utils.prepare_data_for_view(revision)
except (ValueError, NotFoundExc, BadInputExc) as e:
env['message'] = str(e)
return render_template('revision.html', **env)
@app.route('/browse/revision'
'/origin/'
'/history//')
@app.route('/browse/revision'
'/origin/'
'/branch/'
'/history//')
@app.route('/browse/revision'
'/origin/'
'/branch/'
'/ts/'
'/history//')
@set_renderers(HTMLRenderer)
def browse_revision_history_through_origin(origin_id,
branch_name='refs/heads/master',
ts=None,
sha1_git=None):
"""Return information about revision sha1_git, limited to the
sub-graph of all transitive parents of the revision root identified
by (origin_id, branch_name, ts).
Given sha1_git_root such root revision's identifier, in other words,
sha1_git is an ancestor of sha1_git_root.
Args:
origin_id: origin's identifier (default to 1).
branch_name: the optional branch for the given origin (default
to master).
timestamp: optional timestamp (default to the nearest time
crawl of timestamp).
sha1_git: one of sha1_git_root's ancestors.
limit: optional query parameter to limit the revisions log
(default to 100). For now, note that this limit could impede the
transitivity conclusion about sha1_git not being an ancestor of
sha1_git_root (even if it is).
Returns:
Information on sha1_git if it is an ancestor of sha1_git_root
including children leading to sha1_git_root.
"""
env = {'message': None,
'revision': None}
try:
revision = api.api_revision_history_through_origin(
origin_id,
branch_name,
ts,
sha1_git)
env['revision'] = utils.prepare_data_for_view(revision)
except (ValueError, BadInputExc, NotFoundExc) as e:
env['message'] = str(e)
return render_template('revision.html', **env)
@app.route('/browse/revision'
'/origin/'
'/directory/')
@app.route('/browse/revision'
'/origin/'
'/directory/')
@app.route('/browse/revision'
'/origin/'
'/branch/'
'/directory/')
@app.route('/browse/revision'
'/origin/'
'/branch/'
'/directory//')
@app.route('/browse/revision'
'/origin/'
'/branch/'
'/ts/'
'/directory/')
@app.route('/browse/revision'
'/origin/'
'/branch/'
'/ts/'
'/directory//')
@set_renderers(HTMLRenderer)
def browse_revision_directory_through_origin(origin_id,
branch_name='refs/heads/master',
ts=None,
path=None):
env = {'message': None,
'origin_id': origin_id,
'ts': ts,
'path': '.' if not path else path,
'result': None}
encoding = request.args.get('encoding', 'utf8')
if encoding not in aliases:
env['message'] = 'Encoding %s not supported.' \
'Supported Encodings: %s' % (
encoding, list(aliases.keys()))
return render_template('revision-directory.html', **env)
try:
result = api.api_directory_through_revision_origin(
origin_id,
branch_name,
ts,
path,
with_data=True)
result['content'] = utils.prepare_data_for_view(result['content'],
encoding=encoding)
env['revision'] = result['revision']
env['result'] = result
except (ValueError, BadInputExc, NotFoundExc) as e:
env['message'] = str(e)
return render_template('revision-directory.html', **env)
@app.route('/browse/entity/')
@app.route('/browse/entity//')
@set_renderers(HTMLRenderer)
def browse_entity(uuid):
env = {'entities': [],
'message': None}
try:
entities = api.api_entity_by_uuid(uuid)
env['entities'] = entities
except (NotFoundExc, BadInputExc) as e:
env['message'] = str(e)
return render_template('entity.html', **env)