Документы Sphinx не перечисляют аргументы декорированных функций

Когда я применяю свой собственный декоратор (подробности не важны, но см. ниже) или другие декораторы, такие как cached, из cachetools, мои документы, сгенерированные Sphinx, не отображают имена аргументов в своих подписях.

Например, документация для

@cached()
def some_func(argA, argB=None):
    ...

@require_unicode('third')
def another_func(first, second=None, third=None):
...

будет читать, в общем

some_func(*args, **kwargs)

other_func(*args, **kwargs)

а не информативно, как

some_func (argA, argB = нет)

other_func (первый, второй = нет, третий = нет)

Как я могу исправить это, чтобы имена моих аргументов отображались в моей документации по Sphinx? Я понимаю, что это известная проблема, и, поскольку я знаю имена декораторов, которые использую, я подумал просто сделать их неактивными в моем conf.py, но не могу понять, как это сделать.

Например, что-то вроде это кажется многообещающим, но я не знаю, как заставить его работать. Я могу поставить его перед моим определением выше, но не вижу, как заставить его работать для cached.


Мой декоратор, для справки. Обратите внимание, что, по крайней мере, это генерирует документы (чего не было бы, если бы я не использовал wraps):

from functools import wraps

def require_unicode(*given_arg_names):
    def check_types(_func_):
        @wraps(_func_)
        def modified(*args, **kwargs):
            arg_names = list(_func_.func_code.co_varnames[:_func_.func_code.co_argcount])
            if len(given_arg_names) == 0:
                raise TypeError('No arguments provided to require_unicode decorator.')
                #unicode_arg_names = arg_names
            else:
                unicode_arg_names = given_arg_names
            for unicode_arg_name in unicode_arg_names:
                try:
                    arg_index = arg_names.index(unicode_arg_name)
                    if len(args) > arg_index:
                        arg = args[arg_index]
                    elif unicode_arg_name in kwargs:
                        arg = kwargs[unicode_arg_name]
                    else:
                    if not isinstance(arg, unicode):
                        raise TypeError("Parameter '{}' should be Unicode".format(unicode_arg_name))
                except ValueError:
                    raise NameError(unicode_arg_name)
            return _func_(*args, **kwargs)
        return modified
    return check_types

person orome    schedule 28.11.2015    source источник
comment
Я не думаю, что вы можете это исправить, потому что подпись является общей подписью декоратора. Вы тоже не документируете параметры?   -  person jonrsharpe    schedule 29.11.2015
comment
Что-то вроде это кажется многообещающим, но я не знаю, как заставить его работать. Я могу поставить его перед моим определением выше. но не вижу, как заставить его работать для cached.   -  person orome    schedule 29.11.2015
comment
Вам нужно будет посмотреть, использует ли cached wraps, и там же залатать его.   -  person jonrsharpe    schedule 29.11.2015
comment
@jonrsharpe: Это общее, только если я позволю вещам зайти так далеко. Если я смогу каким-то образом перехватить декораторы, то при генерации документации я смогу исправить проблему (см. предыдущий комментарий).   -  person orome    schedule 29.11.2015
comment
@jonrsharpe: Вот в чем вопрос. Где там?   -  person orome    schedule 29.11.2015
comment
Тогда не могли бы вы отредактировать вопрос, чтобы он говорил об этом?   -  person jonrsharpe    schedule 29.11.2015


Ответы (1)


Глядя на исходный код для cached, он не t используйте functools.wraps, так что ваше текущее исправление обезьяны не будет успешным. Он использует либо functools.update_wrapper, либо свою собственную версию с псевдонимом _update_wrapper, так что вам нужно это исправить. Если вы используете какие-либо другие библиотеки с собственными способами реализации переноса, вам необходимо соответствующим образом изучить каждую из них.

person jonrsharpe    schedule 28.11.2015
comment
Да, только что видел то же самое. Можете ли вы помочь с (а) как должен выглядеть патч для cached и (б) где разместить мой патч для него (чтобы он влиял только на сборки документов). Я могу заставить патч для моего декоратора работать, поместив его перед его определением (и условно выполнив его с флагом, который я установил в conf.py). - person orome; 29.11.2015
comment
@raxacoricofallapatorius, почему бы вам не сделать это, как это делает связанный вопрос, исправив wraps в conf.py, чтобы вам не приходилось позволять этим деталям реализации документации проникать в ваш реальный код? Затем cachetools._update_wrapper можно тривиально исправить, например. lambda wrapper, func: func чтобы отключить упаковку. Или исправьте Sphinx для использования __wrapped__, как предлагает второй ответ. - person jonrsharpe; 29.11.2015
comment
На самом деле, эта часть ответа не работает. Установка патча прямо перед моим определением работает, но установка его в conf.py не имеет никакого эффекта. - person orome; 29.11.2015
comment
Так что мне нужна помощь, чтобы выяснить, куда она идет. Ваше предложение пропатчить Sphinx для использования __wrapped__ также может сработать (может быть, даже лучше, хотя у меня меньше идей, как это реализовать!). - person orome; 29.11.2015
comment
@raxacoricofallapatorius Я думаю, вам нужно потратить больше времени на исследования и работу над этим, чтобы точно сузить свой вопрос. - person jonrsharpe; 29.11.2015