【问题标题】:Is sphinxcontrib-autoprogram parsing arguments after grabbing the parser?抓取解析器后,sphinxcontrib-autoprogram 是否解析参数?
【发布时间】:2020-06-25 17:38:10
【问题描述】:

我正在创建一个带有命令行界面的 Python 包,该命令行界面使用子命令模式:kevlar countkevlar partition 等等。 CLI 运行良好,现在我正尝试将 CLI 添加到我的 Sphinx 文档中。在寻找解决方案时,我遇到了sphinxcontrib-autoprogram,它似乎完全符合我的要求,甚至明确处理子命令。但是当我执行 sphinx 构建时,出现以下错误。

sphinx-build -b html -d _build/doctrees   . _build/html
Running Sphinx v1.6.3
loading pickled environment... not yet created
building [mo]: targets for 0 po files that are out of date
building [html]: targets for 5 source files that are out of date
updating environment: 5 added, 0 changed, 0 removed
reading sources... [ 20%] cli
usage: sphinx-build [-h] [-v] [-l F] cmd ...
sphinx-build: error: argument cmd: invalid choice: 'html' (choose from 'reaugment', 'dump', 'novel', 'collect', 'mutate', 'assemble', 'filter', 'partition', 'count', 'localize')
make[1]: *** [html] Error 2
make: *** [doc] Error 2

似乎 sphinx 扩展不仅在创建 argparse 对象(预期),而且还在其上调用parse_args()(意外)。 “无效”html 参数来自 sphinx 命令行构建调用,但在某处被误认为是我的库 CLI 中的子命令之一。

我的语法似乎与 sphinxcontrib-autoprogram 文档相匹配。

.. autoprogram:: cli:parser
   :prog: kevlar

什么可能导致这种行为?


我不确定这些细节是否与问题相关,但如果它们是:

【问题讨论】:

标签: python python-sphinx argparse


【解决方案1】:

您应该将argparse 实例加载到一个单独的模块中,该模块创建相同的argparse 实例但不执行解析器本身。或者您的模块可以检测到它已在自动程序中加载并在构造 argparse 实例后退出。

例如,PoC-Library 使用一个非常庞大的argparse 命令行解析器,其中包含许多子解析器。前端脚本是这样的:py/PoC.py

docs 目录包含一个虚拟前端,它会触发 argparse 的实例化,但在构造完成后会中止。

虚拟加载 PoC 的代码:

from sys import path as sys_path
sys_path.append("../py")

from PoC import PileOfCores

# entry point
parser = PileOfCores(False, False, False, True, sphinx=True).MainParser

来源:docs/PoCSphinx.py

Sphinx 加载和中止的代码:

def __init__(self, debug, verbose, quiet, dryRun, sphinx=False):
    # Call the initializer of ILogable
    # --------------------------------------------------------------------------
    if quiet:      severity = Severity.Quiet
    elif debug:    severity = Severity.Debug
    elif verbose:  severity = Severity.Verbose
    else:          severity = Severity.Normal

    logger = Logger(severity, printToStdOut=True)
    ILogable.__init__(self, logger=logger)

    # Call the constructor of the ArgParseMixin
    # --------------------------------------------------------------------------
    description = dedent("""\
        This is the PoC-Library Service Tool.
        """)
    epilog = "Pile-of-Cores"

    class HelpFormatter(RawDescriptionHelpFormatter):
        def __init__(self, *args, **kwargs):
            kwargs['max_help_position'] = 25
            super().__init__(*args, **kwargs)

    ArgParseMixin.__init__(self, description=description, epilog=epilog, formatter_class=HelpFormatter, add_help=False)
    if sphinx: return

来源:py/PoC.py

PileOfCores 类实现了一个属性来返回主解析器对象MainParser,该对象存储在autoprogram 预期的变量parser 中。

【讨论】:

    【解决方案2】:

    首先,确保您的程序使用argparse,这是autoprogram 的要求:

    扫描argparse.ArgumentParser 对象,然后将其扩展为一组.. program::.. option:: 指令。

    其次,您使用的语法可能不正确。看起来您从第一个示例中复制粘贴而不是阅读其usage。具体来说:

    .. autoprogram:: module:parser
    

    module 是模块的点分导入名称,parser 是一个变量,它引用 argparse.ArgumentParser 对象或创建并返回一个对象的 Python 表达式。

    因此,在您的情况下,假设您的 parser() 创建并返回 argparse.ArgumentParser,您的语法将类似于或接近于它:

    .. autoprogram:: kevlar.cli:parser()
        :prog: kevlar
    

    困难的部分是找出准确、正确的 module:parser 替换。

    要与另一个示例进行比较,请参阅 pcreate 的 Pyramid 文档的 source program、来源 reST filerendered HTML

    【讨论】:

    • “困难的部分是找出准确、正确的 module:parser 替换。”嗯,错误消息清楚地表明正在调用正确的函数。问题是ArgumentParser 对象似乎是执行而不是检查
    猜你喜欢
    • 1970-01-01
    • 2016-01-10
    • 1970-01-01
    • 1970-01-01
    • 2015-07-25
    • 2018-10-27
    • 1970-01-01
    • 2021-02-28
    • 1970-01-01
    相关资源
    最近更新 更多