diff --git a/debian/control b/debian/control
--- a/debian/control
+++ b/debian/control
@@ -8,7 +8,7 @@
libjs-jquery-flot,
libjs-jquery-flot-tooltip,
python3-all,
- python3-flask-api,
+ python3-docutils,
python3-flask-testing,
python3-nose,
python3-setuptools,
diff --git a/swh/web/ui/apidoc.py b/swh/web/ui/apidoc.py
--- a/swh/web/ui/apidoc.py
+++ b/swh/web/ui/apidoc.py
@@ -143,15 +143,6 @@
'doc': argdoc,
'default': default
}
- self.req_args = ['call_args', 'doc_route']
-
- def check_args(self, kwargs):
- missing = [arg for arg in self.req_args if arg not in kwargs]
- if len(missing) > 0:
- message = 'Expected keyword args %s, missing %s.' % (
- ', '.join(self.req_args),
- ', '.join(missing))
- raise SWHAPIDocException(message)
def __call__(self, f):
@wraps(f)
diff --git a/swh/web/ui/renderers.py b/swh/web/ui/renderers.py
--- a/swh/web/ui/renderers.py
+++ b/swh/web/ui/renderers.py
@@ -6,6 +6,7 @@
import re
import yaml
import json
+import sys
from docutils.core import publish_parts
from docutils.writers.html4css1 import Writer, HTMLTranslator
@@ -119,13 +120,6 @@
self.body_prefix = []
self.body_suffix = []
- # disable blockquotes to ignore indentation issue with docstrings
- def visit_block_quote(self, node):
- pass
-
- def depart_block_quote(self, node):
- pass
-
def visit_bullet_list(self, node):
self.context.append((self.compact_simple, self.compact_p))
self.compact_p = None
@@ -141,6 +135,31 @@
Utility function to htmlize reST-formatted documentation in browsable
api.
"""
+
+ def trim(docstring):
+ """Correctly trim triple-quoted docstrings, taking into account
+ first-line indentation inconsistency.
+ Source: https://www.python.org/dev/peps/pep-0257/#handling-docstring-indentation # noqa
+ """
+ if not docstring:
+ return ''
+ lines = docstring.expandtabs().splitlines()
+ indent = sys.maxsize
+ for line in lines[1:]:
+ stripped = line.lstrip()
+ if stripped:
+ indent = min(indent, len(line) - len(stripped))
+ trimmed = [lines[0].strip()]
+ if indent < sys.maxsize:
+ for line in lines[1:]:
+ trimmed.append(line[indent:].rstrip())
+ while trimmed and not trimmed[-1]:
+ trimmed.pop()
+ while trimmed and not trimmed[0]:
+ trimmed.pop(0)
+ return '\n'.join(trimmed)
+
+ docstring = trim(docstring)
return publish_parts(docstring, writer=DOCSTRING_WRITER)['html_body']
diff --git a/swh/web/ui/templates/api.html b/swh/web/ui/templates/api.html
--- a/swh/web/ui/templates/api.html
+++ b/swh/web/ui/templates/api.html
@@ -5,7 +5,7 @@
{% for route, doc in doc_routes %}
- {{ doc }}
+ {% autoescape off %}{{ doc | safe_docstring_display }}{% endautoescape %}
{% endfor %}
diff --git a/swh/web/ui/templates/apidoc.html b/swh/web/ui/templates/apidoc.html
--- a/swh/web/ui/templates/apidoc.html
+++ b/swh/web/ui/templates/apidoc.html
@@ -13,7 +13,7 @@
Request
{{ request.method }} {{ request.url }}
Result
- {% autoescape off %} {{ response_data | urlize_api_links }} {% endautoescape %}
+ {% autoescape off %}{{ response_data | urlize_api_links }}{% endautoescape %}
{% endif %}
diff --git a/swh/web/ui/tests/test_renderers.py b/swh/web/ui/tests/test_renderers.py
--- a/swh/web/ui/tests/test_renderers.py
+++ b/swh/web/ui/tests/test_renderers.py
@@ -214,9 +214,9 @@
# update api link with html links content with links
docstring = """This is my list header:
- - Here is item 1, with a continuation
- line right here
- - Here is item 2
+ - Here is item 1, with a continuation
+ line right here
+ - Here is item 2
Here is something that is not part of the list"""
diff --git a/swh/web/ui/views/browse.py b/swh/web/ui/views/browse.py
--- a/swh/web/ui/views/browse.py
+++ b/swh/web/ui/views/browse.py
@@ -6,9 +6,6 @@
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, apidoc
from ..exc import BadInputExc, NotFoundExc
@@ -19,7 +16,6 @@
@app.route('/api/1/doc/')
-@set_renderers(HTMLRenderer)
def api_doc():
"""Render the API's documentation.
"""
@@ -32,7 +28,6 @@
@app.route('/search/', methods=['GET', 'POST'])
-@set_renderers(HTMLRenderer)
def search():
"""Search for hashes in swh-storage.
@@ -87,7 +82,6 @@
@app.route('/browse/content//')
-@set_renderers(HTMLRenderer)
def browse_content(q):
"""Given a hash and a checksum, display the content's meta-data.
@@ -175,7 +169,6 @@
# @app.route('/browse/content//origin/')
-@set_renderers(HTMLRenderer)
def browse_content_with_origin(q):
"""Show content information.
@@ -205,7 +198,6 @@
@app.route('/browse/directory//')
@app.route('/browse/directory///')
-@set_renderers(HTMLRenderer)
def browse_directory(sha1_git, path=None):
"""Show directory information.
@@ -250,7 +242,6 @@
@app.route('/browse/origin//')
-@set_renderers(HTMLRenderer)
def browse_origin(origin_id):
"""Browse origin with id id.
@@ -273,7 +264,6 @@
@app.route('/browse/person//')
-@set_renderers(HTMLRenderer)
def browse_person(person_id):
"""Browse person with id id.
@@ -291,7 +281,6 @@
@app.route('/browse/release//')
-@set_renderers(HTMLRenderer)
def browse_release(sha1_git):
"""Browse release with sha1_git.
@@ -311,7 +300,6 @@
@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)
@@ -351,7 +339,6 @@
@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
@@ -392,7 +379,6 @@
@app.route('/browse/revision'
'/origin/'
'/ts//log/')
-@set_renderers(HTMLRenderer)
def browse_revision_log_by(origin_id,
branch_name='refs/heads/master',
timestamp=None):
@@ -427,7 +413,6 @@
@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.
@@ -459,7 +444,6 @@
@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.
@@ -501,7 +485,6 @@
@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.
@@ -538,7 +521,6 @@
@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
@@ -639,7 +621,6 @@
'/ts/'
'/history/'
'/directory//')
-@set_renderers(HTMLRenderer)
def browse_directory_through_revision_with_origin_history(
origin_id,
branch_name="refs/heads/master",
@@ -690,7 +671,6 @@
@app.route('/browse/revision'
'/origin/'
'/ts//')
-@set_renderers(HTMLRenderer)
def browse_revision_with_origin(origin_id,
branch_name="refs/heads/master",
ts=None):
@@ -739,7 +719,6 @@
'/branch/'
'/ts/'
'/history//')
-@set_renderers(HTMLRenderer)
def browse_revision_history_through_origin(origin_id,
branch_name='refs/heads/master',
ts=None,
@@ -806,7 +785,6 @@
'/branch/'
'/ts/'
'/directory//')
-@set_renderers(HTMLRenderer)
def browse_revision_directory_through_origin(origin_id,
branch_name='refs/heads/master',
ts=None,
@@ -845,7 +823,6 @@
@app.route('/browse/entity/')
@app.route('/browse/entity//')
-@set_renderers(HTMLRenderer)
def browse_entity(uuid):
env = {'entities': [],
'message': None}
diff --git a/swh/web/ui/views/main.py b/swh/web/ui/views/main.py
--- a/swh/web/ui/views/main.py
+++ b/swh/web/ui/views/main.py
@@ -6,12 +6,9 @@
import flask
from ..main import app
-from flask.ext.api.decorators import set_renderers
-from flask.ext.api.renderers import HTMLRenderer
@app.route('/')
-@set_renderers(HTMLRenderer)
def homepage():
"""Home page
@@ -22,6 +19,5 @@
@app.route('/about/')
-@set_renderers(HTMLRenderer)
def about():
return flask.render_template('about.html')