Georg Brandl avatar Georg Brandl committed c84818a

* ``apidoc`` now ignores "_private" modules by default, and has an option ``-P``
to include them.

* ``apidoc`` now has an option to not generate headings for packages and
modules, for the case that the module docstring already includes a reST
heading.

Comments (0)

Files changed (2)

 Features added
 --------------
 
+* ``apidoc`` now ignores "_private" modules by default, and has an option ``-P``
+  to include them.
+* ``apidoc`` now has an option to not generate headings for packages and
+  modules, for the case that the module docstring already includes a reST
+  heading.
+* PR#161: ``apidoc`` can now write each module to a standalone page instead of
+  combining all modules in a package on one page.
 * Builders: rebuild i18n target document when catalog updated.
 * Support docutils.conf 'writers' and 'html4css1 writer' section in the HTML
   writer.  The latex, manpage and texinfo writers also support their respective
   include members imported from different modules.
 * New locales: Macedonian, Sinhala, Indonesian.
 * Theme package collection by using setuptools plugin mechanism.
-* PR#161: ``apidoc`` can now write each module to a standalone page instead of
-  combining all modules in a package on one page.
 
 Incompatible changes
 --------------------
 
 def create_module_file(package, module, opts):
     """Build the text of the file and write the file."""
-    text = format_heading(1, '%s Module' % module)
+    if not opts.noheadings:
+        text = format_heading(1, '%s module' % module)
+    else:
+        text = ''
     #text += format_heading(2, ':mod:`%s` Module' % module)
     text += format_directive(module, package)
     write_file(makename(package, module), text, opts)
 
 def create_package_file(root, master_package, subroot, py_files, opts, subs):
     """Build the text of the file and write the file."""
-    package = path.split(root)[-1]
-    text = format_heading(1, '%s Package' % package)
-    # add each module in the package
-    for py_file in py_files:
-        if shall_skip(path.join(root, py_file)):
-            continue
-        is_package = py_file == INITPY
-        py_file = path.splitext(py_file)[0]
-        py_path = makename(subroot, py_file)
-        if is_package:
-            heading = ':mod:`%s` Package' % package
-        else:
-            heading = ':mod:`%s` Module' % py_file
+    text = format_heading(1, '%s package' % makename(master_package, subroot))
 
-        # option to have each module go on its own page
-        if opts.separatepages:
-            if is_package:
-                # we handle packages SLIGHTLY differently in this case; no need
-                # for double nested heading for package that apidoc usually does
-                # since all other modules are going to be on separate pages
-                text += format_directive(is_package and subroot or py_path,
-                                         master_package)
-            else:
-                # with separatepages option, instead of embedding all module
-                # file contents on the one package page, each module will have
-                # its own page.
-                outfilepath = makename(master_package, py_path)
-                # text for this page just links to standalone page
-                text += '.. toctree::\n\n'
-                text += '    %s\n\n' % outfilepath
-                # and now the contents of the standalone page file is just what
-                # apidoc used to write inside this page, but with top level
-                # heading.
-                filetext = format_heading(1, heading)
-                filetext += format_directive(is_package and subroot or py_path,
-                                             master_package)
-                # write out standalone page file
-                write_file(outfilepath, filetext, opts)
-        else:
-            # standard apidoc behavior
-            text += format_heading(2, heading)
-            text += format_directive(is_package and subroot or py_path,
-                                     master_package)
-
-        text += '\n'
-
-    # build a list of directories that are packages (contain an INITPY file)
+    # build a list of directories that are szvpackages (contain an INITPY file)
     subs = [sub for sub in subs if path.isfile(path.join(root, sub, INITPY))]
     # if there are some package directories, add a TOC for theses subpackages
     if subs:
             text += '    %s.%s\n' % (makename(master_package, subroot), sub)
         text += '\n'
 
