はじめに
以前の投稿で、1コマンドでsphinx-apidocとsphinxを両方実行する方法について記載しました。しかしながら、この方法はsphinx自体ではなく、setuptoolsの挙動を変更する方法であったため、setuptoolsを噛まさず直接sphinxを実行するRead the Docsなどのサービスとうまく連携できないという問題がありました。本投稿では、sphinx側の実行に直接sphinx-apidocを組みこむ方法について記載します。
手順
ディレクトリ構造などは前回の投稿に準拠します。
まず、Sphinxの実行にsphinx-apidocを組み込みます。
import sphinx.apidoc
root_dir = os.path.abspath('../..')
try:
# This succeeds = the project is already installed.
# This directive avoids Readthedocs to fail
import my_project
except ImportError:
sys.path.insert(0, root_dir)
import my_project
# ...
# Rest of the conf.py
# ...
def run_apidoc(_):
script_dir = os.path.dirname(os.path.realpath(__file__))
src_dir = os.path.join(script_dir, root_dir)
out_dir = os.path.join(script_dir, "modules")
sphinx.apidoc.main(
['', '-f', '-H', project, '-A', author,
'-V', version, '-R', release, '-T', '-M',
'-o', out_dir, src_dir])
def setup(app):
app.connect('builder-inited', run_apidoc)
ポイントは2つあります:
-
import my_project
をこころみ、失敗したらプロジェクトのrootにパスを通して再度インポートを試みます。Read the Docsは一度ライブラリをビルドして、ローカルの環境にインストールしてからドキュメントをビルドするからです1。
2.setup
コマンドを定義することで、Sphinx実行時にsphinx-apidocの実行をhookします。
前回の投稿のようにsetup.pyにsphinx-apidocを組み込んでしまっている場合には元の状態に戻します。その上で下記のようにsetup.py
まわりを修正します。
cmdclass = {}
# こうしないとライブラリを利用者としてインストールするためだけにSphinxが必要になる
try:
from sphinx.setup_command import BuildDoc
cmdclass['build_sphinx'] = BuildDoc
except ImportError:
pass
# ...
# Rest of the setup.py
# ...
setup(
...
cmdclass=cmdclass
)
[build_sphinx]
source-dir = doc/source
build-dir = doc/build
all_files = 1
最後にRead the Docs側を設定します。
以上の手順をふむことで python setup.py build_sphinx
で開発環境でドキュメンテーションのビルドができ、かつRead the Docsからも同じようにビルドできる環境が出来上がります。
-
これはRead the Docsのオプションであり、初期設定の挙動ではありません。しかし、setuptools側で依存ライブラリを定義してあるのであれば、別途Read the Docs用に
requirements.txt
を作ったりするよりスマートだと思います。 ↩