Подтвердить что ты не робот

Как использовать Sphinx с Cython?

Недавно я написал Cythonized проект my, переименовав все модули (за исключением верхнего уровня __init__.py) на *.pyx и положив ext_modules = [Extension('foo', ['foo.pyx'])] в setup.py. Строительно-монтажные работы отлично. Однако, когда я делаю cd doc; make html, Sphinx терпит неудачу, потому что он не может импортировать ни один из модулей, которые теперь *.pyx.

Если я отредактировал doc/conf.py и изменил sys.path.insert(0, os.path.abspath('..')) на sys.path.insert(0, os.path.abspath('../build/temp.linux-x86_64-2.7')), тогда Sphinx может найти все модули и может генерировать документацию, но в этом случае я получаю ошибки, такие как error while formatting arguments for foo.bar: <built-in function bar> is not a Python function. Предположительно это происходит потому, что теперь Sphinx имеет доступ только к файлам *.so, а не к исходным файлам. Эта же модификация sys.path также позволяет запускать доктрины через Sphinx (make doctest).

Другим решением, которое я пробовал, было использование расширения *.py вместо *.pyx (и использование ext_modules = [Extension('foo', ['foo.py'])] в setup.py). В этом случае документация строит правильно, но я думаю, что доктрины теперь обойти Cython.

Я не смог найти какую-либо информацию в Интернете относительно совместного использования Sphinx и Cython. Я рассмотрел исходный код для некоторых проектов, которые используют оба варианта, но они, похоже, не используют docstrings в файлах *.pyx. Я знаю, что Sage делает, но этот проект слишком сложный для меня, чтобы разобрать.

Поддерживает ли Sphinx docstrings в файлах Cython? Если да, то как это сделать?

4b9b3361

Ответ 1

Не стесняйтесь оставлять лучший ответ, но вот исправление, которое я нашел.

Проект dipy вручную импортирует свой собственный модуль из doc/conf.py. Это требует, чтобы модуль был сначала установлен, но он исправляет ошибки импорта (и доктрины будут выполняться на Cythonized файлах).

Однако проблема error while formatting arguments все еще существует. Сначала вам нужно поручить Cython встроить сигнатуры метода/функции в файлы *.so. Сделайте это, установив директиву embedsignature Cython. Проект dipy устанавливает это в каждом файле *.pyx, но его также можно установить в setup.py (см. Документацию Cython о том, как это сделать). Это все еще не помещает сигнатуры метода в документацию Sphinx! Существует отчет об ошибке и патч для проблемы сигнатур метода здесь. Он до сих пор не включен в последнюю версию Sphinx (1.1.3), но если вы установите Sphinx из репозитория разработки, он будет работать.

Ответ 2

Ты выглядишь немного странно. Sphinx на самом деле не синтаксический анализатор. Ваш код Python должен быть запущен, чтобы Sphinx смог поймать docstrings. Вот почему переименование файлов расширений на ".py" не помогает.

Хорошо, я недавно работал с Sphinx и Cython и хотел бы поделиться своим опытом... Вот полная подробная процедура для получения автоматизированной генерации html-документации для данного скомпилированного расширения Cython из docstrings:

[Примечание: я использовал Sphinx 1.1.3 и Cython 0.17.4]

Прежде всего, используйте "docstrings" Python (со всеми ограничениями, которые он может иметь), например, вы не можете описать конструктор. См. docstrings) в вашем Cython-коде:

cdef class PyLabNode:
    """
    This is a LabNode !!!
    """
    cdef LabNode* thisptr
    cdef PyLabNetwork network

    def __cinit__(self):
       self.thisptr = new LabNode()

    def __dealloc__(self):
       if self.thisptr:
           del self.thisptr

    def SetNetwork(self, PyLabNetwork net):
        """
        Set the network !!!
        """
        self.network = net

И перекомпилируйте "yourextension.so".

Затем запустите "sphinx-quickstart" и ответьте на вопросы. Не забудьте сказать "да", когда его попросят "autodoc". Это создаст файл "Makefile", "index.rst" и "conf.py".

Этот последний "conf.py" должен быть отредактирован, чтобы сообщить, что Sphinx должен найти ваш модуль:

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
sys.path.insert(0, os.path.abspath('../../parent/dir/of/yourextension/'))

Файл index.rst также должен быть отредактирован, чтобы определить, какой модуль может быть проанализирован:

Contents:

.. toctree::
   :maxdepth: 2


.. automodule:: yourextension
   :members:
   :undoc-members:
   :show-inheritance:

Наконец, создайте документацию, выполнив:

$ make html

Этого было достаточно для меня (я получил результирующий набор html файлов в каталоге ".../_ build/html/" ). Может быть, Сфинкс и Китон развились после того, как был задан предыдущий вопрос, но у меня не было проблем с "сигнатурой". Никакой конкретной директивы Cython для использования или каких-либо исправлений для применения к Sphinx...

Надеюсь, что это поможет.

РЕДАКТОР: Хорошо, я хотел бы вернуть слова. Я столкнулся с проблемой, которую "Дэн" упоминал в отношении вопроса "embedsignature" при использовании Epydoc (так что я полагаю, что это проблема и для Sphinx). Активация этой директивы компилятора в любом случае не отправляет сигнатуры, совместимые с python:

PyLabNode.SetNetwork(self, PyLabNetwork net)

У этого есть 2 недостатка: пунктирная нотация для префикса класса и типизированного параметра.

В конце концов, единственный способ, по которому я мог найти правильные, - написать совместимую подпись в самой первой строке строк документа так:

def SetNetwork(self, PyLabNetwork net):
    """
    SetNetwork(self, net)
    Set the net !!!
    @param self: Handler to this.
    @type self: L{PyLabNode}
    @param net: The network this node belongs to.
    @type net: L{PyLabNetwork}
    """
    self.network = net

Надеюсь, это поможет как пользователям Sphinx, так и Epydoc...


EDIT: Что касается __cinit__, я смог успешно сгенерировать документ с помощью Epidoc (не пытался с Sphinx), удвоив описание, например:

# For Epydoc only (only used for docstring)
def __init__(self, sim):
    """
    __init__(self, sim)
    Constructor.
    @param sim: The simulator this binding is attached to.
    @type sim: L{PyLabSimulatorBase} 
    """ 

# Real Cython init
def __cinit__(self, PyLabSimulatorBase sim):
   self.thisptr = new LabNetBinding()
   self.sites = []
   simulator = sim

Ответ 3

Как объясняет Голгаут, модуль autodoc Sphinx берет docstrings из .so, а не .pyx. Простейший способ генерации вашей документации без необходимости внесения каких-либо изменений в конфигурацию Sphinx при использовании cythonizing модуля Python заключается в простой сборке модулей расширения на месте перед созданием документов:

python setup.py build_ext --inplace

Таким образом, autodoc найдет модули расширения вместе с регулярными модулями Python и сможет генерировать документацию, как и следовало ожидать.

Чтобы не забыть этот шаг, вы можете отредактировать Makefile, сгенерированный sphinx-quickstart, для сборки модулей расширения до запуска sphinx-build:

html:
  @cd /path/to/setup.py; python setup.py build_ext --inplace
  ...