はじめに
秘密はね、最後に明かされるんだよ、nikkieです。
Python Boot Camp1(a.k.a pycamp)のライディングページを今年Sphinxで作りました!2
この実装の一部「過去の開催回で集まった人数」の表について、実装の秘密を明かしちゃいます!
目次
- はじめに
- 目次
- 「過去の開催回で集まった人数」の表
- 案:csv-table × マークアップしたCSV
- Sphinx拡張を用意して、CSVではマークアップ不要にする
- csv-tableディレクティブの動きを知るのに役立ったリソース
- 思わぬ収穫:csv.readerはリストも受け付ける
- 終わりに
「過去の開催回で集まった人数」の表
ランディングページの下方に位置する参加人数の表。
構成要素は以下です:
- 開催地
- 参加人数
- 開催地からconnpassのイベントページへのリンク
構成要素の他にもう1つ要件を認識していました。
それは、実装したnikkieでなくても簡単に更新できることです。
pycampは今後も開催され3、この表にも行が追加されていきます。
Sphinxでランディングページを作ることにはモチベーションの高いnikkieですが、作り終わった後の行の追加は心の底からやりたいことと感じませんでした。
そのためnikkieに行の追加を依頼する運用だと、nikkieがボトルネックとなり回らなくなる可能性が高いです。
熱しやすく冷めやすい自分の特性を加味した上で、実装者以外でも容易に行を追加できる状態を達成するのが重要と考えました。
案:csv-table
× マークアップしたCSV
csv-table
ディレクティブに、リンクのマークアップ4を使ったCSVを渡すと動作しました5。
開催地,参加人数 `京都 <https://pyconjp.connpass.com/event/33014/>`__,一般参加5人 `愛媛 <https://pyconjp.connpass.com/event/34564/>`__,一般参加11人、学生1人
正しい方法は分かりました!
ですが、この方法は簡単ではないように思われます。
仕組みを知らない人にとっては正しく使えずに、マークアップを間違いうるでしょう。
ブラックボックスにできていないので簡単ではないのだと考えています。
Sphinx拡張を用意して、CSVではマークアップ不要にする
そこで、Sphinx拡張を自作することにしました。
上記のCSVのマークアップロジックを拡張にラップします。
以下のようなCSVに行を追加することで、拡張によってリンクが作られて、表の見た目は同一になります。
開催地,URL,参加人数 京都,https://pyconjp.connpass.com/event/33014/,一般参加5人 愛媛,https://pyconjp.connpass.com/event/34564/,一般参加11人、学生1人
作ったディレクティブevent-history-csv-table
はEventHistoryCSVTable
クラスとして実装しています6。
このクラスはCSVTable
(csv-table
ディレクティブの実装)を継承します。
parse_csv_data_into_rows
メソッドをオーバーライドし、読み込んだcsv_data
(行を表す文字列のリスト)の処理を追加します。
csv_data
のイメージ
[ "開催地,URL,参加人数", "京都,https://pyconjp.connpass.com/event/33014/,一般参加5人", "愛媛,https://pyconjp.connpass.com/event/34564/,一般参加11人、学生1人", ]
csv_data
をcsv
モジュール7を使ってパースして、1行を
`開催地 <URL>`__,参加人数
の形式に変換します。
こうしてマークアップはSphinx拡張にラップされ、「開催地」「URL」「参加人数」の3列からなるCSVに行を追加しさえすれば人数表が更新されるようになりました!🙌
マークアップしてCSVに行を追加するよりも簡単になってますよね
csv-table
ディレクティブの動きを知るのに役立ったリソース
以下のブログ記事を参考に、エディタ(VS Code)でCSVTable
の定義(docutilsの実装)を確認しながら実装を進めました
アウトプットしていただき、ありがとうございました!
思わぬ収穫:csv.readerはリストも受け付ける
csv.reader
やcsv.DictReader
にはファイルオブジェクトしか渡してこなかったのですが、今回CSVTable
クラスの実装を見て分かったのは「イテラブル(例:リスト)8を渡せる」ということ。
実際にcsv_data
(リストを指す変数)を渡しています。
reader = csv.DictReader(csv_data)
ドキュメントを引くとcsv.reader
の第1引数csvfile
について9
csvfile は イテレータ プロトコルをサポートし、
__next__()
メソッドが呼ばれた際に常に文字列を返すような任意のオブジェクトにすることができます --- ファイルオブジェクト でもリストでも構いません。
とあります。
リ ス ト で も 構 い ま せ ん!
終わりに
pycampランディングページにある参加人数の表の実装の秘密を明かしました。
表に含まれるリンクは、マークアップの仕方をSphinx拡張にラップし、ランディングページの実装の詳細を知らなくても、CSVに行を追加するだけでページ下部の表にも行が追加されます!
今回得た知見はcsv-table
ディレクティブにCSVの処理を追加したいケースで今後も活用できそうに思います。
また、個人的な課題と思っている「正しい使い方を簡単に、誤った使い方を困難に」を練習した例とも思っています。
これは小さな成功体験!(もっとよくできそうなアイデアが浮かんだ方はぜひ教えてくださいませ)
本記事は、先日のPyLadiesTokyo 8周年パーティーでのLTの補足記事でもありました。
https://ftnext.github.io/2022_slides/pyladies_tokyo_anniversary/landing_page_with_sphinx.html#/11 の項目の補足です。
- 一般社団法人PyCon JP Associationが開催する日本各地での初心者向けPythonチュートリアルです。テキスト:Python Boot Camp テキスト - Python Boot Camp Text ドキュメント↩
- Sphinxはドキュメント変換ツールです。この記事では知っている前提で進めます。はじめの一冊としては O'Reilly Japan - Sphinxをはじめよう 第3版 がオススメです。↩
-
直近では香川で開催されました。
↩@kobatomo3H @takanory @puhitaku @yamayama_k5 @_khrd_ @tam_x @ftnext あなたのツイートをトゥギャりました。読んでいただけると幸いです。 https://t.co/LHyEarSuaV
— Tomohiro Kobayashi (@kobatomo3H) 2022年11月21日 - 詳しくは reStructuredTextとリンクを作るマークアップ(全部一緒だと思っていたのですが、細かい意味の違いがあった…だと…) - nikkie-ftnextの日記 をどうぞ↩
- https://github.com/pyconjp/pycamp.landing_page/commit/40100e881d0114216af2e50668b08f3e6ea668e7↩
- https://github.com/pyconjp/pycamp.landing_page/blob/4b57021eb2a3d1d50b6d9a924050c1545a461f39/source/extensions/event_history.py↩
- csv --- CSV ファイルの読み書き — Python 3.11.0b5 ドキュメント↩
- https://docs.python.org/ja/3/glossary.html#term-iterable↩
- https://docs.python.org/ja/3/library/csv.html#csv.reader↩