-
-
Notifications
You must be signed in to change notification settings - Fork 31
/
documenters.py
85 lines (72 loc) · 3.08 KB
/
documenters.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import inspect
import re
from sphinx.ext.autodoc import MethodDocumenter
class OverloadedPythonMethodDocumenter(MethodDocumenter):
"""
A method documenter which handles overloaded methods, via processing
the docstrings generated by SIP
"""
objtype = "method"
priority = MethodDocumenter.priority
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
return MethodDocumenter.can_document_member(member, membername, isattr, parent)
def parse_signature_blocks(self, docstring):
"""
Extracts each signature from a sip generated docstring, and
returns each signature in a tuple with the docs for just
that signature.
"""
res = []
current_sig = ""
current_desc = ""
for line in docstring.split("\n"):
match = re.match(r"^\w+(\([^)]*\)(?:\s*->\s*[^:\n]+)?)\s*((?:(?!\w+\().)*)\s*$", line)
if match:
if current_sig:
res.append((current_sig, current_desc))
current_sig = match.group(1)
current_desc = match.group(2)
if current_desc:
current_desc += "\n"
else:
current_desc += line + "\n"
if current_sig:
res.append((current_sig, current_desc))
return res
def add_content(self, more_content):
"""
Parse the docstring to get all signatures and their descriptions
"""
sourcename = self.get_sourcename()
docstring = inspect.getdoc(self.object)
if docstring:
# does this method have multiple overrides?
signature_blocks = self.parse_signature_blocks(docstring)
if len(signature_blocks) <= 1:
# nope, just use standard formatter then!
super().add_content(more_content)
return
# add a method output for EVERY override
for i, (signature, description) in enumerate(signature_blocks):
if i > 0:
self.add_line("", sourcename)
# this pattern is used in the autodoc source!
old_indent = self.indent
new_indent = (
" "
* len(self.content_indent)
* (len(self.indent) // len(self.content_indent) - 1)
)
# skip the signature for the first overload. This will already
# have been included by the base class Documenter logic!
if i > 0:
self.indent = new_indent
self.add_directive_header(signature)
self.indent = old_indent
# we can only index the first signature!
self.add_line(":no-index:", sourcename)
self.add_line("", sourcename)
doc_for_this_override = self.object_name + signature + "\n" + description
for line in self.process_doc([doc_for_this_override.split("\n")]):
self.add_line(line, sourcename)