Sphinxは非常に便利なのですが、ドキュメント作成の手順が非常に煩雑でした。
そこで、Sphinxを拡張するモジュール「sphinx-quickstart-plus」を作りました。
インストール方法
pipで簡単にインストールできます。
Sphinxモジュールに依存していますので、あらかじめSphinxをインストールしておいてください。
$ pip install sphinx-quickstart-plus
使い方
今まで、ドキュメント作成はsphinx-quickstart
と打っていましたが、sphinx-quickstart-plus
と打つだけです。
$ sphinx-quickstart-plus
すると、以下のようなメッセージが流れてきます。
Welcome to the Sphinx 1.5.1 quickstart utility.
Please enter values for the following settings (just press Enter to
accept a default value, if one is given in brackets).
Enter the root path for documentation.
> Root path for the documentation [.]: document_path
You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [n]: y
...
今までのsphinx-quickstart
と全く同じ出力が出ます。
「何も変わってねーじゃん」と思われるかもしれませんが、もう少しお付き合いください。
...
A Makefile and a Windows command file can be generated for you so that you
only have to run e.g. `make html' instead of invoking sphinx-build
directly.
> Create Makefile? (y/n) [y]:
> Create Windows command file? (y/n) [y]:
> ext_commonmark:use CommonMark and AutoStructify (y/n) [n]: y
> ext_nbshpinx:provides a source parser for *.ipynb files (y/n) [n]: y
> ext_blockdiag:Sphinx extension for embedding blockdiag diagrams (y/n) [n]: y
> ext_fontawesome:use font awesome (y/n) [n]: y
> ext_rtd_theme:use Read the Doc theme (y/n) [n]: y
> ext_autobuild:autobuild: Watch a directory and rebuild the documentation (y/n) [n]: y
最後にsphinx-quickstart
になかった設問が出てきます。
今現在の拡張と説明は以下のとおりです。
拡張名 | 説明 |
---|---|
ext_commonmark |
.rst だけでなく.md (CommonMark)が使えるようになります |
ext_nbshpinx | Jupyter Notebookが取り込めるようになります |
ext_blockdiag | ブロック図が書けるようになります |
ext_fontawesome | Font AwesomeがreSTから使えるようになります |
ext_rtd_theme | Read the Docsのテーマを使えるようになります |
ext_autobuild | オートビルドが使えるようになります |
これらのSphinx拡張がconf.py
を編集することなく使えるようになります。
それだけではありません、ふたたびsphinx-quickstart-plus
を起動すると、冒頭の設問が変わります。
> Use latest setting? (y/n) [y]: y
'y'とタイプすると、Path
、Project name
、Author
、Version
、Release
の5項目を答えるだけで、前回のドキュメントと同じ設定のドキュメントが作成されます。
前回のsphinx-quickstart-plus
で作成したドキュメント設定を記憶しています。
ちなみに'n'とタイプした場合は、通常のsphinx-quickstart
の設問が流れますが、デフォルト設定が最後の設定になっていますので、変更箇所以外はEnter
キーの連打でよいので楽ちんです。
$ sphinx-quickstart-plus
> Use latest setting? (y/n) [y]: n
...
You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [y]: <-デフォルトが最後の入力になってる
各拡張選択時にconf.py
に追加されるコード
ext_commonmark
# ----- CommonMark
source_suffix = [source_suffix, '.md']
from recommonmark.parser import CommonMarkParser
source_parsers = {
'.md': CommonMarkParser,
}
from recommonmark.transform import AutoStructify
github_doc_root = 'https://github.com/rtfd/recommonmark/tree/master/doc/'
def setup(app):
app.add_config_value('recommonmark_config', {
'url_resolver': lambda url: github_doc_root + url,
'auto_toc_tree_section': 'Contents',
}, True)
app.add_transform(AutoStructify)
ext_nbshpinx
# ----- Jupyter Notebook nbsphinx
extensions.append('nbsphinx')
exclude_patterns.append('**.ipynb_checkpoints')
ext_blockdiag
# ----- blockdiag settings
extensions.extend([
'sphinxcontrib.blockdiag',
'sphinxcontrib.seqdiag',
'sphinxcontrib.actdiag',
'sphinxcontrib.nwdiag',
'sphinxcontrib.rackdiag',
'sphinxcontrib.packetdiag',
])
blockdiag_html_image_format = 'SVG'
seqdiag_html_image_format = 'SVG'
actdiag_html_image_format = 'SVG'
nwdiag_html_image_format = 'SVG'
rackiag_html_image_format = 'SVG'
packetdiag_html_image_format = 'SVG'
ext_fontawesome
# ----- sphinx-fontawesome
import sphinx_fontawesome
extensions.append('sphinx_fontawesome')
ext_rtd_theme
# ----- Read the Docs Theme
html_theme = "sphinx_rtd_theme"
ext_autobuild
auto_buildはconf.py
を書き換えませんが、Makefileを書き換えます。
$ make livehtml
と打つと、オートビルドが始まります。
Windowsの人はauto_build.bat
が生成されるので、それを実行してください。
$ auto_build.bat
PyCharmなどの.md
を編集していると一時ファイルが作成されてしまい、それもビルドしてしまうので、いくつかの一時ファイルをビルド無視する設定も含まれています。
ライセンスについて
「sphinx-quickstart-plus」はライセンスフリーです、ご自由にお使いください。
なお、このモジュールを使っていかなる不利益が生じても責任は負いませんので、ご理解ください。
また、私の環境はUbuntuなのでWindowsとMacの環境ではテストできていません。
バグなどはあるかと思います。
問題がありましたら、GitHubのイシューかコメント欄におねがいします。
コード解説
このモジュール本体はコメントを合わせて400行もない小さなモジュールです、作成期間も6時間程度で殆どがデバッグ作業です。
ですが、sphinx-quickstart
の豊富な引数や機能をフルサポートしています。
どうしてこんな事ができるかというと、モンキーパッチという技術を使っているからです。
モンキーパッチとは?
モンキーパッチとは既存のライブラリの動作を乗っ取って、動的に書き換えてしまうパッチです。
これは動的言語の特性を活かした離れ業であり、コンパイル言語では真似できない手法です。1
補足
モンキーパッチは既存のライブラリのファイルを書き換えるものではありません。
あくまで既存ライブラリのファイルを変更することなく、動的に動作を変える手法です。
sphinx-quickstart-plus
をインストールしても、元となるSphinxライブラリの動作は一切変わりません。
参考
sphinx-quickstart
はsphinx.quickstart.py
というモジュールに処理が書かれています。
ですので、普通にsphinx.quickstart
をインポートしますが、ask_user
関数はモンキーパッチで書き換えてしまいますので、オリジナル処理の関数ポインタを忘れないよう、別途にfrom .. import ask_user
でインポートしています。
from sphinx import quickstart
from sphinx.quickstart import ask_user, generate, do_prompt, nonempty, boolean
quickstart.ask_user
関数をmonkey_patch_ask_user
関数で上書きして乗っ取ります。
# monkey patch
quickstart.ask_user = monkey_patch_ask_user
monkey_patch_ask_user
関数で独自の処理を行った後、オリジナルのquickstart.ask_user
関数を呼び出しています。
def monkey_patch_ask_user(d):
... 独自処理
# オリジナルの ask_user呼び出し
ask_user(d)
... 独自処理
他にも色んな関数をモンキーパッチで乗っ取っているのですが、基本的にやっている事は一緒です。
最後にquickstart.main
を呼びます。
quickstart.main(argv)
sphinx-quickstart-plusを更に拡張する
Did you want to further expand ‘sphinx-quickstart-plus’? Editing ‘sphinx-quickstart-plus’ source code for extension is not cool.
('sphinx-quickstart-plus'を更に拡張したくなった?拡張のために'sphinx-quickstart-plus'のコードを編集するなんて無粋なことしないでくれよ)
Let’s monkey patch!
(モンキーパッチしようぜ!)
Below is an example of a simple extension.
(下のコードはシンプルな拡張の例)
from sphinx_qsp import quickstart_plus
# Setting your extension.
your_extension = quickstart_plus.Extension(
"ext_your_ext", "your extensions description.",
conf_py="""
# ----Your Extension
import your_extension_package
extension.append("your-extension_name")
)
""",
package=["your_extension_packge"]
)
# Add your extension.
quickstart_plus.qsp_extensions.extend([
your_extension
])
# Run sphinx-quickstart-plus.
quickstart_plus.main()
The base class of extension is the following code.
(拡張に使う基底クラスのコードは以下の通り)
class Extension(object):
def __init__(self, key, description, conf_py=None, new_makefile=None,
makefile=None, package=None):
self.key = key
self.description = description
self.conf_py = conf_py
self.new_makefile = new_makefile
self.makefile = makefile
self.package = package or []
# noinspection PyUnusedLocal
def extend_conf_py(self, d):
return self.conf_py
def extend_makefile(self, d, make_mode):
return self.new_makefile if make_mode else self.makefile
The extended class of ‘sphinx-autobuild’ is the following code.
(‘sphinx-autobuild’の拡張クラスは以下のようになる)
class AutoBuildExtension(Extension):
def extend_makefile(self, d, make_mode):
if d['batchfile']:
batchfile_path = os.path.join(d['path'], 'auto_build.bat')
source_dir = d['sep'] and 'source' or '.'
build_dir = d['sep'] and 'build' or d['dot'] + 'build'
open(batchfile_path, "w").write(
AUTO_BUILD_BATCH.format(
build_dir=build_dir, source_dir=source_dir,
AUTOBUILD_IGNORE=" ".join(AUTOBUILD_IGNORE),
)
)
makefile = self.new_makefile if make_mode else self.makefile
return makefile.format(" ".join(AUTOBUILD_IGNORE))
あとがき
個人的にいくつかのドキュメントを作成しましたが、めっちゃ便利です。
-
http://postd.cc/monkey-patching-in-go/ でコンパイル言語のモンキーパッチしてました、アセンブラを使うかなりな黒魔術ですね ↩