定制`sphinx-apidoc`的模板

21
我最近尝试使用Sphinx中的sphinx-apidoc,来帮助从Python项目的API生成Sphinx特定的reStructuredText。
然而,我得到的结果是:

Default look of <code>sphinx-api</code> result

有人知道我是否可以自定义模板用于其输出吗?具体来说,我想要:
- 摆脱所有“子模块”、“子包”和“模块内容”标题,并且 - 让我的__init__.py文件中的docstring结果直接出现在包下面,这样如果我点击包名称,我看到的第一件事就是包文档。目前,该文档放置在每个包部分末尾略微奇怪的“模块内容”标题下。
“子模块”和“子包”标题我认为是多余的,因为包/模块的常规标题是“xxx.yyy package”和“xxx.yyy.zzz module”。
我想要上述小例子的结构是
- orexplore.components包
- orexplore.components.mbg120模块
- orexplore.simulators包
- orexplore.simulators.test包
- orexplore.simulators.test.mbg120模块 - orexplore.simulators.mbg120模块
当我点击软件包时,第一件看到的就是软件包文档。
或许只需要这样:
  • orexplore.components
    • orexplore.components.mbg120
  • orexplore.simulators
    • orexplore.simulators.test
      • orexplore.simulators.test.mbg120
  • orexplore.simulators.mbg120
如果有一种视觉上区分包/模块(颜色?徽章?)的方法,而不是使用相当冗长的“package”和“module”,那将会更好。
3个回答

9

你的工具在Sphinx中非常需要,这对于平淡无奇的文档来说非常棒,但是对于API参考却极其缺乏。我想知道是否可能实现类似于这个的结果。Pyside使用Sphinx进行文档编写,但正如你所看到的,它已经被大量定制。输出结果与Doxygen有些相似:首先是类名,然后是继承图,接着是简要或完整的描述,然后是成员和方法列表,最后是详细部分。这样更容易阅读。 - Dan Niero
你是否知道有一个“better-apidoc”模板,可以将子包和子模块列表合并为一个,符合原始问题的要求? - Peter Cock

5

以下是一个完整的脚本,用于在每个“filename.rst”旁边创建一个“filename.rst.new”文件,并进行您所需的更改,这也是我所需的更改:

#!/usr/bin/env python

'''
Rearrange content in sphinx-apidoc generated .rst files.

* Move "Module Contents" section to the top.
* Remove headers for "Module Contents", "Submodules" and "Subpackages",
  including their underlines and the following blank line.
'''


import argparse
import glob
import os


# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def argument_parser():
    '''
    Define command line arguments.
    '''

    parser = argparse.ArgumentParser(
        description='''
        Rearrange content in sphinx-apidoc generated .rst files.
        '''
        )

    parser.add_argument(
        '-v', '--verbose',
        dest='verbose',
        default=False,
        action='store_true',
        help="""
            show more output.
            """
        )

    parser.add_argument(
        'input_file',
        metavar="INPUT_FILE",
        nargs='+',
        help="""
            file.
            """
        )

    return parser


# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def main():
    '''
    Main program entry point.
    '''

    global args
    parser = argument_parser()
    args = parser.parse_args()

    filenames = [glob.glob(x) for x in args.input_file]
    if len(filenames) > 0:
        filenames = reduce(lambda x, y: x + y, filenames)

    for filename in set(filenames):

        # line_num was going to be for some consistency checks, never
        # implemented but left in place.
        found = {
            'Subpackages': {'contents': False, 'line_num': None},
            'Submodules': {'contents': False, 'line_num': None},
            'Module contents': {'contents': True, 'line_num': None},
            }

        in_module_contents = False
        line_num = 0
        reordered = []
        module_contents = []

        new_filename = '.'.join([filename, 'new'])

        with open(filename, 'r') as fptr:

            for line in fptr:
                line = line.rstrip()
                discard = False

                line_num += 1

                if (
                        in_module_contents
                        and len(line) > 0
                        and line[0] not in ['.', '-', ' ']
                        ):  # pylint: disable=bad-continuation
                    in_module_contents = False

                for sought in found:

                    if line.find(sought) == 0:

                        found[sought]['line_num'] = line_num
                        if found[sought]['contents']:
                            in_module_contents = True

                        discard = True
                        # discard the underlines and a blank line too
                        _ = fptr.next()
                        _ = fptr.next()

                if in_module_contents and not discard:
                    module_contents.append(line)

                elif not discard:
                    reordered.append(line)

                # print '{:<6}|{}'.format(len(line), line)

        with open(new_filename, 'w') as fptr:
            fptr.write('\n'.join(reordered[:3]))
            fptr.write('\n')
            if module_contents:
                fptr.write('\n'.join(module_contents))
                fptr.write('\n')
                if len(module_contents[-1]) > 0:
                    fptr.write('\n')
            if reordered[3:]:
                fptr.write('\n'.join(reordered[3:]))
                fptr.write('\n')


if __name__ == "__main__":
    main()

这就是我一直在寻找的。谢谢! - undefined

4

sphinx-apidoc脚本使用apidoc.py模块。我无法提供详细的说明,但是如果您想要删除标题或以其他方式自定义输出,您将不得不编写自己的此模块版本。没有其他的“模板”。

请注意,如果API和模块结构稳定,就没有必要反复运行sphinx-apidoc。您可以对生成的rst文件进行后处理,使其符合您的喜好,然后将它们放在版本控制下。另请参阅https://dev59.com/0Yfca4cB1Zd3GeqPns75#28481785

更新

从Sphinx 2.2.0开始,sphinx-apidoc支持模板。请参见https://dev59.com/MFUL5IYBdhLWcg3wbnm4#57520238


2
谢谢@mzjn。我有点怀疑它不可能被定制化。在我看来sphinx-apidoc有一些不足之处,就是它没有模板化。你完全正确,一旦包结构稳定下来,我就可以安全地编辑生成的.rst文件。现在还有一些波动,但我将忍受奇怪的外观,直到它稳定下来。在那之后,我可能可以避免未来运行sphinx-apidoc并手动进行任何更新。 - estan
2
从Sphinx 2.2开始,apidoc脚本现在支持模板。 - Michael Goerz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接