Next step is to allow those to get processed using plugins.
The first paragraph of a module-level, class-level and function-level docstring
is used as a doc summary, copied as-is to the output without formatting it in
-any way.
+any way. What follows is put (again without formatting) paragraph-by-paragraph
+into detailed docs.
.. code:: py
- """Module summary"""
+ """Module summary
+
+ First paragraph of module detailed docs."""
class Foo:
"""Class summary"""
With the current approach, there are a few limitations:
- - Everything after the first paragraph is ignored (there's no way to have
- detailed documentation yet)
- Class and module-level variables can't have a docstring attached due to
how Python works
- Because not every Python API can be documented using docstrings, the
else:
return None
+# Assumes the content is a bunch of raw paragraphs, wrapping them in <p> one
+# by one
+def split_summary_content(doc: str) -> str:
+ summary, _, content = doc.partition('\n\n')
+ content = content.strip()
+ return summary, ('\n'.join(['<p>{}</p>'.format(p) for p in content.split('\n\n')]) if content else None)
+
def extract_summary(state: State, external_docs, path: List[str], doc: str) -> str:
# Prefer external docs, if available
path_str = '.'.join(path)
else:
external_doc_entry = None
+ # some modules (xml.etree) have None as a docstring :(
+ # TODO: render as rst (config option for that)
+ summary, content = split_summary_content(html.escape(inspect.cleandoc(doc or '')))
+
# Summary. Prefer external docs, if available
if external_doc_entry and external_doc_entry['summary']:
summary = render_inline_rst(state, external_doc_entry['summary'])
- else:
- # some modules (xml.etree) have None as a docstring :(
- # TODO: render as rst (config option for that)
- summary = html.escape(inspect.cleandoc(doc or '').partition('\n\n')[0])
# Content
if external_doc_entry and external_doc_entry['content']:
content = render_rst(state, external_doc_entry['content'])
- else:
- # TODO: extract more than just a summary from the docstring
- content = None
# Mark the docs as used (so it can warn about unused docs at the end)
if external_doc_entry: external_doc_entry['used'] = True
elif state.config['PYBIND11_COMPATIBILITY']:
assert hasattr(entry.object, '__members__')
- out.summary, out.content = extract_docs(state, state.enum_docs, entry.path, entry.object.__doc__)
+ # Pybind 2.4 puts enum value docs inside the docstring. We don't parse
+ # that yet and it adds clutter to the output (especially if the values
+ # aren't documented), so cut that away
+ # TODO: implement this
+ out.summary, out.content = extract_docs(state, state.enum_docs, entry.path, entry.object.__doc__.partition('\n\n')[0])
out.has_details = bool(out.content)
out.base = None
value. name = name
value.id = state.config['ID_FORMATTER'](EntryType.ENUM_VALUE, entry.path[-1:] + [name])
value.value = int(v)
- # TODO: once https://github.com/pybind/pybind11/pull/1160 is
- # released, extract from class docs (until then the class
- # docstring is duplicated here, which is useless)
# TODO: external summary for enum values
value.summary = ''
out.values += [value]
<span class="m-doc-wrap-bumper">def <a href="#foo_with_details" class="m-doc">foo_with_details</a>(</span><span class="m-doc-wrap">a, b)</span>
</dt>
<dd>This overwrites the docstring for <code>content.foo_with_details()</code>.</dd>
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#full_docstring" class="m-doc">full_docstring</a>(</span><span class="m-doc-wrap">a, b) -> str</span>
+ </dt>
+ <dd>This function has a full docstring.</dd>
<dt>
<span class="m-doc-wrap-bumper">def <a href="#function_with_summary" class="m-doc">function_with_summary</a>(</span><span class="m-doc-wrap">)</span>
</dt>
<p>This overwrites the docstring for <code>content.foo_with_details()</code>.</p>
<div class="m-note m-info">
Detailed docs for this function</div>
+ </div></section>
+ <section class="m-doc-details" id="full_docstring"><div>
+ <h3>
+ <span class="m-doc-wrap-bumper">def content.<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#full_docstring" class="m-doc-self">full_docstring</a>(</span><span class="m-doc-wrap">a, b) -> str</span></span>
+ </h3>
+ <p>This function has a full docstring.</p>
+<p>It takes one parameter and also another. The details are in two paragraphs,
+each wrapped in its own `<p>`, but not additionally formatted or parsed in any
+way.</p>
+<p>Like this.</p>
</div></section>
<section class="m-doc-details" id="function_with_summary"><div>
<h3>
def param_docs_wrong(a, b):
"""Should give warnings"""
+def full_docstring(a, b) -> str:
+ """This function has a full docstring.
+
+ It takes one parameter and also another. The details are in two paragraphs,
+ each wrapped in its own `<p>`, but not additionally formatted or parsed in any
+ way.
+
+ Like this.
+ """
+
CONSTANT: float = 3.14
DATA_WITH_DETAILS: str = 'heyoo'
<span class="m-doc-wrap-bumper">def <a href="#pow" class="m-doc-self">pow</a>(</span><span class="m-doc-wrap">x, y<span class="m-text m-dim">, /</span>)</span>
</dt>
<dd>Return x**y (x to the power of y).</dd>
- <dt id="log">
- <span class="m-doc-wrap-bumper">def <a href="#log" class="m-doc-self">log</a>(</span><span class="m-doc-wrap">...)</span>
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#log" class="m-doc">log</a>(</span><span class="m-doc-wrap">...)</span>
</dt>
<dd>log(x, [base=math.e])
Return the logarithm of x to the given base.</dd>
</dl>
</section>
+ <section>
+ <h2>Function documentation</h2>
+ <section class="m-doc-details" id="log"><div>
+ <h3>
+ <span class="m-doc-wrap-bumper">def math.<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#log" class="m-doc-self">log</a>(</span><span class="m-doc-wrap">...)</span></span>
+ </h3>
+ <p>log(x, [base=math.e])
+Return the logarithm of x to the given base.</p>
+<p>If the base not specified, returns the natural logarithm (base e) of x.</p>
+ </div></section>
+ </section>
</div>
</div>
</div>
<section id="functions">
<h2><a href="#functions">Functions</a></h2>
<dl class="m-doc">
- <dt id="log">
- <span class="m-doc-wrap-bumper">def <a href="#log" class="m-doc-self">log</a>(</span><span class="m-doc-wrap">...)</span>
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#log" class="m-doc">log</a>(</span><span class="m-doc-wrap">...)</span>
</dt>
<dd>log(x[, base])</dd>
</dl>
</section>
+ <section>
+ <h2>Function documentation</h2>
+ <section class="m-doc-details" id="log"><div>
+ <h3>
+ <span class="m-doc-wrap-bumper">def math.<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#log" class="m-doc-self">log</a>(</span><span class="m-doc-wrap">...)</span></span>
+ </h3>
+ <p>log(x[, base])</p>
+<p>Return the logarithm of x to the given base.
+If the base not specified, returns the natural logarithm (base e) of x.</p>
+ </div></section>
+ </section>
</div>
</div>
</div>
<span class="m-doc-wrap-bumper">def <a href="#pow" class="m-doc-self">pow</a>(</span><span class="m-doc-wrap">x, y<span class="m-text m-dim">, /</span>)</span>
</dt>
<dd>Return x**y (x to the power of y).</dd>
- <dt id="log">
- <span class="m-doc-wrap-bumper">def <a href="#log" class="m-doc-self">log</a>(</span><span class="m-doc-wrap">...)</span>
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#log" class="m-doc">log</a>(</span><span class="m-doc-wrap">...)</span>
</dt>
<dd>log(x, [base=math.e])
Return the logarithm of x to the given base.</dd>
</dl>
</section>
+ <section>
+ <h2>Function documentation</h2>
+ <section class="m-doc-details" id="log"><div>
+ <h3>
+ <span class="m-doc-wrap-bumper">def math.<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#log" class="m-doc-self">log</a>(</span><span class="m-doc-wrap">...)</span></span>
+ </h3>
+ <p>log(x, [base=math.e])
+Return the logarithm of x to the given base.</p>
+<p>If the base not specified, returns the natural logarithm (base e) of x.</p>
+ </div></section>
+ </section>
</div>
</div>
</div>