[python] sphinxでドキュメント生成

# はじめに
sphinxとはpython製のオートドキュメンテーションツールである。
知的で美しいドキュメントを簡単に作れるらしい。(公式談)
今回初めてsphinxを使って文書を作成してみたので、インストールからビルドまでの流れを簡単にまとめておく。

# 環境
|OS|Python Ver|
|---|---|
|Windows10|3.10.5|

# sphinxパッケージのインストール
仮想環境を立ち上げて、環境内にインストールした。

```
(.venv) pip install sphinx
```
これで、最低限としてsphinxパッケージのインストールはOK
Read the Docsのテーマが使いたいなら追加で`sphinx-rtd-theme`を、バージョンごとのドキュメントを作りたい場合は`sphinx-multiversion`をそれぞれ適宜インストールする。
```
(.venv) pip install sphinx-rtd-theme sphinx-multiversion
```

# sphinxプロジェクト作成
現在、ディレクトリ構成は以下のようになっている。
```
for_sphinx_test(root)/
 ┣━.venv/
 ┣━ requirements.txt
 ┗━ pkg/
     ┣━ __pycache__/
     ┣━ test.py
     ┣━ __init__.py
     ┗━ __main__.py  

```
root下に`docs`という名前でsphinx用プロジェクトを作成している人が多い様なので、自分もそれに倣って下記コマンドを打ち`docs`内にsphinxプロジェクトを作成した。
```
(root) sphinx-quickstart docs
```

:::note info
`docs`内にSphinx関係のファイルを作れば削除する際などに比較的楽である
:::

sphinx-quickstartしたときに、色々質問されると思う。
```
Sphinx 出力用のビルドディレクトリを配置する方法は2つあります。
ルートパス内にある "_build" ディレクトリを使うか、
ルートパス内に "source" と "build" ディレクトリを分ける方法です。
> ソースディレクトリとビルドディレクトリを分ける（y / n） [n]: y
```
`sourece`と`build`がごちゃごちゃするのが嫌なので自分はYを選択して、分けるようにしている。

他の質問としてプロジェクト名やauthorなど聞かれると思うがミスしたとしても、後で`conf.py`で設定し直せるので気楽に答えていけばよい。

sphinxプロジェクトを立ち上げた後のディレクトリ構成は以下のようになる。
```
for_sphinx_test(root)/
 ┣━ .venv/
 ┣━ requirements.txt
 ┣━ pkg/
 ┃   ┣━ __pycache__/
 ┃   ┣━ test.py
 ┃   ┣━ __init__.py
 ┃   ┗━ __main__.py  
 ┗━ docs/
      ┣━ build/
      ┣━ source/
      ┃     ┣━ _static/
      ┃     ┣━ _templates/
      ┃     ┣━ conf.py
      ┃     ┗━ index.rst
      ┣━ make.bat
      ┗━ makefile
```
`quick-start`後に生成されるファイルやディレクトリの用途としては以下の通り。
|ディレクトリ名/ファイル名|用途|
|---|---|
|build|ビルド後に生成されるhtml等のドキュメントソース置き場|
|_static|cssやJavaScript置き場|
|_templates|テンプレートを上書きするファイルなどを置く|
|conf.py|設定ファイル|
|index.rst|ドキュメントの起点になるファイル|
|make.bat|(Windows環境)ビルドを行うスクリプトが書かれたバッチファイル|
|Makefile|(Linux環境)ビルドを行うスクリプトが書かれたファイル|

:::note info
ちなみに、`sphinx-quickstart`したときの質問で、`build`と`source`を分けなかった場合、`source`ディレクトリは生成されず、中のディレクトリとファイルが`build`と同じ階層に置かれることになる。
:::

## conf.pyの設定
初めてビルドする際には、`docs`配下の`conf.py`を少しいじらなければいけない。
いじる内容は主に3つ(うち1個は任意)

