1 # Copyright 2014-2015 Canonical Limited.
3 # This file is part of charm-helpers.
5 # charm-helpers is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Lesser General Public License version 3 as
7 # published by the Free Software Foundation.
9 # charm-helpers is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public License
15 # along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
22 from docutils
import nodes
23 from docutils
.statemachine
import ViewList
24 from sphinx
.errors
import SphinxError
25 from sphinx
.util
.compat
import Directive
26 from sphinx
.util
.nodes
import nested_parse_with_titles
29 class AutoMemberSummary(Directive
):
30 required_arguments
= 1
33 module_name
= self
.arguments
[0]
36 module
= importlib
.import_module(module_name
)
38 raise SphinxError("Unable to generate reference docs for %s, "
39 "could not import" % (module_name
))
41 divider
= '+{:-<80}+'.format('')
42 row
= '| {:<78} |'.format
44 for member_name
, member
in inspect
.getmembers(module
):
45 if not self
._filter
(module_name
, member_name
, member
):
47 summary
= textwrap
.wrap(self
._get
_summary
(member
), 78) or ['']
48 link
= '`{} <#{}>`_'.format(member_name
,
49 '.'.join([module_name
,
51 methods
= ['* `{} <#{}>`_'.format(n
,
52 '.'.join([module_name
,
55 for n
, m
in inspect
.getmembers(member
)
56 if not n
.startswith('_') and inspect
.isfunction(m
)]
59 lines
.append(row(link
))
62 lines
.append(row(line
))
65 lines
.append(row('Methods:'))
67 for i
, method
in enumerate(methods
):
68 lines
.append(row(method
))
70 content
= '\n'.join(lines
)
72 result
= self
._parse
(content
, '<automembersummary>')
75 def _get_summary(self
, member
):
76 doc
= (member
.__doc
__ or '').splitlines()
78 # strip any leading blank lines
79 while doc
and not doc
[0].strip():
82 # strip anything after the first blank line
83 for i
, piece
in enumerate(doc
):
88 return " ".join(doc
).strip()
90 def _filter(self
, module_name
, member_name
, member
):
91 if member_name
.startswith('_'):
93 if hasattr(member
, '__module__'):
94 # skip imported classes & functions
95 return member
.__module
__.startswith(module_name
)
96 elif hasattr(member
, '__name__'):
97 # skip imported modules
98 return member
.__name
__.startswith(module_name
)
100 return False # skip instances
103 def _parse(self
, rst_text
, annotation
):
105 for line
in rst_text
.split("\n"):
106 result
.append(line
, annotation
)
107 node
= nodes
.paragraph()
108 node
.document
= self
.state
.document
109 nested_parse_with_titles(self
.state
, result
, node
)
114 app
.add_directive('automembersummary', AutoMemberSummary
)