1 # Copyright 2014-2015 Canonical Limited.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
20 from docutils
import nodes
21 from docutils
.statemachine
import ViewList
22 from sphinx
.errors
import SphinxError
23 from sphinx
.util
.compat
import Directive
24 from sphinx
.util
.nodes
import nested_parse_with_titles
27 class AutoMemberSummary(Directive
):
28 required_arguments
= 1
31 module_name
= self
.arguments
[0]
34 module
= importlib
.import_module(module_name
)
36 raise SphinxError("Unable to generate reference docs for %s, "
37 "could not import" % (module_name
))
39 divider
= '+{:-<80}+'.format('')
40 row
= '| {:<78} |'.format
42 for member_name
, member
in inspect
.getmembers(module
):
43 if not self
._filter
(module_name
, member_name
, member
):
45 summary
= textwrap
.wrap(self
._get
_summary
(member
), 78) or ['']
46 link
= '`{} <#{}>`_'.format(member_name
,
47 '.'.join([module_name
,
49 methods
= ['* `{} <#{}>`_'.format(n
,
50 '.'.join([module_name
,
53 for n
, m
in inspect
.getmembers(member
)
54 if not n
.startswith('_') and inspect
.isfunction(m
)]
57 lines
.append(row(link
))
60 lines
.append(row(line
))
63 lines
.append(row('Methods:'))
65 for i
, method
in enumerate(methods
):
66 lines
.append(row(method
))
68 content
= '\n'.join(lines
)
70 result
= self
._parse
(content
, '<automembersummary>')
73 def _get_summary(self
, member
):
74 doc
= (member
.__doc
__ or '').splitlines()
76 # strip any leading blank lines
77 while doc
and not doc
[0].strip():
80 # strip anything after the first blank line
81 for i
, piece
in enumerate(doc
):
86 return " ".join(doc
).strip()
88 def _filter(self
, module_name
, member_name
, member
):
89 if member_name
.startswith('_'):
91 if hasattr(member
, '__module__'):
92 # skip imported classes & functions
93 return member
.__module
__.startswith(module_name
)
94 elif hasattr(member
, '__name__'):
95 # skip imported modules
96 return member
.__name
__.startswith(module_name
)
98 return False # skip instances
101 def _parse(self
, rst_text
, annotation
):
103 for line
in rst_text
.split("\n"):
104 result
.append(line
, annotation
)
105 node
= nodes
.paragraph()
106 node
.document
= self
.state
.document
107 nested_parse_with_titles(self
.state
, result
, node
)
112 app
.add_directive('automembersummary', AutoMemberSummary
)