##// END OF EJS Templates
Add option to generate API docs based on __all__
Thomas Kluyver -
Show More
@@ -22,6 +22,12 b' from .validator import validate'
22
22
23 from IPython.utils.log import get_logger
23 from IPython.utils.log import get_logger
24
24
25 __all__ = ['NotebookNode', 'new_code_cell', 'new_text_cell', 'new_notebook',
26 'new_output', 'new_worksheet', 'parse_filename', 'new_metadata', 'new_author',
27 'new_heading_cell', 'nbformat', 'nbformat_minor', 'nbformat_schema',
28 'to_notebook_json', 'convert', 'validate', 'NBFormatError', 'parse_py',
29 'reads_json', 'writes_json', 'reads_py', 'writes_py', 'reads', 'writes', 'read',
30 'write']
25
31
26 current_nbformat = nbformat
32 current_nbformat = nbformat
27 current_nbformat_minor = nbformat_minor
33 current_nbformat_minor = nbformat_minor
@@ -21,6 +21,8 b" if __name__ == '__main__':"
21 # Extensions are documented elsewhere.
21 # Extensions are documented elsewhere.
22 r'\.extensions',
22 r'\.extensions',
23 r'\.config\.profile',
23 r'\.config\.profile',
24 # These should be accessed via nbformat.current
25 r'\.nbformat\.v\d+',
24 ]
26 ]
25
27
26 # The inputhook* modules often cause problems on import, such as trying to
28 # The inputhook* modules often cause problems on import, such as trying to
@@ -33,7 +35,18 b" if __name__ == '__main__':"
33 r'\.frontend$',
35 r'\.frontend$',
34 # We document this manually.
36 # We document this manually.
35 r'\.utils\.py3compat',
37 r'\.utils\.py3compat',
38 # These are exposed by nbformat.current
39 r'\.nbformat\.convert',
40 r'\.nbformat\.validator',
36 ]
41 ]
42
43 # These modules import functions and classes from other places to expose
44 # them as part of the public API. They must have __all__ defined. The
45 # non-API modules they import from should be excluded by the skip patterns
46 # above.
47 docwriter.names_from__all__.update({
48 'IPython.nbformat.current',
49 })
37
50
38 # Now, generate the outputs
51 # Now, generate the outputs
39 docwriter.write_api_docs(outdir)
52 docwriter.write_api_docs(outdir)
@@ -21,6 +21,7 b' from __future__ import print_function'
21
21
22 # Stdlib imports
22 # Stdlib imports
23 import ast
23 import ast
24 import inspect
24 import os
25 import os
25 import re
26 import re
26
27
@@ -85,6 +86,7 b' class ApiDocWriter(object):'
85 rst_extension='.rst',
86 rst_extension='.rst',
86 package_skip_patterns=None,
87 package_skip_patterns=None,
87 module_skip_patterns=None,
88 module_skip_patterns=None,
89 names_from__all__=None,
88 ):
90 ):
89 ''' Initialize package for parsing
91 ''' Initialize package for parsing
90
92
@@ -111,6 +113,12 b' class ApiDocWriter(object):'
111 ``.util.console``
113 ``.util.console``
112 If is None, gives default. Default is:
114 If is None, gives default. Default is:
113 ['\.setup$', '\._']
115 ['\.setup$', '\._']
116 names_from__all__ : set, optional
117 Modules listed in here will be scanned by doing ``from mod import *``,
118 rather than finding function and class definitions by scanning the
119 AST. This is intended for API modules which expose things defined in
120 other files. Modules listed here must define ``__all__`` to avoid
121 exposing everything they import.
114 '''
122 '''
115 if package_skip_patterns is None:
123 if package_skip_patterns is None:
116 package_skip_patterns = ['\\.tests$']
124 package_skip_patterns = ['\\.tests$']
@@ -120,6 +128,7 b' class ApiDocWriter(object):'
120 self.rst_extension = rst_extension
128 self.rst_extension = rst_extension
121 self.package_skip_patterns = package_skip_patterns
129 self.package_skip_patterns = package_skip_patterns
122 self.module_skip_patterns = module_skip_patterns
130 self.module_skip_patterns = module_skip_patterns
131 self.names_from__all__ = names_from__all__ or set()
123
132
124 def get_package_name(self):
133 def get_package_name(self):
125 return self._package_name
134 return self._package_name
@@ -204,6 +213,29 b' class ApiDocWriter(object):'
204 mod = ast.parse(f.read())
213 mod = ast.parse(f.read())
205 return FuncClsScanner().scan(mod)
214 return FuncClsScanner().scan(mod)
206
215
216 def _import_funcs_classes(self, uri):
217 """Import * from uri, and separate out functions and classes."""
218 ns = {}
219 exec('from %s import *' % uri, ns)
220 funcs, classes = [], []
221 for name, obj in ns.items():
222 if inspect.isclass(obj):
223 cls = Obj(name=name, has_init='__init__' in obj.__dict__)
224 classes.append(cls)
225 elif inspect.isfunction(obj):
226 funcs.append(name)
227
228 return sorted(funcs), sorted(classes, key=lambda x: x.name)
229
230 def find_funcs_classes(self, uri):
231 """Find the functions and classes defined in the module ``uri``"""
232 if uri in self.names_from__all__:
233 # For API modules which expose things defined elsewhere, import them
234 return self._import_funcs_classes(uri)
235 else:
236 # For other modules, scan their AST to see what they define
237 return self._parse_module(uri)
238
207 def generate_api_doc(self, uri):
239 def generate_api_doc(self, uri):
208 '''Make autodoc documentation template string for a module
240 '''Make autodoc documentation template string for a module
209
241
@@ -218,7 +250,7 b' class ApiDocWriter(object):'
218 Contents of API doc
250 Contents of API doc
219 '''
251 '''
220 # get the names of all classes and functions
252 # get the names of all classes and functions
221 functions, classes = self._parse_module(uri)
253 functions, classes = self.find_funcs_classes(uri)
222 if not len(functions) and not len(classes):
254 if not len(functions) and not len(classes):
223 #print ('WARNING: Empty -', uri) # dbg
255 #print ('WARNING: Empty -', uri) # dbg
224 return ''
256 return ''
General Comments 0
You need to be logged in to leave comments. Login now