diff --git a/docs/uri-scheme.rst b/docs/uri-scheme.rst index f06574688..9ff1d7a00 100644 --- a/docs/uri-scheme.rst +++ b/docs/uri-scheme.rst @@ -1,475 +1,487 @@ URI scheme for SWH Web applications =================================== SWH Browse Urls --------------- This web application aims to provide HTML views to easily navigate in the SWH archive, thus it needs to be reached from a web browser. If you intend to query the SWH archive programmatically through any HTTP client, please refer to the `SWH Web API URLs`_ instead. Content ^^^^^^^ .. http:get:: /browse/content/[(algo_hash):](hash)/ HTML view that displays a SWH content identified by its hash value. If the content to display is textual, it will be highlighted client-side if possible using highlightjs_. In order for that operation to be performed, a programming language must first be associated to the content. The following procedure is used in order to find the language: 1) First try to find a language from the content filename (provided as query parameter when navigating from a directory view). 2) If no language has been found from the filename, try to find one from the content mime type. The mime type is retrieved from the content metadata stored in the SWH archive or is computed server-side using Python magic module. When that view is called in the context of a navigation coming from a directory view, a breadcrumb will be displayed on top of the rendered content in order to easily navigate up to the associated root directory. In that case, the path query parameter will be used and filled with the path of the file relative to the root directory. :param algo_hash: optionnal parameter to indicate the algorithm used to compute the content checksum (default to *sha1*) :type algo_hash: a string identifying the hashing algorithm (either *sha1*, *sha1_git*, *sha256* or *blake2s256*) :param hash: the checksum from which to retrieve the associated content in the SWH archive :type hash: hexadecimal representation of the hash value :query path: optionnal parameter used to describe the path of the content relative to a root directory (used to add context aware navigation links when navigating from a directory view) :type path: string :statuscode 200: no error :statuscode 400: an invalid query string has been provided :statuscode 404: requested content can not be found in the SWH archive .. http:get:: /browse/content/[(algo_hash):](hash)/raw/ HTML view that produces a raw display of a SWH content identified by its hash value. The behaviour of that view depends on the mime type of the requested content. If the mime type is from the text family, the view will return a response whose content type is 'text/plain' that will be rendered by the browser. Otherwise, the view will return a response whose content type is 'application/octet-stream' and the browser will then offer to download the file. In the context of a navigation coming from a directory view, the filename query parameter will be used in order to provide the real name of the file when one wants to save it locally. :param algo_hash: optionnal parameter to indicate the algorithm used to compute the content checksum (default to *sha1*) :type algo_hash: a string identifying the hashing algorithm (either *sha1*, *sha1_git*, *sha256* or *blake2s256*) :param hash: the checksum from which to retrieve the associated content in the SWH archive :type hash: hexadecimal representation of the hash value :query filename: optionnal parameter used to indicate the name of the file holding the requested content (used when one wants to save the content to a local file) :type path: string :statuscode 200: no error :statuscode 400: an invalid query string has been provided :statuscode 404: requested content can not be found in the SWH archive Directory ^^^^^^^^^ .. http:get:: /browse/directory/(sha1_git)/ HTML view for browsing the content of a SWH directory identified by its `sha1_git` value. The content of the directory is first sorted in lexicographical order and the sub-directories are displayed before the regular files. The view enables to navigate from the provided root directory to directories reachable from it in a recursive way. A breadcrumb located in the top part of the view allows to keep track of the paths navigated so far. :param sha1_git: the `sha1_git` identifier of the directory to browse :type sha1_git: hexadecimal representation of that hash value :statuscode 200: no error :statuscode 400: an invalid `sha1_git` value has been provided :statuscode 404: requested directory can not be found in the SWH archive .. http:get:: /browse/directory/(sha1_git)/(path)/ HTML view for browsing the content of a SWH directory reachable from the provided root one identified by its `sha1_git` value. The content of the directory is first sorted in lexicographical order and the sub-directories are displayed before the regular files. The view enables to navigate from the requested directory to directories reachable from it in a recursive way but also up to the root directory. A breadcrumb located in the top part of the view allows to keep track of the paths navigated so far. :param sha1_git: the `sha1_git` identifier of the directory to browse :type sha1_git: hexadecimal representation of that hash value :param path: path of a directory reachable from the provided root one :type path: string :statuscode 200: no error :statuscode 400: an invalid `sha1_git` value has been provided :statuscode 404: requested directory can not be found in the SWH archive Origin ^^^^^^ Origin metadata """"""""""""""" .. http:get:: /browse/origin/(origin_id)/ HTML view that displays a SWH origin identified by its id. The view displays the origin metadata and contains links for browsing its directories and contents for each SWH visit. :param origin_id: the id of a SWH origin :type origin_id: int :statuscode 200: no error :statuscode 404: requested origin can not be found in the SWH archive .. http:get:: /browse/origin/(origin_type)/url/(origin_url)/ HTML view that displays a SWH origin identified by its type and url. The view displays the origin metadata and contains links for browsing its directories and contents for each SWH visit. :param origin_type: the type of the SWH origin (*git*, *svn*, ...) :type origin_type: string :param origin_url: the url of the origin (e.g. https://github.com///) :type origin_url: string :statuscode 200: no error :statuscode 404: requested origin can not be found in the SWH archive Origin directory """""""""""""""" .. http:get:: /browse/origin/(origin_id)/directory/ HTML view for browsing the content of the root directory associated to the latest visit of a SWH origin. The content of the directory is first sorted in lexicographical order and the sub-directories are displayed before the regular files. The view enables to navigate from the origin root directory to directories reachable from it in a recursive way. A breadcrumb located in the top part of the view allows to keep track of the paths navigated so far. The view also enables to easily switch between the origin branches through a dropdown menu. The origin branch (default to master) from which to retrieve the directory content can also be specified by using the branch query parameter. :param origin_id: the id of a SWH origin :type origin_id: int :query branch: optional query parameter to specify the origin branch from which to retrieve the directory :type branch: string :statuscode 200: no error :statuscode 404: requested origin can not be found in the SWH archive .. http:get:: /browse/origin/(origin_id)/directory/(path)/ HTML view for browsing the content of a directory reachable from the root directory associated to the latest visit of a SWH origin. The content of the directory is first sorted in lexicographical order and the sub-directories are displayed before the regular files. The view enables to navigate from the requested directory to directories reachable from it in a recursive way but also up to the origin root directory. A breadcrumb located in the top part of the view allows to keep track of the paths navigated so far. The view also enables to easily switch between the origin branches through a dropdown menu. The origin branch (default to master) from which to retrieve the directory content can also be specified by using the branch query parameter. :param origin_id: the id of a SWH origin :type origin_id: int :param path: path of a directory reachable from the origin root one :type path: string :query branch: optional query parameter to specify the origin branch from which to retrieve the directory :type branch: string :statuscode 200: no error :statuscode 404: requested origin can not be found in the SWH archive or the provided path does not exist from the origin root directory .. http:get:: /browse/origin/(origin_id)/visit/(visit_id)/directory/ HTML view for browsing the content of the root directory associated to a specific visit (identified by its id) of a SWH origin. The content of the directory is first sorted in lexicographical order and the sub-directories are displayed before the regular files. The view enables to navigate from the origin root directory to directories reachable from it in a recursive way. A breadcrumb located in the top part of the view allows to keep track of the paths navigated so far. The view also enables to easily switch between the origin branches through a dropdown menu. The origin branch (default to master) from which to retrieve the directory content can also be specified by using the branch query parameter. :param origin_id: the id of a SWH origin :type origin_id: int :param visit_id: the id of the origin visit :type visit_id: int :query branch: optional query parameter to specify the origin branch from which to retrieve the directory :type branch: string :statuscode 200: no error :statuscode 404: requested origin can not be found in the SWH archive or requested visit id does not exist .. http:get:: /browse/origin/(origin_id)/visit/(visit_id)/directory/(path)/ HTML view for browsing the content of a directory reachable from the root directory associated to a specific visit (identified by its id) of a SWH origin. The content of the directory is first sorted in lexicographical order and the sub-directories are displayed before the regular files. The view enables to navigate from the requested directory to directories reachable from it in a recursive way but also up to the origin root directory. A breadcrumb located in the top part of the view allows to keep track of the paths navigated so far. The view also enables to easily switch between the origin branches through a dropdown menu. The origin branch (default to master) from which to retrieve the directory content can also be specified by using the branch query parameter. :param origin_id: the id of a SWH origin :type origin_id: int :param visit_id: the id of the origin visit :type visit_id: int :param path: path of a directory reachable from the origin root one :type path: string :query branch: optional query parameter to specify the origin branch from which to retrieve the directory :type branch: string :statuscode 200: no error :statuscode 404: requested origin can not be found in the SWH archive, requested visit id does not exist or the provided path does not exist from the origin root directory .. http:get:: /browse/origin/(origin_id)/ts/(ts)/directory/ HTML view for browsing the content of the root directory associated to a specific visit (identified by its timestamp) of a SWH origin. The content of the directory is first sorted in lexicographical order and the sub-directories are displayed before the regular files. The view enables to navigate from the origin root directory to directories reachable from it in a recursive way. A breadcrumb located in the top part of the view allows to keep track of the paths navigated so far. The view also enables to easily switch between the origin branches through a dropdown menu. The origin branch (default to master) from which to retrieve the directory content can also be specified by using the branch query parameter. :param origin_id: the id of a SWH origin :type origin_id: int :param ts: the timestamp of the origin visit :type ts: Unix timestamp :query branch: optional query parameter to specify the origin branch from which to retrieve the directory :type branch: string :statuscode 200: no error :statuscode 404: requested origin can not be found in the SWH archive or requested visit timestamp does not exist .. http:get:: /browse/origin/(origin_id)/ts/(ts)/directory/(path)/ HTML view for browsing the content of a directory reachable from the root directory associated to a specific visit (identified by its timestamp) of a SWH origin. The content of the directory is first sorted in lexicographical order and the sub-directories are displayed before the regular files. The view enables to navigate from the requested directory to directories reachable from it in a recursive way but also up to the origin root directory. A breadcrumb located in the top part of the view allows to keep track of the paths navigated so far. The view also enables to easily switch between the origin branches through a dropdown menu. The origin branch (default to master) from which to retrieve the directory content can also be specified by using the branch query parameter. :param origin_id: the id of a SWH origin :type origin_id: int :param ts: the timestamp of the origin visit :type ts: Unix timestamp :param path: path of a directory reachable from the origin root one :type path: string :query branch: optional query parameter to specify the origin branch from which to retrieve the directory :type branch: string :statuscode 200: no error :statuscode 404: requested origin can not be found in the SWH archive, requested visit timestamp does not exist or the provided path does not exist from the origin root directory Origin content """""""""""""" .. http:get:: /browse/origin/(origin_id)/content/(path)/ HTML view that produces an HTML display of a SWH content associated to the latest visit of a SWH origin. If the content to display is textual, it will be highlighted client-side if possible using highlightjs_. In order for that operation to be performed, a programming language must first be associated to the content. The following procedure is used in order to find the language: 1) First try to find a language from the content filename 2) If no language has been found from the filename, try to find one from the content mime type. The mime type is retrieved from the content metadata stored in the SWH archive or is computed server-side using Python magic module. The view displays a breadcrumb on top of the rendered content in order to easily navigate up to the origin root directory. The view also enables to easily switch between the origin branches through a dropdown menu. The origin branch (default to master) from which to retrieve the content can also be specified by using the branch query parameter. :param origin_id: the id of a SWH origin :type origin_id: int :param path: path of a content reachable from the origin root directory :type path: string :query branch: optional query parameter to specify the origin branch from which to retrieve the content :type branch: string :statuscode 200: no error :statuscode 404: requested origin can not be found in the SWH archive, or the provided content path does not exist from the origin root directory .. http:get:: /browse/origin/(origin_id)/visit/(visit_id)/content/(path)/ HTML view that produces an HTML display of a SWH content associated to a specific visit (identified by its id) of a SWH origin. If the content to display is textual, it will be highlighted client-side if possible using highlightjs_. In order for that operation to be performed, a programming language must first be associated to the content. The following procedure is used in order to find the language: 1) First try to find a language from the content filename 2) If no language has been found from the filename, try to find one from the content mime type. The mime type is retrieved from the content metadata stored in the SWH archive or is computed server-side using Python magic module. The view displays a breadcrumb on top of the rendered content in order to easily navigate up to the origin root directory. The view also enables to easily switch between the origin branches through a dropdown menu. The origin branch (default to master) from which to retrieve the content can also be specified by using the branch query parameter. :param origin_id: the id of a SWH origin :type origin_id: int :param visit_id: the id of the origin visit :type visit_id: int :param path: path of a content reachable from the origin root directory :type path: string :query branch: optional query parameter to specify the origin branch from which to retrieve the content :type branch: string :statuscode 200: no error :statuscode 404: requested origin can not be found in the SWH archive, requested visit id does not exist or the provided content path does not exist from the origin root directory .. http:get:: /browse/origin/(origin_id)/ts/(ts)/content/(path)/ HTML view that produces an HTML display of a SWH content associated to a specific visit (identified by its timestamp) of a SWH origin. If the content to display is textual, it will be highlighted client-side if possible using highlightjs_. In order for that operation to be performed, a programming language must first be associated to the content. The following procedure is used in order to find the language: 1) First try to find a language from the content filename 2) If no language has been found from the filename, try to find one from the content mime type. The mime type is retrieved from the content metadata stored in the SWH archive or is computed server-side using Python magic module. The view displays a breadcrumb on top of the rendered content in order to easily navigate up to the origin root directory. The view also enables to easily switch between the origin branches through a dropdown menu. The origin branch (default to master) from which to retrieve the content can also be specified by using the branch query parameter. :param origin_id: the id of a SWH origin :type origin_id: int :param ts: the timestamp of the origin visit :type ts: Unix timestamp :param path: path of a content reachable from the origin root directory :type path: string :query branch: optional query parameter to specify the origin branch from which to retrieve the content :type branch: string :statuscode 200: no error :statuscode 404: requested origin can not be found in the SWH archive, requested visit timestamp does not exist or the provided content path does not exist from the origin root directory +Person +^^^^^^ + +.. http:get:: /browse/person/(person_id)/ + + HTML view that displays information regarding a SWH person. + + :param person_id: the id of a SWH person + :type origin_id: int + :statuscode 200: no error + :statuscode 404: requested person can not be found in the SWH archive + SWH Web API URLs ---------------- .. _highlightjs: https://highlightjs.org/ \ No newline at end of file diff --git a/swh/web/browse/urls.py b/swh/web/browse/urls.py index 5f076e287..f6f580f64 100644 --- a/swh/web/browse/urls.py +++ b/swh/web/browse/urls.py @@ -1,40 +1,41 @@ # Copyright (C) 2017 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information from django.conf.urls import url from django.shortcuts import redirect from swh.web.common.utils import reverse import swh.web.browse.views.directory # noqa import swh.web.browse.views.content # noqa import swh.web.browse.views.origin # noqa +import swh.web.browse.views.person # noqa from swh.web.browse.browseurls import BrowseUrls def default_browse_view(request): """Default django view used as an entry point for the swh browse ui web application. The url that point to it is /browse/. Currently, it points to the origin view for the linux kernel source tree github mirror. Args: request: input django http request """ linux_origin_id = '2' linux_origin_url = reverse('browse-origin', kwargs={'origin_id': linux_origin_id}) return redirect(linux_origin_url) urlpatterns = [ url(r'^$', default_browse_view) ] urlpatterns += BrowseUrls.get_url_patterns() diff --git a/swh/web/browse/views/person.py b/swh/web/browse/views/person.py new file mode 100644 index 000000000..70fa590d9 --- /dev/null +++ b/swh/web/browse/views/person.py @@ -0,0 +1,34 @@ +# Copyright (C) 2017 The Software Heritage developers +# See the AUTHORS file at the top-level directory of this distribution +# License: GNU General Public License version 3, or any later version +# See top-level LICENSE file for more information + + +from django.shortcuts import render +from swh.web.common import service +from swh.web.common.exc import handle_view_exception +from swh.web.browse.browseurls import browse_route + + +@browse_route(r'person/(?P[0-9]+)/', + view_name='browse-person') +def person_browse(request, person_id): + """ + Django view that produces an HTML display of a swh person + identified by its id. + + The url that points to it is :http:get:`/browse/person/(person_id)/`. + + Args: + request: input django http request + person_id (int): a swh person id + + Returns: + The HMTL rendering for the metadata of the provided person. + """ + try: + person = service.lookup_person(person_id) + except Exception as exc: + return handle_view_exception(exc) + + return render(request, 'person.html', {'person': person}) diff --git a/swh/web/common/swh_templatetags.py b/swh/web/common/swh_templatetags.py index 970a9b968..0cdcbee71 100644 --- a/swh/web/common/swh_templatetags.py +++ b/swh/web/common/swh_templatetags.py @@ -1,89 +1,92 @@ # Copyright (C) 2017 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information import re from docutils.core import publish_parts from docutils.writers.html4css1 import Writer, HTMLTranslator from inspect import cleandoc from django import template from django.utils.safestring import mark_safe from pygments import highlight from pygments.lexers import JsonLexer from pygments.formatters import HtmlFormatter register = template.Library() class NoHeaderHTMLTranslator(HTMLTranslator): """ Docutils translator subclass to customize the generation of HTML from reST-formatted docstrings """ def __init__(self, document): super().__init__(document) self.body_prefix = [] self.body_suffix = [] def visit_bullet_list(self, node): self.context.append((self.compact_simple, self.compact_p)) self.compact_p = None self.compact_simple = self.is_compactable(node) self.body.append(self.starttag(node, 'ul', CLASS='docstring')) DOCSTRING_WRITER = Writer() DOCSTRING_WRITER.translator_class = NoHeaderHTMLTranslator @register.filter def safe_docstring_display(docstring): """ Utility function to htmlize reST-formatted documentation in browsable api. """ docstring = cleandoc(docstring) return publish_parts(docstring, writer=DOCSTRING_WRITER)['html_body'] @register.filter def urlize_api_links(text): """Utility function for decorating api links in browsable api. Args: text: whose content matching links should be transformed into contextual API or Browse html links. Returns The text transformed if any link is found. The text as is otherwise. """ - return re.sub(r'(/api/[^"<]*/|/browse/.*/|http.*$)', + text = re.sub(r'(/api/[^"<]*/|/browse/.*/|http.*$)', r'\1', text) + return re.sub(r'([^ <>"]+@[^ <>"]+)', + r'\1', + text) @register.filter def urlize_header_links(text): """Utility function for decorating headers links in browsable api. Args text: Text whose content contains Link header value Returns: The text transformed with html link if any link is found. The text as is otherwise. """ return re.sub(r'<(/api/.*|/browse/.*)>', r'<\1>', text) @register.filter def highlight_json(text): return mark_safe(highlight(text, JsonLexer(), HtmlFormatter())) diff --git a/swh/web/templates/person.html b/swh/web/templates/person.html index ebf455f8b..c13efda15 100644 --- a/swh/web/templates/person.html +++ b/swh/web/templates/person.html @@ -1,27 +1,16 @@ {% extends "layout.html" %} +{% load swh_templatetags %} {% block title %}Person{% endblock %} {% block content %} -{% if message is not none %} - {{ message }} -{% endif %} - -{% if person is not none %} -
Details on person {{ person_id }}: - {% for key in ['name', 'email'] %} - {% if person[key] is not none %} -
-
{{ key }}
-
{{ person[key] }}
-
- {% endif %} - {% endfor %} - {% if 'decoding_failures' in person %} -
-
(some decoding errors)
-
- {% endif %} -
-{% endif %} +

Person information

+ + {% for key, val in person.items|dictsort:0 %} + + + + + {% endfor %} +
{{ key }}{{ val | safe | urlize_api_links | escape | safe }}
{% endblock %} diff --git a/swh/web/tests/browse/views/test_person.py b/swh/web/tests/browse/views/test_person.py new file mode 100644 index 000000000..ef0a86618 --- /dev/null +++ b/swh/web/tests/browse/views/test_person.py @@ -0,0 +1,42 @@ +# Copyright (C) 2017 The Software Heritage developers +# See the AUTHORS file at the top-level directory of this distribution +# License: GNU General Public License version 3, or any later version +# See top-level LICENSE file for more information + +from unittest.mock import patch +from nose.tools import istest +from django.test import TestCase + +from swh.web.common.utils import reverse + + +class SwhBrowsePersonTest(TestCase): + + @patch('swh.web.browse.views.person.service') + @istest + def person_browse(self, mock_service): + test_person_data = \ + { + "email": "j.adams440@gmail.com", + "fullname": "oysterCrusher ", + "id": 457587, + "name": "oysterCrusher" + } + + mock_service.lookup_person.return_value = test_person_data + + url = reverse('browse-person', kwargs={'person_id': 457587}) + + resp = self.client.get(url) + + self.assertEquals(resp.status_code, 200) + self.assertTemplateUsed('person.html') + self.assertContains(resp, '%s' % test_person_data['id']) + self.assertContains(resp, '%s' % test_person_data['name']) + self.assertContains(resp, '%s' % + (test_person_data['email'], + test_person_data['email'])) + self.assertContains(resp, '%s <%s>' % + (test_person_data['name'], + test_person_data['email'], + test_person_data['email']))