(1) **パッケージディレクトリへのパス設定**
ドキュメント化したいパッケージのパスを設定する必要がある。
今回はpkgのトップ階層がそれにあたる。パスはconf.pyとの相対で取るので下のようにコードを加えればよい
```python:conf.py
import os
import sys
sys.path.insert(0, os.path.abspath('../..'))
```

(2) **extensionsの設定**
初期状態ではextensionsは空リストになっていると思うがオートドキュメントのために、下の拡張を加える必要がある。
sphinxライブラリに標準で入っているので追加インストールは不要
```python:conf.py
extensions = [
    'sphinx.ext.autodoc',  # ソースコード読み込み用
    'sphinx.ext.viewcode',  # ハイライト済みのソースコードへのリンクを追加
    'sphinx.ext.todo',  # ToDoアイテムのサポート
    'sphinx.ext.napoleon' #googleスタイルやNumpyスタイルでdocstringを記述した際に必要
]
```

(3) **htmlテーマの変更(任意)**
初期では`alabaster`が設定されているはず。
自分は`sphinx_rtd_theme`の方がイケていると思ったのでこちらに変更した。
```python:conf.py
html_theme = 'sphinx_rtd_theme'
```

他にも、quick-startで設定を間違えたり、Ver情報を更新したい時などは`conf.py`を変更すれば反映される。

# rstファイルの作成
パッケージのパスを指定して、htmlファイルのソースとなるrstファイルを作成していく。
```
sphinx-apidoc [OPTIONS] -o <OUTPUT_PATH> <MODULE_PATH>
```
公式サイトでは、このような指定がある。
OUTPUT_PATHにはsourceのディレクトリを指せばよいので、rootにいた場合は次のようになる
```
(root) sphinx-apidoc -f -o docs/source pkg
```
これでモジュール毎のrstと`modules.rst`というファイルが生成されたと思う。
(-f:上書き, -o:ディレクトリがなかったら作成する)

# index.rstへの登録
index.rstはhtmlのトップページとして使用される。
ここにapidocで出力されたmodulesを参照させることで、htmlドキュメントが追加される仕組みのようだ。

```rst:index.rst

===========================================

.. toctree::
   :maxdepth: 2
   :caption: Contents:

   modules #これを追加

Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

```

# htmlファイルのビルド
最後にrstをhtmlへビルドする。
docsのディレクトリへ移動し、makeコマンドをたたく。
```
make html
```

または、
```
sphinx-build -b html ./source ./build
```
これで、buildディレクトリにhtmlファイルが自動生成される。
ちなみに、html以外も`make help`と打つことで、作成可能なファイル形式の一覧が表示される。

build内の`index.html`をブラウザで表示させると生成されたものが表示される。

開くとこんな感じで、階層構造で表示される。
![キャプチャ_1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/836555/2d4d0373-4343-367e-78a5-c5359d7b8a44.png)

もちろんコードの中身も見ることができる。
自動でこれが生成されるのは非常に便利

![キャプチャ_2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/836555/d113188a-5092-c508-5ab8-e1a78221df23.png)

# さいごに
参考にさせていただいたサイト様には感謝いたします。

今回はsphinxを仮想環境下にインストールしたが、パッケージ毎にこれをやってしまうと、それぞれの`requirements.txt`が冗長になってしまうなぁ。。と思った。

解決策としては、

(1) base環境下にsphinxを入れてしまう。(あまりやりたくない)
(2) 各パッケージをドキュメント化させるパッケージを作って集約させる。

といった感じか...(ジャストアイデアだが。)

ここら辺は今後の課題として考えどころである。


# 参考サイト

[Sphinx documentation](https://www.sphinx-doc.org/ja/master/)
[Sphinx-apidoc](https://www.sphinx-doc.org/ja/master/man/sphinx-apidoc.html)
[reSTを書かずにautodocだけでSphinxする](https://qiita.com/satamame/items/65abd04e74b341ed1e80)
[Sphinxを使って自作パッケージのドキュメントを簡単に更新しよう！！](https://qiita.com/hanama_chem/items/a9ecc941acdda4bcc2c7)