Page MenuHomeSoftware Heritage

D2667.diff
No OneTemporary

D2667.diff

diff --git a/swh/web/api/apidoc.py b/swh/web/api/apidoc.py
--- a/swh/web/api/apidoc.py
+++ b/swh/web/api/apidoc.py
@@ -63,6 +63,7 @@
self.reqheaders_set = set()
self.resheaders_set = set()
self.field_list_visited = False
+ self.current_json_obj = None
def process_paragraph(self, par):
"""
@@ -82,8 +83,12 @@
# remove parsed document markups
par = re.sub('<[^<]+?>', '', par)
# api urls cleanup to generate valid links afterwards
- par = re.sub(r'\(\w+\)', '', par)
- par = re.sub(r'\[.*\]', '', par)
+ subs_made = 1
+ while subs_made:
+ (par, subs_made) = re.subn(r'(:http:.*)(\(\w+\))', r'\1', par)
+ subs_made = 1
+ while subs_made:
+ (par, subs_made) = re.subn(r'(:http:.*)(\[.*\])', r'\1', par)
par = par.replace('//', '/')
# transform references to api endpoints into valid rst links
par = re.sub(':http:get:`([^,]*)`', r'`<\1>`_', par)
@@ -135,6 +140,7 @@
'type': field_data[1],
'doc': text})
self.inputs_set.add(field_data[2])
+ self.current_json_obj = self.data['inputs'][-1]
# Response type
if (field_data[0] in self.response_json_array_roles or
field_data[0] in self.response_json_object_roles):
@@ -150,6 +156,7 @@
'type': field_data[1],
'doc': text})
self.returns_set.add(field_data[2])
+ self.current_json_obj = self.data['returns'][-1]
# Status Codes
if field_data[0] in self.status_code_roles:
if field_data[1] not in self.status_codes_set:
@@ -218,6 +225,14 @@
if isinstance(child, docutils.nodes.paragraph):
line_text = self.process_paragraph(str(child))
self.data['description'] += '\t* %s\n' % line_text
+ elif self.current_json_obj:
+ self.current_json_obj['doc'] += '\n\n'
+ for child in node.traverse():
+ # process list item
+ if isinstance(child, docutils.nodes.paragraph):
+ line_text = self.process_paragraph(str(child))
+ self.current_json_obj['doc'] += '\t\t* %s\n' % line_text
+ self.current_json_obj = None
def visit_warning(self, node):
text = self.process_paragraph(str(node))
diff --git a/swh/web/assets/src/bundles/webapp/webapp.css b/swh/web/assets/src/bundles/webapp/webapp.css
--- a/swh/web/assets/src/bundles/webapp/webapp.css
+++ b/swh/web/assets/src/bundles/webapp/webapp.css
@@ -507,6 +507,12 @@
margin: 10px;
}
+.swh-apidoc .swh-rst blockquote {
+ border: 0;
+ margin: 0;
+ padding: 0;
+}
+
a.toggle-col {
text-decoration: none;
}
diff --git a/swh/web/common/middlewares.py b/swh/web/common/middlewares.py
--- a/swh/web/common/middlewares.py
+++ b/swh/web/common/middlewares.py
@@ -3,10 +3,11 @@
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
-from bs4 import BeautifulSoup
from htmlmin import minify
import sentry_sdk
+from swh.web.common.utils import prettify_html
+
class HtmlPrettifyMiddleware(object):
"""
@@ -22,11 +23,10 @@
if 'text/html' in response.get('Content-Type', ''):
if hasattr(response, 'content'):
content = response.content
- response.content = BeautifulSoup(content, 'lxml').prettify()
+ response.content = prettify_html(content)
elif hasattr(response, 'streaming_content'):
content = b''.join(response.streaming_content)
- response.streaming_content = \
- BeautifulSoup(content, 'lxml').prettify()
+ response.streaming_content = prettify_html(content)
return response
diff --git a/swh/web/common/swh_templatetags.py b/swh/web/common/swh_templatetags.py
--- a/swh/web/common/swh_templatetags.py
+++ b/swh/web/common/swh_templatetags.py
@@ -6,8 +6,6 @@
import json
import re
-from inspect import cleandoc
-
from django import template
from django.core.serializers.json import DjangoJSONEncoder
from django.utils.safestring import mark_safe
@@ -21,12 +19,12 @@
@register.filter
-def safe_docstring_display(docstring):
+def docstring_display(docstring):
"""
Utility function to htmlize reST-formatted documentation in browsable
api.
"""
- return rst_to_html(cleandoc(docstring))
+ return rst_to_html(docstring)
@register.filter
diff --git a/swh/web/common/utils.py b/swh/web/common/utils.py
--- a/swh/web/common/utils.py
+++ b/swh/web/common/utils.py
@@ -14,6 +14,8 @@
import docutils.parsers.rst
import docutils.utils
+from bs4 import BeautifulSoup
+
from docutils.core import publish_parts
from docutils.writers.html5_polyglot import Writer, HTMLTranslator
@@ -477,3 +479,16 @@
pp = publish_parts(rst, writer=_HTML_WRITER,
settings_overrides=settings)
return f'<div class="swh-rst">{pp["html_body"]}</div>'
+
+
+def prettify_html(html: str) -> str:
+ """
+ Prettify an HTML document.
+
+ Args:
+ html: Input HTML document
+
+ Returns:
+ The prettified HTML document
+ """
+ return BeautifulSoup(html, 'lxml').prettify()
diff --git a/swh/web/templates/api/apidoc.html b/swh/web/templates/api/apidoc.html
--- a/swh/web/templates/api/apidoc.html
+++ b/swh/web/templates/api/apidoc.html
@@ -35,7 +35,7 @@
{% if description %}
<div>
<h4> Description </h4>
- {{ description | safe_docstring_display | safe }}
+ {{ description | docstring_display | safe }}
</div>
{% endif %}
{% if response_data is not None %}
@@ -71,7 +71,7 @@
<tbody>
{% for url in urls %}
<tr>
- <td>{{ url.rule | safe_docstring_display | safe }}</td>
+ <td>{{ url.rule | docstring_display | safe }}</td>
<td>{{ url.methods | dictsort:0 | join:', ' }}</td>
</tr>
{% endfor %}
@@ -86,7 +86,7 @@
{% for arg in args %}
<dl class="row">
<dt class="col col-md-2 text-right"> {{ arg.name }} ({{ arg.type }}) </dt>
- <dd class="col col-md-9"> {{ arg.doc | safe_docstring_display | safe }} </dd>
+ <dd class="col col-md-9"> {{ arg.doc | docstring_display | safe }} </dd>
</dl>
{% endfor %}
</div>
@@ -98,7 +98,7 @@
{% for param in params %}
<dl class="row">
<dt class="col col-md-2 text-right"> {{ param.name }} ({{ param.type }}) </dt>
- <dd class="col col-md-9"> {{ param.doc | safe_docstring_display | safe }} </dd>
+ <dd class="col col-md-9"> {{ param.doc | docstring_display | safe }} </dd>
</dl>
{% endfor %}
</div>
@@ -110,7 +110,7 @@
{% for header in reqheaders %}
<dl class="row">
<dt class="col col-md-2 text-right"> {{ header.name }} </dt>
- <dd class="col col-md-9"> {{ header.doc | safe_docstring_display | safe }} </dd>
+ <dd class="col col-md-9"> {{ header.doc | docstring_display | safe }} </dd>
</dl>
{% endfor %}
</div>
@@ -133,7 +133,7 @@
an object containing the following keys:
{% endif %}
{% if inputs_list != '' %}
- {{ inputs_list | safe_docstring_display | safe }}
+ {{ inputs_list | docstring_display | safe }}
{% endif %}
</p>
</dd>
@@ -147,7 +147,7 @@
{% for header in resheaders %}
<dl class="row">
<dt class="col col-md-2 text-right"> {{ header.name }} </dt>
- <dd class="col col-md-9"> {{ header.doc | safe_docstring_display | safe }} </dd>
+ <dd class="col col-md-9"> {{ header.doc | docstring_display | safe }} </dd>
</dl>
{% endfor %}
</div>
@@ -170,7 +170,7 @@
an object containing the following keys:
{% endif %}
{% if returns_list != '' %}
- {{ returns_list | safe_docstring_display | safe }}
+ {{ returns_list | docstring_display | safe }}
{% endif %}
</p>
</dd>
@@ -184,7 +184,7 @@
{% for status in status_codes %}
<dl class="row">
<dt class="col col-md-2 text-right"> {{ status.code }} </dt>
- <dd class="col col-md-9"> {{ status.doc | safe_docstring_display | safe }} </dd>
+ <dd class="col col-md-9"> {{ status.doc | docstring_display | safe }} </dd>
</dl>
{% endfor %}
</div>
diff --git a/swh/web/templates/api/endpoints.html b/swh/web/templates/api/endpoints.html
--- a/swh/web/templates/api/endpoints.html
+++ b/swh/web/templates/api/endpoints.html
@@ -59,7 +59,7 @@
{% endif %}
<td class="d-none d-sm-table-cell">
<a href="{% url doc.route_view_name %}">
- {{ doc.doc_intro | safe_docstring_display | safe }}
+ {{ doc.doc_intro | docstring_display | safe }}
</a>
</td>
</tr>
diff --git a/swh/web/tests/api/test_apidoc.py b/swh/web/tests/api/test_apidoc.py
--- a/swh/web/tests/api/test_apidoc.py
+++ b/swh/web/tests/api/test_apidoc.py
@@ -3,6 +3,8 @@
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
+import textwrap
+
import pytest
from rest_framework.response import Response
@@ -12,8 +14,8 @@
from swh.web.api.apidoc import api_doc, _parse_httpdomain_doc
from swh.web.api.apiurls import api_route
from swh.web.common.exc import BadInputExc, ForbiddenExc, NotFoundExc
-from swh.web.common.utils import reverse
-from swh.web.tests.django_asserts import assert_template_used, assert_contains
+from swh.web.common.utils import reverse, prettify_html
+from swh.web.tests.django_asserts import assert_template_used
_httpdomain_doc = """
@@ -229,7 +231,7 @@
expected_reqheaders = [{
'doc': ('the requested response content type, either '
- '``application/json`` or ``application/yaml``'),
+ '``application/json`` (default) or ``application/yaml``'),
'name': 'Accept'
}]
@@ -378,9 +380,10 @@
:<jsonarr string -: Input array of pids
- :>jsonarr string type: swh object type
- :>jsonarr string sha1_git: swh object sha1_git
- :>jsonarr boolean found: whether the object was found or not
+ :>json object <swh_pid>: an object whose keys are input persistent
+ identifiers and values objects with the following keys:
+
+ * **known (bool)**: whether the object was found
"""
pass
@@ -392,40 +395,60 @@
assert rv.status_code == 200, rv.content
assert_template_used(rv, 'api/apidoc.html')
- input_html_doc = (
- ' <dl class="row">\n'
- ' <dt class="col col-md-2 text-right"> array </dt>\n'
- ' <dd class="col col-md-9">\n'
- ' <p>\n'
- ' \n'
- ' Input array of pids\n'
- ' \n'
- ' \n'
- ' </p>\n'
- ' </dd>\n'
- ' </dl>\n'
- )
-
- output_html_doc = (
- ' <dl class="row">\n'
- ' <dt class="col col-md-2 text-right"> array </dt>\n'
- ' <dd class="col col-md-9">\n'
- ' <p>\n'
- ' \n'
- ' an array of objects containing the following keys:\n'
- ' \n'
- ' \n'
- ' <div class="swh-rst"><ul class="simple">\n'
- '<li><p><strong>type (string)</strong>: swh object type</p></li>\n'
- '<li><p><strong>sha1_git (string)</strong>: swh object sha1_git</p></li>\n' # noqa
- '<li><p><strong>found (boolean)</strong>: whether the object was found or not</p></li>\n' # noqa
- '</ul>\n'
- '</div>\n'
- ' \n'
- ' </p>\n'
- ' </dd>\n'
- ' </dl>'
- )
-
- assert_contains(rv, input_html_doc)
- assert_contains(rv, output_html_doc)
+ input_html_doc = textwrap.indent((
+ '<dl class="row">\n'
+ ' <dt class="col col-md-2 text-right">\n'
+ ' array\n'
+ ' </dt>\n'
+ ' <dd class="col col-md-9">\n'
+ ' <p>\n'
+ ' Input array of pids\n'
+ ' </p>\n'
+ ' </dd>\n'
+ '</dl>\n'
+ ), ' '*7)
+
+ output_html_doc = textwrap.indent((
+ '<dl class="row">\n'
+ ' <dt class="col col-md-2 text-right">\n'
+ ' object\n'
+ ' </dt>\n'
+ ' <dd class="col col-md-9">\n'
+ ' <p>\n'
+ ' an object containing the following keys:\n'
+ ' </p>\n'
+ ' <div class="swh-rst">\n'
+ ' <blockquote>\n'
+ ' <ul>\n'
+ ' <li>\n'
+ ' <p>\n'
+ ' <strong>\n'
+ ' &lt;swh_pid&gt; (object)\n'
+ ' </strong>\n'
+ ' : an object whose keys are input persistent identifiers'
+ ' and values objects with the following keys:\n'
+ ' </p>\n'
+ ' <blockquote>\n'
+ ' <ul class="simple">\n'
+ ' <li>\n'
+ ' <p>\n'
+ ' <strong>\n'
+ ' known (bool)\n'
+ ' </strong>\n'
+ ' : whether the object was found\n'
+ ' </p>\n'
+ ' </li>\n'
+ ' </ul>\n'
+ ' </blockquote>\n'
+ ' </li>\n'
+ ' </ul>\n'
+ ' </blockquote>\n'
+ ' </div>\n'
+ ' </dd>\n'
+ '</dl>\n'
+ ), ' '*7)
+
+ html = prettify_html(rv.content)
+
+ assert input_html_doc in html
+ assert output_html_doc in html
diff --git a/swh/web/tests/common/test_templatetags.py b/swh/web/tests/common/test_templatetags.py
--- a/swh/web/tests/common/test_templatetags.py
+++ b/swh/web/tests/common/test_templatetags.py
@@ -4,7 +4,7 @@
# See top-level LICENSE file for more information
from swh.web.common.swh_templatetags import (
- urlize_links_and_mails, urlize_header_links, safe_docstring_display
+ urlize_links_and_mails, urlize_header_links, docstring_display
)
@@ -36,7 +36,7 @@
assert urlize_header_links(content) == expected_content
-def test_safe_docstring_display():
+def test_docstring_display():
# update api link with html links content with links
docstring = (
'This is my list header:\n\n'
@@ -49,13 +49,15 @@
expected_docstring = (
'<div class="swh-rst">'
'<p>This is my list header:</p>\n'
+ '<blockquote>\n'
'<ul class="simple">\n'
'<li><p>Here is item 1, with a continuation\n'
'line right here</p></li>\n'
'<li><p>Here is item 2</p></li>\n'
'</ul>\n'
'<p>Here is something that is not part of the list</p>\n'
+ '</blockquote>\n'
'</div>'
)
- assert safe_docstring_display(docstring) == expected_docstring
+ assert docstring_display(docstring) == expected_docstring

File Metadata

Mime Type
text/plain
Expires
Dec 21 2024, 5:37 PM (11 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3215589

Event Timeline