def test_template_renders_with_no_warnings(self): """The Tempita tmpl-api.rst template should render for the sample annotated API docstring with no errors. """ ds = self.sample_api_annotated_docstring template = APITemplateRenderer() template_path = ( "%s/../%s" % (os.path.dirname(__file__), self.api_tempita_template)) api_docstring_parser = APIDocstringParser() api_docstring_parser.parse(ds, uri=self.test_uri_plural) result = template.apply_template(template_path, api_docstring_parser) self.assertThat(result, Not(Contains("API_WARNING")))
def render_api_docs(): """Render ReST documentation for the REST API. This module's docstring forms the head of the documentation; details of the API methods follow. :return: Documentation, in ReST, for the API. :rtype: :class:`unicode` """ from maasserver import urls_api as urlconf module = sys.modules[__name__] output = StringIO() line = partial(print, file=output) line(getdoc(module)) line() line() line("Operations") line("``````````") line() def export_key(export): """Return a sortable key for an export. `op` is often `None`, which cannot be compared to non-`None` operations. """ (http_method, op), function = export if op is None: return http_method, "", function else: return http_method, op, function annotation_parser = APIDocstringParser() templates = APITemplateRenderer() resources = find_api_resources(urlconf) for doc in generate_api_docs(resources): uri_template = doc.resource_uri_template exports = doc.handler.exports.items() # Derive a section title from the name of the handler class. section_name = doc.handler.api_doc_section_name line(section_name) line("=" * len(section_name)) # Note: # The following dedent is useless in the following situation: # # def somefunc(foo) # """No indent here # # Here, there is an indent, so dedent doesn't do # anything. # """ # # This fixes the problem: # # def somefunc(foo) # """ # Indent here # # Now dedent works because the entire docstring appears # to be indented. # """ # # This also works because the dedent version is the same # as the non-dented version: # # def somefunc(foo) # """No indent here""" # line(dedent(doc.handler.__doc__).strip()) line() line() for (http_method, op), function in sorted(exports, key=export_key): operation = " op=%s" % op if op is not None else "" subsection = "``%s %s%s``" % (http_method, uri_template, operation) docstring = getdoc(function) if docstring is not None: if APIDocstringParser.is_annotated_docstring(docstring): operation = "op=%s" % op if op is not None else "" annotation_parser.parse( docstring, http_method, uri_template, operation ) line( templates.apply_template( os.path.dirname(__file__) + "/tmpl-apidoc.rst", annotation_parser, ) ) else: line("%s\n%s\n" % (subsection, "#" * len(subsection))) line() for docline in dedent(docstring).splitlines(): if docline.strip() == "": # Blank line. Don't indent. line() else: # Print documentation line, indented. line(docline) line() else: line("%s\n%s\n" % (subsection, "#" * len(subsection))) line() line() line() line(generate_power_types_doc()) line() line() line(generate_pod_types_doc()) return output.getvalue()