Today I learned。Sphinx拡張開発の中で知ったことです。
目次
Sphinx拡張からロギング
自作拡張の中でロギングしてみようとなり1、sphinx.util.logging
を触りました。
getLogger()
してロガーインスタンスを得て、重要度ごとのメソッドにメッセージを渡します(標準モジュールloggingと似ていますね2)
logger = logging.getLogger(__name__)
logger.info("✅ Reveal.js CopyCode plugin is already installed")
この出力を見たときに気づいたのです。
いつも見ているSphinxのビルドログには、太字が混ざって出力されていることに。
太字のログ出力の実装
ビルダー
ビルドログの文字列でコードベースを検索して当たりをつけました3。
https://github.com/sphinx-doc/sphinx/blob/v8.0.2/sphinx/builders/__init__.py#L381
logger.info(bold(__('updating environment: ')), nonl=True)
- bold!!(この後見ていきます)
nonl=True
は改行しないという指定。たしかに太字の後にログが続きますね__
は国際化4という理解です。今回はスコープアウトです
ログメッセージをsphinx.util.console.bold()
に通すことで、太字にしていることが分かりました。
bold()
の実装
console.pyを見ます。
https://github.com/sphinx-doc/sphinx/blob/v8.0.2/sphinx/util/console.py
ANSIエスケープシーケンスを使っていると理解しました。
過去のブログで取り上げており、再会を果たしました!
詳細は過去記事に譲りますが、例えば「Running Sphinx v8.0.2」の「Running Sphinx」を太字にしたい場合、
% printf '\x1b[01mRunning Sphinx\x1b[39;49;00m v8.0.2\n' Running Sphinx v8.0.2
「Running Sphinx」が太字になっています!
これがbold("Running Sphinx") + " v8.0.2"
に相当します。
console.pyはANSIエスケープシーケンスのサポートを拡張しやすいように、動的に関数定義する書き方と読みました。
- エスケープシーケンスは
codes
という辞書に持つ- https://github.com/sphinx-doc/sphinx/blob/v8.0.2/sphinx/util/console.py#L180-L190
codes["bold"]
は"\x1b[01m"
を返すcodes["reset"]
は"\x1b[39;49;00m"
- モジュールに
bold()
関数などを設けるのがcreate_color_func()
- https://github.com/sphinx-doc/sphinx/blob/v8.0.2/sphinx/util/console.py#L173
- モジュールの名前空間の辞書である globals() の返り値に、
bold()
関数の定義を追加しています
bold()
関数の実体は、ANSIエスケープシーケンスを返す関数- https://github.com/sphinx-doc/sphinx/blob/v8.0.2/sphinx/util/console.py#L121
return escseq('bold') + text + escseq('reset')
printf
コマンドで示したように、ANSIエスケープシーケンスが含まれた文字列です
終わりに
Sphinxのビルドログで太字部分をどのように実現しているか、仕組みを知りました。
P.S. sphinx-revealjsのロギング
NOTICE: For next major version, path of Revealjs will change to other.
https://github.com/attakei/sphinx-revealjs/blob/v2.9.3/sphinx_revealjs/__init__.py#L59-L63
def notify_deprecated(app: Sphinx, config: Config): """Do not work. But it keep for next deprecated.""" logger.info( "NOTICE: For next major version, path of Revealjs will change to other." )
拡張の実装ではconfig-inited
イベントでログ出力するようにしています。
https://github.com/attakei/sphinx-revealjs/blob/v2.9.3/sphinx_revealjs/__init__.py#L77
app.connect("config-inited", notify_deprecated)
- 先日公開したsphinx-revealjs-copycodeにロギングを追加しています。 https://github.com/ftnext/sphinx-revealjs-copycode/commit/9cf562ccd3dfda4affe6d06f9f4c2fb324e29c8e↩
- 先日の ↩
- ビルダー内のロギングでした。ビルダーとは:SphinxのTranslatorってなんだろう? 自作拡張の実装の理解を深める - nikkie-ftnextの日記↩
- 国際化 — Sphinx documentation↩