Date: 2014-4-12
Tags: python, sphinx

Sphinxメンテナ日記: autosummaryがattributeコメントを無視する問題(Issue #1444)

前置き: このエントリを読むと、あなたの知らないSphinxの機能を使えるようになるかもしれません。ならないかもしれません。前置きおわり。

autodocとautosummaryとで属性ドキュメントの内容が違う

元ネタ: Issue #1444

autodocとautosummaryはPythonコードから自動的にドキュメントを作る機能で、Sphinxの sphinx.ext.autodocsphinx.ext.autosummary で使い方が紹介されています。

例えば、こういうPythonコードがあるとします。

# -*- coding: utf-8 -*-

class A(object):
    """My Class
    """

    #: This is attribute document
    #:
    #: type of `abc` is integer.
    abc = 1

    def upper_name(self, name):
        """
        upper_name accept name argument and ...

        :param str name: your name
        :return: upper case your name
        :rtype: str
        """
        return name.upper()

コードそのものにあまり意味はありませんが、docstringなどを使って関数やクラス属性にドキュメントが書いてあります。 これをSphinxドキュメントに取り込むために以下のようにreSTを書きます。

Welcome to issue1444's documentation!
=====================================

.. module:: foo

.. autoclass:: A
   :members:


   .. autosummary::

      abc
      upper_name

この中で、 moduleSphinxドメイン が提供するディレクティブです。 autoclasssphinx.ext.autodoc 拡張が提供するディレクティブです。 autosummarysphinx.ext.autodoc 拡張が提供するディレクティブです。

conf.pyでは autosummary_generate = True を忘れないようにします。

# -*- coding: utf-8 -*-

import sys
import os

sys.path.insert(0, os.path.abspath('.'))

extensions = ['sphinx.ext.autodoc', 'sphinx.ext.autosummary']
autosummary_generate = True
master_doc = 'index'

project = u'issue1444'
copyright = u'2014, issue1444'
version = release = 'issue1444'

exclude_patterns = ['_build']

html_theme_options = {
    'collapsiblesidebar': True,
}

これで make html でビルドすると以下のようなHTMLが生成されます。

../../_images/1-autosummary-bug.png

abc の説明がautosummaryでは help(int) の説明になっている。

上記のように、期待とはちょっと違う結果が表示されます。intの説明はいらないので、そのint値の意味をサマリーに表示して欲しいですね。

この問題を修正したあとでは以下のように表示されます。

../../_images/2-autosummary-fix.png

abc の説明がautodocと同じ、 This is a ... という説明になっている。

問題を再現するSphinxプロジェクトは Issue #1444 に添付してある issue1444.zip から入手できます。

問題の原因は?

Pythonは関数のドキュメントをdocstringとして書くことが出来ますが、属性値のドキュメントを書く機能はありません。 そこで、autodocではPythonコードを解析して以下のようにドキュメントを書いたら認識するようになっています。

class Foo:
    """Fooのクラスドキュメント"""

    #: クラス属性Foo.barのドキュメントコメントです。
    #: 複数行書くことが出来ます。
    bar = 1

    flox = 1.5   #: Foo.floxのドキュメントコメントです。この書き方は1行のみ

    baz = 2
    """Foo.baz のdocstringです。"""

    def __init__(self):
        #: インスタンス.qux のドキュメントコメントです。
        self.qux = 3

        self.spam = 4
        """インスタンス.spam のdocstringです。"""

Python標準の機能では """Fooのクラスドキュメント""" 以外は認識されないため、autodocでがんばって解析しているわけですが、autosummaryの方では「がんばって解析する」部分が省略されていました。

どうやって対策したの?

autodocの実装と同じ機能を呼び出すように実装を追加しました。 差分は https://bitbucket.org/birkenfeld/sphinx/commits/7029194ff9b9 にありますが、 実装にかかった時間より、テストコードで動作を担保するほうが時間がかかりました。

まとめ

このバグ修正はSphinx-1.2.3に含まれる予定です。