Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F8393978
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
81 KB
Subscribers
None
View Options
diff --git a/swh/web/ui/tests/test_views.py b/swh/web/ui/tests/test_views.py
index 77ddb3e1..d92086cd 100644
--- a/swh/web/ui/tests/test_views.py
+++ b/swh/web/ui/tests/test_views.py
@@ -1,1558 +1,1558 @@
# 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 swh.web.ui.tests import test_app
from unittest.mock import patch
from swh.web.ui.exc import BadInputExc, NotFoundExc
class FileMock():
def __init__(self, filename):
self.filename = filename
class ViewTestCase(test_app.SWHViewTestCase):
render_template = False
@patch('swh.web.ui.views.flask')
@istest
def homepage(self, mock_flask):
# given
mock_flask.flash.return_value = 'something'
# when
rv = self.client.get('/')
# then
self.assertEquals(rv.status_code, 200)
self.assert_template_used('home.html')
mock_flask.flash.assert_called_once_with(
'This Web app is still work in progress, use at your own risk',
'warning')
@istest
def info(self):
# when
rv = self.client.get('/about/')
self.assertEquals(rv.status_code, 200)
self.assert_template_used('about.html')
self.assertIn(b'About', rv.data)
@istest
def search_default(self):
# when
rv = self.client.get('/search/')
self.assertEquals(rv.status_code, 200)
self.assertEqual(self.get_context_variable('q'), '')
self.assertEqual(self.get_context_variable('messages'), [])
self.assertEqual(self.get_context_variable('filename'), None)
self.assertEqual(self.get_context_variable('file'), None)
self.assert_template_used('upload_and_search.html')
@patch('swh.web.ui.views.service')
@istest
def search_get_query_hash_not_found(self, mock_service):
# given
mock_service.lookup_hash.return_value = {'found': None}
# when
rv = self.client.get('/search/?q=sha1:456')
self.assertEquals(rv.status_code, 200)
self.assertEqual(self.get_context_variable('q'), 'sha1:456')
self.assertEqual(self.get_context_variable('messages'),
['Content with hash sha1:456 not found!'])
self.assertEqual(self.get_context_variable('filename'), None)
self.assertEqual(self.get_context_variable('file'), None)
self.assert_template_used('upload_and_search.html')
mock_service.lookup_hash.assert_called_once_with('sha1:456')
@patch('swh.web.ui.views.service')
@istest
def search_get_query_hash_bad_input(self, mock_service):
# given
mock_service.lookup_hash.side_effect = BadInputExc('error msg')
# when
rv = self.client.get('/search/?q=sha1_git:789')
self.assertEquals(rv.status_code, 200)
self.assertEqual(self.get_context_variable('q'), 'sha1_git:789')
self.assertEqual(self.get_context_variable('messages'),
['error msg'])
self.assertEqual(self.get_context_variable('filename'), None)
self.assertEqual(self.get_context_variable('file'), None)
self.assert_template_used('upload_and_search.html')
mock_service.lookup_hash.assert_called_once_with('sha1_git:789')
@patch('swh.web.ui.views.service')
@istest
def search_get_query_hash_found(self, mock_service):
# given
mock_service.lookup_hash.return_value = {'found': True}
# when
rv = self.client.get('/search/?q=sha1:123')
self.assertEquals(rv.status_code, 200)
self.assertEqual(self.get_context_variable('q'), 'sha1:123')
self.assertEqual(self.get_context_variable('messages'),
['Content with hash sha1:123 found!'])
self.assertEqual(self.get_context_variable('filename'), None)
self.assertEqual(self.get_context_variable('file'), None)
self.assert_template_used('upload_and_search.html')
mock_service.lookup_hash.assert_called_once_with('sha1:123')
@patch('swh.web.ui.views.service')
@istest
def search_post_query_hash_not_found(self, mock_service):
# given
mock_service.lookup_hash.return_value = {'found': None}
# when
rv = self.client.get('/search/?q=sha1:456')
self.assertEquals(rv.status_code, 200)
self.assertEqual(self.get_context_variable('q'), 'sha1:456')
self.assertEqual(self.get_context_variable('messages'),
['Content with hash sha1:456 not found!'])
self.assertEqual(self.get_context_variable('filename'), None)
self.assertEqual(self.get_context_variable('file'), None)
self.assert_template_used('upload_and_search.html')
mock_service.lookup_hash.assert_called_once_with('sha1:456')
@patch('swh.web.ui.views.service')
@istest
def search_post_query_hash_bad_input(self, mock_service):
# given
mock_service.lookup_hash.side_effect = BadInputExc('error msg!')
# when
rv = self.client.post('/search/', data=dict(q='sha1_git:987'))
self.assertEquals(rv.status_code, 200)
self.assertEqual(self.get_context_variable('q'), 'sha1_git:987')
self.assertEqual(self.get_context_variable('messages'),
['error msg!'])
self.assertEqual(self.get_context_variable('filename'), None)
self.assertEqual(self.get_context_variable('file'), None)
self.assert_template_used('upload_and_search.html')
mock_service.lookup_hash.assert_called_once_with('sha1_git:987')
@patch('swh.web.ui.views.service')
@istest
def search_post_query_hash_found(self, mock_service):
# given
mock_service.lookup_hash.return_value = {'found': True}
# when
rv = self.client.post('/search/', data=dict(q='sha1:321'))
self.assertEquals(rv.status_code, 200)
self.assertEqual(self.get_context_variable('q'), 'sha1:321')
self.assertEqual(self.get_context_variable('messages'),
['Content with hash sha1:321 found!'])
self.assertEqual(self.get_context_variable('filename'), None)
self.assertEqual(self.get_context_variable('file'), None)
self.assert_template_used('upload_and_search.html')
mock_service.lookup_hash.assert_called_once_with('sha1:321')
@patch('swh.web.ui.views.service')
@patch('swh.web.ui.views.request')
@istest
def search_post_upload_and_hash_bad_input(self, mock_request,
mock_service):
# given
mock_request.data = {}
mock_request.method = 'POST'
mock_request.files = dict(filename=FileMock('foobar'))
mock_service.upload_and_search.side_effect = BadInputExc(
'error bad input')
# when (mock_request completes the post request)
rv = self.client.post('/search/')
# then
self.assertEquals(rv.status_code, 200)
self.assertEqual(self.get_context_variable('messages'),
['error bad input'])
self.assert_template_used('upload_and_search.html')
mock_service.upload_and_search.called = True
@patch('swh.web.ui.views.service')
@patch('swh.web.ui.views.request')
@istest
def search_post_upload_and_hash_not_found(self, mock_request,
mock_service):
# given
mock_request.data = {}
mock_request.method = 'POST'
mock_request.files = dict(filename=FileMock('foobar'))
mock_service.upload_and_search.return_value = {'filename': 'foobar',
'sha1': 'blahhash',
'found': False}
# when (mock_request completes the post request)
rv = self.client.post('/search/')
# then
self.assertEquals(rv.status_code, 200)
self.assertEqual(self.get_context_variable('messages'),
["File foobar with hash blahhash not found!"])
self.assertEqual(self.get_context_variable('filename'), 'foobar')
self.assertEqual(self.get_context_variable('sha1'), 'blahhash')
self.assert_template_used('upload_and_search.html')
mock_service.upload_and_search.called = True
@patch('swh.web.ui.views.service')
@patch('swh.web.ui.views.request')
@istest
def search_post_upload_and_hash_found(self, mock_request, mock_service):
# given
mock_request.data = {}
mock_request.method = 'POST'
mock_request.files = dict(filename=FileMock('foobar'))
mock_service.upload_and_search.return_value = {'filename': 'foobar',
'sha1': '123456789',
'found': True}
# when (mock_request completes the post request)
rv = self.client.post('/search/')
# then
self.assertEquals(rv.status_code, 200)
self.assertEqual(self.get_context_variable('messages'),
["File foobar with hash 123456789 found!"])
self.assertEqual(self.get_context_variable('filename'), 'foobar')
self.assertEqual(self.get_context_variable('sha1'), '123456789')
self.assert_template_used('upload_and_search.html')
mock_service.upload_and_search.called = True
@patch('swh.web.ui.views.api')
@istest
def browse_content_metadata_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.assertEquals(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.api')
@istest
def browse_content_metadata_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.assertEquals(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.service')
@patch('swh.web.ui.views.api')
@istest
def browse_content_metadata(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.assertEquals(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.service')
@istest
def browse_content_raw(self, mock_service):
# given
stub_content_raw = {
'sha1': 'sha1-hash',
'data': b'some-data'
}
mock_service.lookup_content_raw.return_value = stub_content_raw
# when
rv = self.client.get('/browse/content/sha1:sha1-hash/raw/')
self.assertEquals(rv.status_code, 200)
self.assert_template_used('content-data.html')
self.assertEqual(self.get_context_variable('message'),
'Content sha1-hash')
self.assertEqual(self.get_context_variable('content'),
stub_content_raw)
mock_service.lookup_content_raw.assert_called_once_with(
'sha1:sha1-hash')
@patch('swh.web.ui.views.service')
@istest
def browse_content_raw_not_found(self, mock_service):
# given
mock_service.lookup_content_raw.return_value = None
# when
rv = self.client.get('/browse/content/sha1:sha1-unknown/raw/')
self.assertEquals(rv.status_code, 200)
self.assert_template_used('content-data.html')
self.assertEqual(self.get_context_variable('message'),
'Content with sha1:sha1-unknown not found.')
self.assertEqual(self.get_context_variable('content'), None)
mock_service.lookup_content_raw.assert_called_once_with(
'sha1:sha1-unknown')
@patch('swh.web.ui.views.service')
@istest
def browse_content_raw_invalid_hash(self, mock_service):
# given
mock_service.lookup_content_raw.side_effect = BadInputExc(
'Invalid hash')
# when
rv = self.client.get('/browse/content/sha2:sha1-invalid/raw/')
self.assertEquals(rv.status_code, 200)
self.assert_template_used('content-data.html')
self.assertEqual(self.get_context_variable('message'),
'Invalid hash')
self.assertEqual(self.get_context_variable('content'), None)
mock_service.lookup_content_raw.assert_called_once_with(
'sha2:sha1-invalid')
@patch('swh.web.ui.views.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.assertEquals(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.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.assertEquals(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.api')
@patch('swh.web.ui.views.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.assertEquals(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)
@patch('swh.web.ui.views.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.assertEquals(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.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.assertEquals(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.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.assertEquals(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')
@patch('swh.web.ui.views.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.assertEquals(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.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.assertEquals(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.api')
@istest
def browse_origin_found(self, mock_api):
# given
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.assertEquals(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)
mock_api.api_origin.assert_called_once_with(426)
- @patch('swh.web.ui.views.service')
+ @patch('swh.web.ui.views.api')
@istest
- def browse_person_not_found(self, mock_service):
+ def browse_person_KO_not_found(self, mock_api):
# given
- mock_service.lookup_person.return_value = None
+ mock_api.api_person.side_effect = NotFoundExc('not found')
# when
rv = self.client.get('/browse/person/1/')
# then
self.assertEquals(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'),
- 'Person 1 not found!')
+ 'not found')
- mock_service.lookup_person.assert_called_once_with(1)
+ mock_api.api_person.assert_called_once_with(1)
- @patch('swh.web.ui.views.service')
+ @patch('swh.web.ui.views.api')
@istest
- def browse_person_found(self, mock_service):
+ def browse_person_KO_bad_input(self, mock_api):
# given
- mock_person = {'type': 'git',
- 'lister': None,
- 'project': None,
- 'url': 'rsync://some/url',
- 'id': 426}
- mock_service.lookup_person.return_value = mock_person
+ mock_api.api_person.side_effect = BadInputExc('wrong input')
# when
rv = self.client.get('/browse/person/426/')
# then
self.assertEquals(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_service.lookup_person.assert_called_once_with(426)
+ mock_api.api_person.assert_called_once_with(426)
- @patch('swh.web.ui.views.service')
+ @patch('swh.web.ui.views.api')
@istest
- def browse_person_bad_input(self, mock_service):
+ def browse_person(self, mock_api):
# given
- mock_service.lookup_person.side_effect = BadInputExc('wrong input')
+ 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.assertEquals(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_service.lookup_person.assert_called_once_with(426)
+ mock_api.api_person.assert_called_once_with(426)
@patch('swh.web.ui.views.service')
@istest
def browse_release_not_found(self, mock_service):
# given
mock_service.lookup_release.return_value = None
# when
rv = self.client.get('/browse/release/1/')
# then
self.assertEquals(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'),
'Release 1 not found!')
mock_service.lookup_release.assert_called_once_with('1')
@patch('swh.web.ui.views.service')
@istest
def browse_release_bad_input(self, mock_service):
# given
mock_service.lookup_release.side_effect = BadInputExc('wrong input')
# when
rv = self.client.get('/browse/release/426/')
# then
self.assertEquals(rv.status_code, 200)
self.assert_template_used('release.html')
self.assertEqual(self.get_context_variable('sha1_git'), '426')
mock_service.lookup_release.assert_called_once_with('426')
@patch('swh.web.ui.views.service')
@istest
def browse_release(self, mock_service):
# given
mock_release = {
"date": "Sun, 05 Jul 2015 18:02:06 GMT",
"id": "1e951912027ea6873da6985b91e50c47f645ae1a",
"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"
}
mock_service.lookup_release.return_value = mock_release
expected_release = {
"date": "Sun, 05 Jul 2015 18:02:06 GMT",
"id": "1e951912027ea6873da6985b91e50c47f645ae1a",
"target": '/browse/revision/d770e558e21961ad6cfdf0ff7df0'
'eb5d7d4f0754/',
"synthetic": False,
"target_type": "revision",
"author": "Linus Torvalds <torvalds@linux-foundation.org>",
"message": "Linux 4.2-rc1\n",
"name": "v4.2-rc1"
}
# when
rv = self.client.get('/browse/release/426/')
# then
self.assertEquals(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)
self.assertEqual(self.get_context_variable('keys'), [
'id', 'name', 'date', 'message', 'author', 'target',
'target_type'])
mock_service.lookup_release.assert_called_once_with('426')
@patch('swh.web.ui.views.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.assertEquals(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')
@patch('swh.web.ui.views.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.assertEquals(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')
@patch('swh.web.ui.views.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.assertEquals(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')
@patch('swh.web.ui.views.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.assertEquals(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')
@patch('swh.web.ui.views.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.assertEquals(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')
@patch('swh.web.ui.views.api')
@istest
def browse_revision_log(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.return_value = stub_revisions
# when
rv = self.client.get('/browse/revision/426/log/')
# then
self.assertEquals(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.assertIsNone(self.get_context_variable('message'))
mock_api.api_revision_log.assert_called_once_with('426')
@patch('swh.web.ui.views.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.assertEquals(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.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.assertEquals(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.assertEquals(rv.status_code, 302)
@patch('swh.web.ui.views.utils')
@patch('swh.web.ui.views.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.assertEquals(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.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.assertEquals(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)
@patch('swh.web.ui.views.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.assertEquals(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)
@patch('swh.web.ui.views.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.assertEquals(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')
@patch('swh.web.ui.views.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.assertEquals(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')
@patch('swh.web.ui.views.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.assertEquals(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')
@patch('swh.web.ui.views.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.assertEquals(rv.status_code, 301)
@patch('swh.web.ui.views.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.assertEquals(rv.status_code, 301)
@patch('swh.web.ui.views.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.assertEquals(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')
@patch('swh.web.ui.views.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/')
# then
self.assertEquals(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.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.assertEquals(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.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.assertEquals(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')
@patch('swh.web.ui.views.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.assertEquals(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.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.assertEquals(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.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.assertEquals(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.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.assertEquals(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.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.assertEquals(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.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.assertEquals(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.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.assertEquals(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.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.assertEquals(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.api')
@istest
def browse_revision_directory_through_origin_KO_not_found(self, mock_api):
# given
mock_api.api_directory_through_origin.side_effect = BadInputExc(
'this is not the robot you are looking for')
# when
rv = self.client.get('/browse/revision/origin/2'
'/directory/')
self.assertEquals(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_origin.assert_called_once_with( # noqa
2, 'refs/heads/master', None, None)
@patch('swh.web.ui.views.api')
@istest
def browse_revision_directory_through_origin_KO_bad_input(self, mock_api):
# given
mock_api.api_directory_through_origin.side_effect = BadInputExc(
'Bad Robot')
# when
rv = self.client.get('/browse/revision/origin/2'
'/directory/')
self.assertEquals(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_origin.assert_called_once_with(
2, 'refs/heads/master', None, None)
@patch('swh.web.ui.views.api')
@istest
def browse_revision_directory_through_origin_KO_other(self, mock_api):
# given
mock_api.api_directory_through_origin.side_effect = ValueError(
'Other bad stuff')
# when
rv = self.client.get('/browse/revision/origin/2'
'/directory/')
self.assertEquals(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_origin.assert_called_once_with(
2, 'refs/heads/master', None, None)
@patch('swh.web.ui.views.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_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.assertEquals(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_origin.assert_called_once_with(
2, 'dev', '2013-20-20 10:02', 'some/file')
@patch('swh.web.ui.views.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.assertEquals(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)
@patch('swh.web.ui.views.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.assertEquals(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')
@patch('swh.web.ui.views.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.assertEquals(rv.status_code, 200)
self.assert_template_used('revision-directory.html')
self.assertEquals(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')
diff --git a/swh/web/ui/views.py b/swh/web/ui/views.py
index af8b0716..42ca2c33 100644
--- a/swh/web/ui/views.py
+++ b/swh/web/ui/views.py
@@ -1,738 +1,735 @@
# 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 flask
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 swh.web.ui import service, utils, api
from swh.web.ui.exc import BadInputExc, NotFoundExc
from swh.web.ui.main import app
hash_filter_keys = ALGORITHMS
@app.route('/')
@set_renderers(HTMLRenderer)
def homepage():
"""Home page
"""
flask.flash('This Web app is still work in progress, use at your own risk',
'warning')
return render_template('home.html')
@app.route('/about/')
@set_renderers(HTMLRenderer)
def about():
return render_template('about.html')
@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
- some file content to upload, compute its hash and look it up in swh
storage
- both
Returns:
dict representing data to look for in swh storage.
The following keys are returned:
- file: File submitted for upload
- filename: Filename submitted for upload
- q: Query on hash to look for
- message: Message detailing if data has been found or not.
"""
env = {'filename': None,
'q': None,
'file': None}
data = None
q = env['q']
file = env['file']
if request.method == 'GET':
data = request.args
elif request.method == 'POST':
data = request.data
# or hash and search a file
file = request.files.get('filename')
# could either be a query for sha1 hash
q = data.get('q')
messages = []
if q:
env['q'] = q
try:
r = service.lookup_hash(q)
messages.append('Content with hash %s%sfound!' % (
q, ' ' if r.get('found') else ' not '))
except BadInputExc as e:
messages.append(str(e))
if file and file.filename:
env['file'] = file
try:
uploaded_content = service.upload_and_search(file)
filename = uploaded_content['filename']
sha1 = uploaded_content['sha1']
found = uploaded_content['found']
messages.append('File %s with hash %s%sfound!' % (
filename, sha1, ' ' if found else ' not '))
env.update({
'filename': filename,
'sha1': sha1,
})
except BadInputExc as e:
messages.append(str(e))
env['q'] = q if q else ''
env['messages'] = messages
return render_template('upload_and_search.html', **env)
@app.route('/browse/content/')
@app.route('/browse/content/<string:q>/')
@set_renderers(HTMLRenderer)
def browse_content_metadata(q='5d448a06f02d9de748b6b0b9620cba1bed8480da'):
"""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}
try:
content = api.api_content_metadata(q)
content_raw = service.lookup_content_raw(q)
if content_raw:
content_raw = content_raw['data'].decode('utf-8')
content['data'] = content_raw
env['content'] = content
except (NotFoundExc, BadInputExc) as e:
env['message'] = str(e)
return render_template('content.html', **env)
@app.route('/browse/content/<string:q>/raw/')
@set_renderers(HTMLRenderer)
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.
"""
env = {}
content = None
try:
content = service.lookup_content_raw(q)
if content:
# FIXME: will break if not utf-8
content['data'] = content['data'].decode('utf-8')
message = 'Content %s' % content['sha1']
else:
message = 'Content with %s not found.' % q
except BadInputExc as e:
message = str(e)
env['message'] = message
env['content'] = content
return render_template('content-data.html', **env)
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/<string:q>/origin/')
@set_renderers(HTMLRenderer)
def browse_content_with_origin(
q='sha1:4320781056e5a735a39de0b8c229aea224590052'):
"""Show content information.
Args:
- q: query string of the form <algo_hash:hash> 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/<string:sha1_git>/')
@set_renderers(HTMLRenderer)
def browse_directory(sha1_git='dcf3289b576b1c8697f2a2d46909d36104208ba3'):
"""Show directory information.
Args:
- sha1_git: the directory's sha1 git identifier.
Returns:
The content's information at sha1_git
"""
env = {'sha1_git': sha1_git,
'files': []}
try:
directory_files = api.api_directory(sha1_git)
env['message'] = "Listing for directory %s:" % 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/')
@app.route('/browse/origin/<int:origin_id>/')
@set_renderers(HTMLRenderer)
def browse_origin(origin_id=1):
"""Browse origin with id id.
"""
env = {'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/')
@app.route('/browse/person/<int:person_id>/')
@set_renderers(HTMLRenderer)
def browse_person(person_id=1):
"""Browse person with id id.
"""
env = {'person_id': person_id,
- 'person': None}
+ 'person': None,
+ 'message': None}
try:
- ori = service.lookup_person(person_id)
- if ori:
- env.update({'person': ori})
- else:
- env.update({'message': 'Person %s not found!' % person_id})
- except BadInputExc as e:
- env.update({'message': str(e)})
+ 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/')
@app.route('/browse/release/<string:sha1_git>/')
@set_renderers(HTMLRenderer)
def browse_release(sha1_git='1e951912027ea6873da6985b91e50c47f645ae1a'):
"""Browse release with sha1_git.
"""
env = {'sha1_git': sha1_git,
'release': None}
try:
rel = service.lookup_release(sha1_git)
if rel:
author = rel.get('author')
if author:
rel['author'] = utils.person_to_string(author)
target_type = rel.get('target_type')
if target_type == 'revision':
rel['target'] = url_for('browse_revision',
sha1_git=rel['target'])
env.update({'release': rel,
'keys': ['id', 'name', 'date', 'message', 'author',
'target', 'target_type']})
else:
env.update({'message': 'Release %s not found!' % sha1_git})
except BadInputExc as e:
env.update({'message': str(e)})
return render_template('release.html', **env)
@app.route('/browse/revision/')
@app.route('/browse/revision/<string:sha1_git>/')
@set_renderers(HTMLRenderer)
def browse_revision(sha1_git='d770e558e21961ad6cfdf0ff7df0eb5d7d4f0754'):
"""Browse revision with sha1_git.
"""
env = {'sha1_git': sha1_git,
'message': None,
'revision': None}
try:
rev = api.api_revision(sha1_git)
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/<string:sha1_git>/log/')
@set_renderers(HTMLRenderer)
def browse_revision_log(sha1_git):
"""Browse revision with sha1_git.
"""
env = {'sha1_git': sha1_git,
'message': None,
'revisions': []}
try:
revisions = api.api_revision_log(sha1_git)
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/<string:sha1_git_root>/history/<sha1_git>/')
@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/<string:sha1_git>/directory/')
@app.route('/browse/revision/<string:sha1_git>/directory/<path:path>/')
@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
}
try:
result = api.api_revision_directory(sha1_git, path)
result['content'] = utils.prepare_data_for_view(result['content'])
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/<string:sha1_git_root>'
'/history/<sha1_git>'
'/directory/')
@app.route('/browse/revision/<string:sha1_git_root>'
'/history/<sha1_git>'
'/directory/<path:path>/')
@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
}
if sha1_git == sha1_git_root:
return redirect(url_for('browse_revision_directory',
sha1_git=sha1_git,
path=path),
code=301)
try:
result = api.api_revision_history_directory(sha1_git_root,
sha1_git,
path)
env['revision'] = result['revision']
env['content'] = utils.prepare_data_for_view(result['content'])
env['result'] = result
except (BadInputExc, NotFoundExc) as e:
env['message'] = str(e)
return render_template('revision-directory.html', **env)
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/history/<sha1_git>'
'/directory/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/history/<sha1_git>'
'/directory/<path:path>/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/branch/<path:branch_name>'
'/history/<sha1_git>'
'/directory/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/branch/<path:branch_name>'
'/history/<sha1_git>'
'/directory/<path:path>/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/ts/<string:ts>'
'/history/<sha1_git>'
'/directory/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/ts/<string:ts>'
'/history/<sha1_git>'
'/directory/<path:path>/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/branch/<path:branch_name>'
'/ts/<string:ts>'
'/history/<sha1_git>'
'/directory/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/branch/<path:branch_name>'
'/ts/<string:ts>'
'/history/<sha1_git>'
'/directory/<path:path>/')
@set_renderers(HTMLRenderer)
def browse_directory_through_revision_with_origin_history(
origin_id=1,
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
}
try:
result = api.api_directory_through_revision_with_origin_history(
origin_id, branch_name, ts, sha1_git, path)
env['revision'] = result['revision']
env['content'] = utils.prepare_data_for_view(result['content'])
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/<int:origin_id>/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/branch/<path:branch_name>/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/branch/<path:branch_name>'
'/ts/<string:ts>/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/ts/<string:ts>/')
@set_renderers(HTMLRenderer)
def browse_revision_with_origin(origin_id=1,
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/<int:origin_id>'
'/history/<sha1_git>/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/branch/<path:branch_name>'
'/history/<sha1_git>/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/branch/<path:branch_name>'
'/ts/<string:ts>'
'/history/<sha1_git>/')
@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/<int:origin_id>'
'/directory/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/directory/<path:path>')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/branch/<path:branch_name>'
'/directory/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/branch/<path:branch_name>'
'/directory/<path:path>/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/branch/<path:branch_name>'
'/ts/<string:ts>'
'/directory/')
@app.route('/browse/revision'
'/origin/<int:origin_id>'
'/branch/<path:branch_name>'
'/ts/<string:ts>'
'/directory/<path:path>/')
@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}
try:
result = api.api_directory_through_origin(
origin_id,
branch_name,
ts,
path)
result['content'] = utils.prepare_data_for_view(result['content'])
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/<string:uuid>/')
@set_renderers(HTMLRenderer)
def browse_entity(uuid='5f4d4c51-498a-4e28-88b3-b3e4e8396cba'):
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)
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Wed, Jun 4, 7:19 PM (1 w, 13 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3281398
Attached To
rDWAPPS Web applications
Event Timeline
Log In to Comment