Tracのチケット一覧のCSV/TSVエクスポート
Tracでは、チケットの一覧を、CSV/TSV形式でエクスポートすることが可能です。
ただ、この出力は、以下のような問題があって多少使いづらい。
- 文字コードがUTF-8
- 日付が一加工を加える必要がある形式
- Trac0.11では秒をint値として出力したもの
- Trac0.11で「2008-08-30T10:00:00Z+0900」というISO 8601形式
国際化としては正しいと思うのですが、これでは、出力したものをExcelで読み込んでグラフ表示したりする際にも、一手間かかってしまいまいます。
ということで、この問題を解決するべく、以下のようなパッチを作ってみました。
Trac0.10とTrac0.11では、処理が大分異なっているようなので、それぞれのパッチを作成しました。
- 変更点
- 文字コードをcp932とする
- 日付の値はExcelの書式設定で言うところの「yyyy/mm/dd hh:mm:ss」という形式にする
Trac0.10
TracLightning 1.8.2を利用して確認しました。
Index: report.py =================================================================== --- report.py (revision 1) +++ report.py (working copy) @@ -491,11 +491,34 @@ def _render_csv(self, req, cols, rows, sep=',', mimetype='text/plain', filename=None): req.send_response(200) - req.send_header('Content-Type', mimetype + ';charset=utf-8') + req.send_header('Content-Type', mimetype + ';charset=cp932') if filename: req.send_header('Content-Disposition', 'filename=' + filename) req.end_headers() + def fmt_time(t): + return format_time(t) + + def fmt_datetime(dt): + return format_datetime(dt) + + col_conversions = { + 'time' : fmt_time, + 'datetime' : fmt_datetime, + 'changetime' : fmt_datetime, + 'date' : fmt_datetime, + 'created' : fmt_datetime, + 'modified' : fmt_datetime, + } + + converters = [col_conversions.get(c.strip('_'), unicode) for c in cols] + + for rowindex in xrange(len(rows)): + row = list(rows[rowindex]) + for colindex in xrange(len(row)): + row[colindex] = converters[colindex](row[colindex]).encode('utf-8') + rows[rowindex] = row + req.write(sep.join(cols) + '\r\n') for row in rows: req.write(sep.join(
Trac0.11
TracLightning 2.0.6を利用して確認しました。
Index: report.py =================================================================== --- report.py (revision 1) +++ report.py (working copy) @@ -639,34 +639,34 @@ def _send_csv(self, req, cols, rows, sep=',', mimetype='text/plain', filename=None): req.send_response(200) - req.send_header('Content-Type', mimetype + ';charset=utf-8') + req.send_header('Content-Type', mimetype + ';charset=cp932') if filename: req.send_header('Content-Disposition', 'filename=' + filename) req.end_headers() - def iso_time(t): - return format_time(t, 'iso8601') + def fmt_time(t): + return format_time(t) - def iso_datetime(dt): - return format_datetime(dt, 'iso8601') + def fmt_datetime(dt): + return format_datetime(dt) col_conversions = { - 'time': iso_time, - 'datetime': iso_datetime, - 'changetime': iso_datetime, - 'date': iso_datetime, - 'created': iso_datetime, - 'modified': iso_datetime, + 'time' : fmt_time, + 'datetime' : fmt_datetime, + 'changetime' : fmt_datetime, + 'date' : fmt_datetime, + 'created' : fmt_datetime, + 'modified' : fmt_datetime, } converters = [col_conversions.get(c.strip('_'), unicode) for c in cols] writer = csv.writer(req, delimiter=sep) - writer.writerow([unicode(c).encode('utf-8') for c in cols]) + writer.writerow([unicode(c).encode('cp932') for c in cols]) for row in rows: row = list(row) for i in xrange(len(row)): - row[i] = converters[i](row[i]).encode('utf-8') + row[i] = converters[i](row[i]).encode('cp932') writer.writerow(row) raise RequestDone
チケットの一覧だけでなく、チケット単体でもCSV/TSVエクスポートが可能なのですが、その場合は、web_ui.pyを修正することが必要となります。