Sphinxにおけるコードの説明

前のセクションのチュートリアルでは、Sphinxで記述的なドキュメントを作成する方法について説明しました。このセクションでは、代わりにコードオブジェクトについて説明します。

Sphinxは、Python、C、C++、JavaScript、reStructuredTextなど、いくつかの言語のコードオブジェクトのドキュメント化をサポートしています。これらはそれぞれ、ドメイン別にグループ化された一連のディレクティブとロールを使用してドキュメント化できます。チュートリアルの残りの部分ではPythonドメインを使用しますが、このセクションで説明するすべての概念は、他のドメインにも適用されます。

Python

Pythonオブジェクトのドキュメント化

Sphinxは、Pythonドメインにグループ化された、Pythonオブジェクトをドキュメント化するためのいくつかのロールとディレクティブを提供しています。たとえば、py:functionディレクティブを使用してPython関数を次のようにドキュメント化できます。

docs/source/usage.rst
Creating recipes
----------------

To retrieve a list of random ingredients,
you can use the ``lumache.get_random_ingredients()`` function:

.. py:function:: lumache.get_random_ingredients(kind=None)

   Return a list of random ingredients as strings.

   :param kind: Optional "kind" of ingredients.
   :type kind: list[str] or None
   :return: The ingredients list.
   :rtype: list[str]

結果は次のようにレンダリングされます。

HTML result of documenting a Python function in Sphinx

SphinxでのPython関数のドキュメント化のレンダリング結果

いくつかの点に注意してください。

  • Sphinxは.. py:functionディレクティブの引数を解析し、モジュール、関数名、パラメーターを適切に強調表示しました。

  • ディレクティブの内容には、関数の1行の説明と、関数パラメーター、その期待される型、戻り値、戻り値の型を含む情報フィールドリストが含まれています。

注記

py:プレフィックスはドメインを指定します。primary_domain設定を使用してグローバルにデフォルトのドメインを設定するか、default-domainディレクティブを使用して呼び出し時点からファイルの最後まで変更することで、プレフィックスを省略できます。たとえば、py(デフォルト)に設定すると、.. function::を直接記述できます。

Pythonオブジェクトの相互参照

デフォルトでは、これらのディレクティブのほとんどは、対応するロールを使用してドキュメントの任意の部分から相互参照できるエンティティを生成します。関数の場合は、次のようにpy:funcを使用できます。

docs/source/usage.rst
The ``kind`` parameter should be either ``"meat"``, ``"fish"``,
or ``"veggies"``. Otherwise, :py:func:`lumache.get_random_ingredients`
will raise an exception.

コードドキュメントを生成する場合、Sphinxは、オブジェクトの名前を使用するだけで、明示的にロールを使用しなくても、自動的に相互参照を生成します。たとえば、py:exceptionディレクティブを使用して、関数によって発生するカスタム例外を記述できます。

docs/source/usage.rst
.. py:exception:: lumache.InvalidKindError

   Raised if the kind is invalid.

次に、この例外を関数の元の説明に追加します。

docs/source/usage.rst
.. py:function:: lumache.get_random_ingredients(kind=None)

   Return a list of random ingredients as strings.

   :param kind: Optional "kind" of ingredients.
   :type kind: list[str] or None
   :raise lumache.InvalidKindError: If the kind is invalid.
   :return: The ingredients list.
   :rtype: list[str]

最後に、結果は次のようになります。

HTML result of documenting a Python function in Sphinx with cross-references

相互参照付きのSphinxでのPython関数のドキュメント化のHTML結果

素晴らしいですね!

ドキュメントへのdoctestの組み込み

Pythonライブラリのコードを説明しているので、ドキュメントとコードをできるだけ同期させることが役立ちます。Sphinxでこれを行う方法の1つは、ドキュメントにコードスニペット(doctestと呼ばれる)を含めることです。これは、ドキュメントがビルドされるときに実行されます。

このチュートリアルで説明されているdoctestやその他のSphinx機能をデモするために、Sphinxはコードをインポートできる必要があります。conf.pyの先頭に次のように記述します。

docs/source/conf.py
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here.
import pathlib
import sys
sys.path.insert(0, pathlib.Path(__file__).parents[2].resolve().as_posix())

注記

sys.path変数を変更する代わりに、pyproject.tomlファイルを作成してコードをインストール可能にし、他のPythonライブラリのように動作させることもできます。ただし、sys.pathアプローチの方が簡単です。

次に、ドキュメントにdoctestを追加する前に、conf.pydoctest拡張機能を有効にします。

docs/source/conf.py
extensions = [
    'sphinx.ext.duration',
    'sphinx.ext.doctest',
]

次に、次のようにdoctestブロックを記述します。

docs/source/usage.rst
>>> import lumache
>>> lumache.get_random_ingredients()
['shells', 'gorgonzola', 'parsley']

Doctestには、標準のPythonインタプリタプロンプトである>>>で始まる実行するPython命令と、各命令の期待される出力があります。これにより、Sphinxは実際の出力と期待される出力が一致するかどうかを確認できます。

上記のコードエラーではなく、doctestの失敗がどのように見えるかを確認するために、最初に戻り値を間違って記述してみましょう。そのため、次のようなget_random_ingredients関数を追加します。

lumache.py
def get_random_ingredients(kind=None):
    return ["eggs", "bacon", "spam"]

これで、make doctestを実行して、ドキュメントのdoctestを実行できます。最初は、実際のコードが指定どおりに動作しないため、エラーが表示されます。

(.venv) $ make doctest
Running Sphinx v4.2.0
loading pickled environment... done
...
running tests...

Document: usage
---------------
**********************************************************************
File "usage.rst", line 44, in default
Failed example:
    lumache.get_random_ingredients()
Expected:
    ['shells', 'gorgonzola', 'parsley']
Got:
    ['eggs', 'bacon', 'spam']
**********************************************************************
...
make: *** [Makefile:20: doctest] Error 1

ご覧のとおり、doctestは、簡単に確認できるように、期待される結果と実際の結果を報告します。これで関数を修正する時間です。

lumache.py
def get_random_ingredients(kind=None):
    return ["shells", "gorgonzola", "parsley"]

最後に、make doctestは成功を報告します!

ただし、大規模なプロジェクトでは、この手動アプローチは少し面倒になる可能性があります。次のセクションでは、プロセスを自動化する方法について説明します。

その他の言語 (C、C++、その他)

オブジェクトのドキュメント化と相互参照

Sphinxは、他のプログラミング言語で記述されたオブジェクトのドキュメント化と相互参照もサポートしています。C、C++、JavaScript、reStructuredTextという4つの追加の組み込みドメインがあります。サードパーティの拡張機能では、Fortran、

たとえば、C++の型定義をドキュメント化するには、次のように組み込みのcpp:typeディレクティブを使用します。

.. cpp:type:: std::vector<int> CustomList

   A typedef-like declaration of a type.

結果は次のようになります。

typedef std::vector<int> CustomList

型のtypedefのような宣言。

このようなディレクティブはすべて、対応するロールを使用して相互参照できる参照を生成します。たとえば、前の型定義を参照するには、次のようにcpp:typeロールを使用できます。

Cross reference to :cpp:type:`CustomList`.

これにより、前の定義へのハイパーリンクが生成されます。CustomList