+    submods = [path.splitext(sub)[0] for sub in py_files
+               if not shall_skip(path.join(root, sub), opts)
+               and sub != INITPY]
+    if submods:
+        text += format_heading(2, 'Submodules')
+        if opts.separatemodules:
+            text += '.. toctree::\n\n'
+            for submod in submods:
+                modfile = makename(master_package, makename(subroot, submod))
+                text += '   %s\n' % modfile
+
+                # generate separate file for this module
+                if not opts.noheadings:
+                    filetext = format_heading(1, '%s module' % modfile)
+                else:
+                    filetext = ''
+                filetext += format_directive(makename(subroot, submod),
+                                             master_package)
+                write_file(modfile, filetext, opts)
+        else:
+            for submod in submods:
+                modfile = makename(master_package, makename(subroot, submod))
+                if not opts.noheadings:
+                    text += format_heading(2, '%s module' % modfile)
+                text += format_directive(makename(subroot, submod),
+                                         master_package)
+                text += '\n'
+        text += '\n'
+
+    text += format_heading(2, 'Module contents')
+    text += format_directive(subroot, master_package)
+
     write_file(makename(master_package, subroot), text, opts)
 
 
     write_file(name, text, opts)
 
 
-def shall_skip(module):
+def shall_skip(module, opts):
     """Check if we want to skip this module."""
     # skip it if there is nothing (or just \n or \r\n) in the file
-    return path.getsize(module) <= 2
+    if path.getsize(module) <= 2:
+        return True
+    # skip if it has a "private" name and this is selected
+    filename = path.basename(module)
+    if filename != '__init__.py' and filename.startswith('_') and \
+        not opts.includeprivate:
+        return True
+    return False
 
 
 def recurse_tree(rootpath, excludes, opts):
         if is_pkg:
             # we are in a package with something to document
             if subs or len(py_files) > 1 or not \
-                shall_skip(path.join(root, INITPY)):
+                shall_skip(path.join(root, INITPY), opts):
                 subpackage = root[len(rootpath):].lstrip(path.sep).\
                     replace(path.sep, '.')
                 create_package_file(root, root_package, subpackage,
             # if we are at the root level, we don't require it to be a package
             assert root == rootpath and root_package is None
             for py_file in py_files:
-                if not shall_skip(path.join(rootpath, py_file)):
+                if not shall_skip(path.join(rootpath, py_file), opts):
                     module = path.splitext(py_file)[0]
                     create_module_file(root_package, module, opts)
                     toplevels.append(module)
                       help='Maximum depth of submodules to show in the TOC '
                       '(default: 4)', type='int', default=4)
     parser.add_option('-f', '--force', action='store_true', dest='force',
-                      help='Overwrite all files')
+                      help='Overwrite existing files')
     parser.add_option('-l', '--follow-links', action='store_true',
                       dest='followlinks', default=False,
                       help='Follow symbolic links. Powerful when combined '
                       'with collective.recipe.omelette.')
     parser.add_option('-n', '--dry-run', action='store_true', dest='dryrun',
                       help='Run the script without creating files')
-    parser.add_option('-E', '--separate', action='store_true',
-                      dest='separatepages',
+    parser.add_option('-e', '--separate', action='store_true',
+                      dest='separatemodules',
                       help='Put documentation for each module on its own page')
+    parser.add_option('-P', '--private', action='store_true',
+                      dest='includeprivate',
+                      help='Include "_private" modules')
     parser.add_option('-T', '--no-toc', action='store_true', dest='notoc',
                       help='Don\'t create a table of contents file')
+    parser.add_option('-E', '--no-headings', action='store_true',
+                      dest='noheadings',
+                      help='Don\'t create headings for the module/package '
+                           'packages (e.g. when the docstrings already contain '
+                           'them)')
     parser.add_option('-s', '--suffix', action='store', dest='suffix',
                       help='file suffix (default: rst)', default='rst')
     parser.add_option('-F', '--full', action='store_true', dest='full',
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.