pdoc3で超お手軽にPythonコードのドキュメントを生成しよう

Pythonのドキュメンテーションシステムといえば[sphinx](https://www.sphinx-doc.org/ja/master/)が有名ですが、もっとお手軽にできてしまう[pdoc3](https://pdoc3.github.io/pdoc/)を紹介してみます。

※本記事の情報は2020年11月30日、pdoc3 `v0.9.2`時点の情報になります。

## TL;DR

* `pdoc3`で設定なしでお手軽ドキュメンテーション生成！
* こんな感じの美しいサイトを生成できるよ
    * https://yukinarit.github.io/pyserde/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44173/ec2dbd90-c4a0-f3c6-c2c8-95d90ec92c04.png)


## `pdoc3`

* Webサイト: https://pdoc3.github.io/pdoc/
* APIドキュメント: https://pdoc3.github.io/pdoc/doc/pdoc/ 
* PyPI: https://pypi.org/project/pdoc3/
* Github: https://github.com/pdoc3/pdoc/

## 特徴・機能一覧

* 設定なしでも簡単に動く
* docstring(Markdown, numpydoc, Google-style)、LaTex math、reSTをサポート
    * 例えばreSTの`include`で別のMarkdownをインクルードできたりする
* [PEP484](https://www.python.org/dev/peps/pep-0484/)や[PEP526](https://www.python.org/dev/peps/pep-0526/)といったクラスや変数に対する型宣言を表示してくれる
* サイト内Google検索の設置
* デザインテンプレートのカスタマイズ
* [Lunr](https://lunrjs.com/)による全文検索
* ビルトインのHTTPサーバー

## Sphinxとの違い

SphinxはPythonソースコードからのAPIドキュメンテーション生成だけでなく、reSTやMarkdownからのドキュメンテーション生成もサポートしている。

一方、`pdoc3`はソースコードからのAPIドキュメンテーション生成だけしかできない。もし、Markdown等から生成したい場合は、[MkDocs](https://www.mkdocs.org/)、[GitBook](https://www.gitbook.com/)や[mdBook](https://rust-lang.github.io/mdBook/)をセットで使いましょう。筆者はRustaceanなので、mdBookを愛用しています。

## 使い方

前置きが長くなりましたが、早速使ってみましょう。

```
pip install pdoc3
```

`--html`でHTM形式で出力（デフォルトではMarkdown, `--pdf`でMarkdown-PDF変換用のMarkdown形式になる)

```
pdoc <Module名> --html -o <出力ディレクトリ>
```

`--force`で強制上書き

```
pdoc <Module名> --html -o <出力ディレクトリ> --force
```

HTTP用サーバーを立ち上げる

```
pdoc <Module名> --html -o <出力ディレクトリ> --force --http <IPアドレス:Port>
```

## こんな感じで出来上がります

* pdoc3本家のdocs: https://pdoc3.github.io/pdoc/doc/pdoc/
* 筆者のライブラリのdocs: https://yukinarit.github.io/pyserde/

## Tips

### ドキュメントにCIのバッジ付ける

`README.md`にはCIのバッジとか付けていたら、ルートの\_\_init\_\_.pyで`.. include:: ../README.md`するとドキュメントにも表示することができる

```python
"""
.. include:: ../README.md
"""
from .core import SerdeError, init, logger, typecheck  # noqa
from .de import deserialize, from_dict, from_obj, from_tuple, is_deserializable  # noqa
from .se import asdict, astuple, is_serializable, serialize  # noqa
```

### グローバル変数のドキュメント

変数の下にコメントを付けましょう。下である必要があります。

```python
FOO_VAR = xxx
""" This is VAR of FOO"""
```

### ドキュメント化したくない場合

* モジュール内に[\_\_all\_\_](https://techacademy.jp/magazine/41656)変数を作り、そこにドキュメント化したい変数だけ列挙する

```python
__all__ = [
    'serialize',
    'deserialize',
]
```

* `__all__`を作りたくない場合は、pdoc3が提供する`__pdoc__`変数でも制御可能。詳しくは[こちら](https://pdoc3.github.io/pdoc/doc/pdoc/#overriding-docstrings-with-__pdoc__)

### ドキュメント内にGoogle検索バーを追加する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44173/a61bce95-ea59-f5ad-e306-2977d93ab6a1.png" width="40%" />

`config.mako`に以下の変数を作り、検索クエリを指定する。クエリに使えるシンタックスは[こちら](https://promonista.com/howto-google-search/)を参照

```
google_search_query = 'inurl:github.com/USER/PROJECT site:PROJECT.github.io site:PROJECT.website'
```

`pdoc`コマンド実行時に`--template-dir`で`config.mako`のあるディレクトリを指定してやれば良い

```
pdoc <Module名> --html -o <出力ディレクトリ> --force --template-dir <config.makoのあるディレクトリ>
```

### Github Actionsでドキュメントをgithub.ioにアップロードする

[github-pages-deploy-action](https://github.com/JamesIves/github-pages-deploy-action)を使えば簡単にアップロードできる。

例として[筆者のプロジェクト](https://github.com/yukinarit/pyserde/blob/62742d4ad4f60023c70cbe1a7108762a92181bac/.github/workflows/build.yml#L31-L58)では、以下のようなActionを実行している。参考にされたし。
* PR番号を取得
* ドキュメントのビルド
* コミットメッセージにPR番号をいれる
* `gh-pages`ブランチにプッシュ

## まとめ

`pdoc3`を使えば超簡単にドキュメントを生成、公開できるのでみんなもやってみよう。