読者です 読者をやめる 読者になる 読者になる

sphinxでtsv-tableできなかった!(前編)

sphinx

きっかけは sphinxでtsv-tableしたい! - think it over

結論から言うと、ディレクティブにコンテンツが渡ったときにはすでにタブはスペースに変換されておりました。。。

あきらめきれないので、そこまで行き着くまでの流れを備忘録的にまとめておきます。

長いので、前編、後編の2回に分けます。

csv-tableの実装はいずこ?

pythonのsite-package配下を探したところ、csv-tableの実装は

/usr/lib/python2.7/site-packages/docutils-0.10-py2.7.egg/docutils/parsers/rst/directives/tables.py

※Windows + Cygwin環境

にありました。


tables.pyには

  • CSVTable (csv-tableディレクティブの実装)
  • ListTable(list-tableディレクティブの実装)

等が含まれています。

ちなみに、罫線をrstに記述していく以下のタイプは一つ上の階層にあるtableparser.pyにその実装があります。

 +------------------------+------------+----------+----------+
 | Header row, column 1   | Header 2   | Header 3 | Header 4 |
 +========================+============+==========+==========+
 | body row 1, column 1   | column 2   | column 3 | column 4 |
 +------------------------+------------+----------+----------+
 | body row 2             | Cells may span columns.          |
 +------------------------+------------+---------------------+
 | body row 3             | Cells may  | - Table cells       |
 +------------------------+ span rows. | - contain           |
 | body row 4             |            | - body elements.    |
 +------------------------+------------+---------------------+

csv-tableを継承してtsv-tableを作る

さて、CSVTableですが、ディレクティブのコンテンツであるCSVデータを解析する「parse_csv_data_into_rows」関数オブジェクトがあります。

CSVTableを継承したTSVTableを作ってparse_csv_data_into_rowsをオーバーラードしてタブ区切り用にカスタマイズすればOKじゃーん、やったね!

ってことで、tables.pyと同じ階層にtsvtable.pyを作成し、まずは継承のみしてみる

"""
Directives for tsv-table elements.
"""

__docformat__ = 'reStructuredText'


import sys
import os.path
import csv

from StringIO import StringIO
from docutils import io, nodes, statemachine, utils
from docutils.utils.error_reporting import SafeString
from docutils.utils import SystemMessagePropagation
from docutils.parsers.rst import Directive
from docutils.parsers.rst import directives
from docutils.parsers.rst.directives.tables import CSVTable

class TSVTable(CSVTable):

    def run(self):
        return CSVTable.run(self)

tsv-tableディレクティブの登録

ここまでで、csv-tableと同一機能のtsv-tableが出来上がり。
これで、できるのか?と疑問を抱きつつ、makeしてみると、案の定、、

ERROR: Unknown directive type "tsv-table".

あーーーん。。。

ディレクティブを登録しなければならないようです。

Creating reStructuredText Directives

公式ドキュメントによると、ディレクティブを登録する方法は2つ。

  1. docutilsのコアディレクティブとして使う場合
    • __init__.pyの「_directive_registry」ディクショナリに追加してね
  2. アプリ固有のディレクティブとしえ使う場合
    • 「register_directive」関数を使ってディレクティブを追加してね


後者で!!

むんむん唸りながら、結局、sphinxのconf.pyに

from docutils.parsers.rst import directives
from docutils.parsers.rst.directives.tsvtable import TSVTable
directives.register_directive('tsv-table', TSVTable)

と書くことでtsv-tableのディレクティブの登録が行われ、

.. tsv-table:: 
   :header: "開始", "終了", "時間", "内容"
   :widths: 10, 10, 10, 200
   
   08:00, 08:10, 00:10, メールチェック
   08:10, 08:20, 00:10, 

が正常にparseされるようになりました。


前編おわり!!