sphinxでtsv-tableできなかった!(後編)
sphinxでtsv-tableできなかった!(前編) - think it over
で、csv-tableと同等の機能を持つtsv-tableの作成までできました。
後編では断念するまでの経緯をまとめておこうかと。
csv-tableの実装を確認
前編でも触れましたが、
/usr/lib/python2.7/site-packages/docutils-0.10-py2.7.egg/docutils/parsers/rst/directives/tables.py
のソースを確認すると、
「parse_csv_data_into_rows」
というわかりやすい名前の関数があります。
def parse_csv_data_into_rows(self, csv_data, dialect, source): # csv.py doesn't do Unicode; encode temporarily as UTF-8 csv_reader = csv.reader([self.encode_for_csv(line + '\n') for line in csv_data], dialect=dialect) rows = [] max_cols = 0 for row in csv_reader: row_data = [] for cell in row: # decode UTF-8 back to Unicode cell_text = self.decode_from_csv(cell) cell_data = (0, 0, 0, statemachine.StringList( cell_text.splitlines(), source=source)) row_data.append(cell_data) rows.append(row_data) max_cols = max(max_cols, len(row)) return rows, max_cols
実際にCSV形式のコンテンツの読み込みを行っているのは「csv.reader」であることがわかります。
csvっていいながらも区切り文字を指定できるんでしょ、と調べると以下に辿り着く。
13.1. csv — CSV ファイルの読み書き — Python 2.7ja1 documentation
そこに記述されている、「短い利用例」を引用すると、
>>> import csv >>> spamReader = csv.reader(open('eggs.csv', 'rb'), delimiter=' ', quotechar='|') >>> for row in spamReader: ... print ', '.join(row) Spam, Spam, Spam, Spam, Spam, Baked Beans Spam, Lovely Spam, Wonderful Spam
おお!やはり「delimiter」なるものが!!!
タブ区切りに♪
早速、parse_csv_data_into_rowsをtsv-tableでオーバーライドする。
delimiterに「\t」を指定して、rstをタブ区切りにして、make html!
ERROR: "tsv-table" widths do not match the number of columns in table (1).
あちゃー。
もともと「タブ区切りは外部ファイルに定義しなきゃだめよ」という制約があったので、
そんな単純に行く訳ないかと反省し、処理を追いはじめる。
タブがスペースに?誰が?
まずは、parse_csv_data_into_rowsに渡されている、csv_dataの中身を確認してみると、
なんと、タブがない。スペースに置き換わっている??
parse_csv_data_into_rowsを起点にして呼出し元を
さかのぼり、
さかのぼり、、
さかのぼり、、、
行き着いた先は、、、、
/usr/lib/python2.7/site-packages/docutils-0.10-py2.7.egg/docutils/parsers/rst/__init__.py
貴様か、Parser
__init__.pyの中にParserというクラスが定義されており、parse関数の中身を見ると、こんな処理が。
inputlines = docutils.statemachine.string2lines(
inputstring, tab_width=document.settings.tab_width,
convert_whitespace=True)
convert_whitespace。ほーーう。
特定のために前後にデバッグプリントを埋め込む
print inputstring.split("\n") inputlines = docutils.statemachine.string2lines( inputstring, tab_width=document.settings.tab_width, convert_whitespace=True) print inputlines
結果、
[u'.. tsv-table::', u' :header: "\u958b\u59cb"\t"\u7d42\u4e86"\t"\u6642\u9593"\t"\u5185\u5bb9"', u' :widths: 10, 10, 10, 200', u'', u' 09:00\t09:10\t00:10\t\u30c6\u30b9\u30c8', u''] [u'.. tsv-table::', u' :header: "\u958b\u59cb" "\u7d42\u4e86" "\u6642\u9593" "\u5185\u5bb9"', u' :widths: 10, 10, 10, 200', u'', u' 09:00 09:10 00:10 \u30c6\u30b9\u30c8']
おお、、、、こいつだ。。。
挑戦は続けます
Parser.parse関数を書き換えてしまうのは影響範囲が計り知れない、そして時間の都合で今回はここで断念。。。
いつか近いうちにリベンジします。