SphinxでのAPIドキュメント作成 まとめ
作業環境
環境構築
Sphinxのインストール
pip install sphinx
ドキュメント出力対象のプロジェクトと最終的なSphinxプロジェクト
https://drive.google.com/file/d/0B4fmLEFqtND0MGZRMWh2TlNNTlE/view?usp=sharing
PromotedTest
PromotedTest │ ButtonWrapper.py │ MainWindow.py │ ui_PromotedTest.py │ ViewWrapper.py │ WrapperBase.py │ __init__.py │ └─ui ui2py.py ui_PromotedTest.ui
ソースへdocstringの記述
記述位置
大体こんな感じ
# -*- coding:utf-8 -*- """ Module no docstring """ import os import sys class Hogehoge(object): """ Class no docstring """ def __init__(self, a, b): """ Method no docstring """ pass def huga(self, i, j): """ Method no docstring """ pass
変数については
とか
でググれば出る
Methodのdocstring書式
PyCharmの場合docstringで補完とかしてくれるのでドキュメントを出さないにしても書いておくと楽
引数の説明等々は以下の通り
def huga(self, a, b): """ 説明 :type a: 引数の型 :type b: 引数の型 :param a: 引数の説明 :param b: 引数の説明 :rtype: 戻り値の型 """ pass @property def value(self): """ 説明 :getter: getterの説明 :type: 戻り値の型 """ pass
setterは知らん
PyCharmのdocstringショートカット
def huga(self, a, b): pass
という形の関数があった場合に関数名・引数のそれぞれの変数部分でAlt+Enter押すと
何種類かのdocstringを挿入する項目が表示される
- Insert documentation string stub
- docstringのテンプレを追加
- Specify return type in docstring
- 関数の戻り値の型の記述を追加
- Specify type for reference in docstring
- 引数の型の記述を追加
このショートカットで上記の形式のdocstringになっていない場合には
Setting > Tools > Python Integrated Tools > docstring
の設定を reStructuredText に変更する必要がある
Sphinxでの作業
Sphinxではrstファイルを使用してhtmlなどのファイルを出力する
そのために、まずはSphinxのプロジェクト・rstファイルの作成をする必要がある
基本的にプロジェクトを作成するには
sphinx-quickstart
のコマンドを使用するが、
apiドキュメント用のプロジェクト作成コマンド
sphinx-apidoc
があったのでそれを使用する
プロジェクトの作成
コマンドラインから
sphinx-apidoc -F -f -o [OUTPUT] [PATH]
- -F
- フルサイズのSphinxプロジェクトの生成
- -f
- 強制的に上書き
- -o [OUTPUT]
- プロジェクト出力先の指定
- [PATH]
コマンド実行後、出力されたSphinxプロジェクトに移動して
make html
と実行するとhtmlファイルが生成される...はずだが、このままではパス諸々の設定が
正しくない場合があるので
conf.py
を編集して設定を変更する
conf.pyの編集
Sphinxプロジェクトから対象プログラムへのパスを通す
conf.pyの割と最初のほうにある
import os import sys sys.path.insert(0, os.path.abspath('.'))
のコメントアウトを外して
os.path.abspath('.')
の部分に対象となる
プログラムが読み込めるようなパスを指定する
ここに指定するパスはconf.pyの存在するディレクトリから見たパスなので
_DATA ├─SphinxProject └─TargetPackage
このように対象となるプログラムがSphinxプロジェクトのディレクトリと同階層にあった場合には
sys.path.insert(0, os.path.abspath('..'))
といった指定にする
―――
ここまで設定した後に
make html
を実行するとhtmlが出力される
.
.
.
.
...で、出力されたのがコレ
どこから飛んでもこのページ...クッソ見づらい...見づらくない??
そもそもSphinxでのドキュメント出力を勉強しようと思った切っ掛けが、
仕事でバカでかいパッケージの修正(ドキュメントなし)案件が来たので
- 開発用にprivateも含めたすべてのMethodが見たい
- Method・Attributeの一覧が見たい
- クラスの一覧→1クラス1ページでなんかよくあるドキュメントっぽくしたい
といったことがしたかった。
というわけで上記を実現するための処理を追加していく。
privateを含めたMethodの表示
conf.pyに autodoc_default_flags を追加して private-members を設定
autodoc_default_flags = [ 'members', 'private-members' ]
この設定はSphinxの拡張であるautodocに対してのデフォルトを設定する
ここに
special-members
と追加することで__init__等の特殊関数の表示もできる
autodocはrstファイルに書かれてる
- automodule
- autoclass
- automethod
とかそのへんのやつ
クラスの一覧→1クラス1ページで表示
Moduleごとにrstファイルの生成
クラスの一覧→1クラス1ページを実現するためにはまずモジュールごとの
rstファイルを作成する必要がある
そのために sphinx-apidoc 実行時にオプションを追加する
コマンドラインから
sphinx-apidoc -F -f -e -o [OUTPUT] [PATH]
- -e
- Moduleごとにrstファイルを生成
としてコマンドを実行
これでモジュールごとにrstファイルが生成される
一覧表示とクラス別ページの生成
モジュールごとに生成されたrstファイルに
autosummary
のディレクティブを追加することで
一覧表示とクラス別ページを同時に実現できる
conf.pyの修正
autosummaryはSphinxの拡張なので使用することを明示する必要がある
conf.pyの extensions に sphinx.ext.autosummary を追加する
extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.autosummary', 'sphinx.ext.todo', 'sphinx.ext.viewcode', ]
また、
autosummary_generate = True
という記述も追加しておく必要がある
これがないとモジュール別→クラス別のページとして作成されない
モジュールごとのrstファイルの修正
モジュールごとに
PromotedTest.ButtonWrapper module ================================= .. automodule:: PromotedTest.ButtonWrapper :members: :undoc-members: :show-inheritance:
上記のような内容のrstファイルが生成されるので
PromotedTest.ButtonWrapper module ================================= .. automodule:: PromotedTest.ButtonWrapper :members: :undoc-members: :show-inheritance: .. autosummary:: :toctree: _gen ButtonWrapper
というように追加
この場合の
.. autosummary:: :toctree: _gen ButtonWrapper
ButtonWraperは
クラス名
なので注意
1Moduleに複数のクラスがある場合は表示させたいクラス名を全て記述する必要がある
:toctree: _gen
は(autosummary_generate = Trueの場合に)_genディレクトリに
rstファイル出力しますよ的なアレ
で、rstが生成されていないと別ページにならない
―――
ここまで設定した後に
make html
を実行するとhtmlが出力される
.
.
.
.
...で、出力されたのがコレ
出来た!!
.
.
.
.
...ただし親クラスのpublic、テメーはダメだ!!
この状態だとクラス別のページで親クラスのpublicも一覧に表示されてしまい、非常に見づらい。
というわけで、消す。
autosummaryの一覧から親クラスのpublicの表示を消す
恐らく他の方法がある
自分が調べる限り、conf.pyやディレクティブでなんやかんやできるという情報は見つからなかった。
ので、ソースとautosummaryのclassのtemplateを修正する。
修正するのは
の2つ
generate.pyのget_membersを以下のように修正
def get_members(obj, typ, include_public=[], no_inherited=True): items = [] for name in dir(obj): try: documenter = get_documenter(safe_getattr(obj, name), obj) except AttributeError: continue if documenter.objtype == typ: items.append(name) if no_inherited: import inspect items = set(items) for cls in inspect.getmro(obj)[1:]: items = items - set(dir(cls)) items = list(items) public = [x for x in items if x in include_public] return public, items
inspectでなんやかんやしてitemsから親クラスのmemberを削除している
また、クラス別ページのMethod一覧内にprivateも含めたかったので最後の内包表記ではじいていた処理を削除
class.rstは以下のように修正
{{ fullname }} {{ underline }} .. currentmodule:: {{ module }} .. autoclass:: {{ objname }} :show-inheritance: {% block methods %} .. automethod:: __init__ {% if all_methods %} .. rubric:: Methods .. autosummary:: {% for item in all_methods %} ~{{ name }}.{{ item }} {%- endfor %} {% endif %} {% endblock %} {% block attributes %} {% if all_attributes %} .. rubric:: Attributes .. autosummary:: {% for item in all_attributes %} ~{{ name }}.{{ item }} {%- endfor %} {% endif %} {% endblock %}
修正箇所は
- autoclassの下に:show-inheritance:を追加
- methodsをall_methodsに変更
- attributesをall_attributesに変更
の3箇所
:show-inheritance:の追加は親クラスのMember一覧については別ページで表示するため
methods・attributesを修正したのは上記のget_membersの修正によりmethod名・attribute名が
all~に入るようになったため
get_membersの変更を正しく行えばmethods・attributesからall~の変更は不要
また、autosummaryのtemplateの修正については別ファイルで行い、autosummaryディレクティブに
:template:
のフラグを追加するべきなのだろうが、今回は力尽きたのでこれで良しとした
―――
ここまで設定した後に(略)
.
.
.
.
...で、出力されたのがコレ
完成!! 第三部完!!
―――
(追記:10/1)
その他・気になったところ
- クラス別ページの出力はされているのに、クラス一覧→クラス別ページに飛ばないことがあった。
- automoduleディレクティブに:noindex:を追加することで解決
参考・気になったところとかは気が向いたら追加