在Sphinx文档中保留包装/装饰的Python函数的默认参数


问题内容

如何在修饰函数的文档中替换*args并替换**kwargs为真实签名?

假设我有以下装饰器和装饰函数:

import functools

def mywrapper(func):
    @functools.wraps(func)
    def new_func(*args, **kwargs):
        print('Wrapping Ho!')
        return func(*args, **kwargs)
    return new_func

@mywrapper
def myfunc(foo=42, bar=43):
    """Obscure Addition

    :param foo: bar!
    :param bar: bla bla
    :return: foo + bar

    """
    return foo + bar

因此,致电print(myfunc(3, 4))给我们:

Wrapping Ho!
7

到现在为止还挺好。我还希望我的库包含myfuncSphinx正确记录的文档。但是,如果我通过以下方式在我的狮身人面像html页面中包含函数:

.. automodule:: mymodule
    :members: myfunc

它实际上将显示为:

myfunc( args,* kwargs)

晦涩的加法

  • 参数:
    • foo :吧!
    • 酒吧 :bla bla
  • 返回值: foo + bar

如何摆脱myfunc(*args, **kwargs)标题中的泛型?应该用 myfunc(foo = 42,bar = 43)
代替。如何更改狮身人面像或装饰器mywrapper,以使默认关键字参数保留在文档中?

编辑

如前所述,这个问题曾经被问过,但是答案并没有那么大的帮助。

但是,我有一个主意,想知道这是否可能。Sphinx是否设置一些环境变量来告诉我的模块它实际上是由Sphinx导入的?如果是这样,我可以简单地修补自己的包装器。如果我的模块是由Sphinx导入的,我的包装器将返回原始函数,而不是包装它们。因此,签名被保留。


问题答案:

我想出了一个猴子补丁functools.wraps。因此,我只是将其添加到了conf.py项目文档的sphinxsource文件夹中的脚本中:

# Monkey-patch functools.wraps
import functools

def no_op_wraps(func):
    """Replaces functools.wraps in order to undo wrapping.

    Can be used to preserve the decorated function's signature
    in the documentation generated by Sphinx.

    """
    def wrapper(decorator):
        return func
    return wrapper

functools.wraps = no_op_wraps

因此,当通过构建html页面时make htmlfunctools.wraps此装饰器no_op_wraps将替换它,该装饰器仅返回原始函数就什么也不做。