今日の三角巾(さんかくきん) by matobaa

| プロフィール | 欲しい物リスト | おとなりページ | @matobaa
追記

2012-03-31 [長年日記]

EpochFieldPluginをリリースした

2012-01-142012-03-24でいろいろトライしていたやつの結論として、EpochFieldPlugin をリリースしたよ。

Tracのフィールドに時刻を指定できるプラグイン。ユーザのタイムゾーンにしたがって表示を変えるので、ワールドワイドで使ってるTracでも誤解なく使えるようにしてある。pytzを使えば夏時間も理解するよ。

CustomFieldAdmin上でフォーマットをepochと指定するだけで使えるようになっているので、特に説明なく使えるんじゃないかな。


2012-03-24 [長年日記]

tracでepoch time をちゃんと扱いたい (日付の表示が変になっちゃう。の続き)

チケットの作成日などの日付フィールドは、date, time, datetime, created, modified といった特定のカラム名の場合だけ 日付文字列(YYYY-MM-DDなど)で表示され、それ以外は unixtimeである整数値(16桁の数値)で表示されてしまうという問題がある。具体的には、tracのレポートで、チケットの作成日を created 以外のカラム名で表示しようとした際に、16桁の数字で表示されてしまう。

これを解決するために、Genshiのメソッドをサーバ側で使って変換するプラグインを作ってみた。EpochFieldPlugin まだ詰めが甘いところがある。

ついでに、時刻を扱うカスタムフィールドを作ってみた。

trac-hacks.org にある DateFieldPluginは日付を扱うカスタムフィールドを作れるのだが、時刻を扱うことができない。そこで、時刻を扱うカスタムフィールドに取り組んでみた。

UI部分はjquery.datetimeentry.jsというよさげなのを見つけたので、それで実装してみている。

まだ作りかけ。フィールド名をソースに直書きして動作確認中。

tracってユーザごとにタイムゾーンを指定できるので、時刻を扱う場合はユーザごとのタイムゾーンを意識しないといけない。日本で「正午」と入力したら、中国では「午前11時」と扱われなければいけない。

だとしたら、サーバ上では epoch time で扱い、表示する際にはユーザのタイムゾーンに応じて時刻を調整して表示してやればいい。

JavaScriptで実装してやろう。簡単かんたん……。

あれ。時差って結構大変だ。

これって本来、日付でもきちんと考えないといけないことなのでは。日本で 「3月24日」と入力したら、北米西海岸だったら「3月23日」だったりするのでは。

とか考えていったら、「isdst」とかいうメソッドにぶちあたった。なんだこれー。GMT+0900 だけでは語れない世界がそこにあるらしい……。

Pythonでは pytzで解決できるらしいが、JavaScript側で解決しようとしても適当なライブラリが見つからない。ううむー。

元データを探してみた。Time-zone database down によれば、ちょっと前にややこしいことがあったらしいが、現時点ではIANAのtime-zonesにあるのが最新ぽい。

で。中を見てみたら、"2dst"とかいう文字がある! サマータイムを二段階やってる! まじっすか。……がっつり読んでみたら、1940年代にやってたらしく、1970年以降にはそういうのはないみたい。でも、「4月の最後の日曜日から」とかいう感じで、単純には実装できなさそう。うーん。

Olson javascript で検索すると はてぶが見つかるが、その先が 404 Not Found だ。うーん。方針変更が必要かもー。


2012-01-14 [長年日記]

[trac] ワークフローをまわすとき「承認日」が欲しい。なんてな。

旧来の稟議書には必ず入ってるので、それをそのままtracに移行する場合「承認日」「承認者」とかいうフィールドを用意して解決しよう、ということになりがち*1。 すると、「クローズする際は、承認日フィールドに現在の日時を、承認者フィールドに自分の名前を入れてクローズボタンを押す」とかいうルールで運用されることになる。ワークフローシステムをつかえばこのへんは自動的にできるのに、チケットシステムだと泥臭い運用になってしまう。 こんなの絶対おかしいよ。
そこで、tracが持っている「ステータスを変えた日時」を取り出して使おう。SQLはこんなかんじ:

SELECT ticket, max(time) FROM ticket_change
    WHERE
        field = 'status' AND
        newvalue = "closed"
    GROUP BY ticket;
closed以外でも使えるように条件からはずして、tracのレポートから使えるようにビューにしておく:
CREATE VIEW status_change AS
    SELECT ticket, author, newvalue AS status, max(time) AS time
        FROM ticket_change WHERE field = 'status'
        GROUP BY ticket, newvalue;

これで、tracのレポートで以下のように使えるようになる:
select id, summary, ticket.time,
    a.time as Accepted_Date,
    c.time as Closed_Date, c.author as Closer
from ticket
left join status_change AS a on (a.ticket = ticket.id and a.status = "accepted")
left join status_change AS c on (c.ticket = ticket.id and c.status = "closed")

*1 TracLightningでは、日付を意味するフィールドは DateFieldPluginを使うことで日付文字列を文字列としてそのまま格納するようになっている。これが「承認日」とかいうフィールドを作ろうとさせる要因のひとつになっているんだろうね。

[trac] 日付の表示が変。数字になっちゃう。

オリジナルのTracを使う場合、チケットの作成日などの日付フィールドは、date, time, datetime, created, modified といった特定のカラム名の場合だけ 日付文字列(YYYY-MM-DDなど)で表示され、それ以外は unixtimeである整数値(16桁の数値)で表示されてしまうという問題がある。具体的には、tracのレポートで、チケットの作成日を created 以外のカラム名で表示しようとした際に、16桁の数字で表示されてしまう。

ネットを検索してみると、SQLiteのdatetime関数で日付文字列に変換する処理を入れる、というやり方が見つかった。こんなかんじ:

select id, summary, ticket.time,
    datetime(a.time/1e6,'unixepoch') as Accepted_Date,
    datetime(c.time/1e6,'unixepoch') as Closed_Date, c.author as Closer
from ticket
left join status_change AS a on (a.ticket = ticket.id and a.status = "accepted")
left join status_change AS c on (c.ticket = ticket.id and c.status = "closed")

まぁこれでもいいのだけど、以下の二つの点でいけてない:

  1. tracではユーザごとにタイムゾーンを設定できるので、ユーザのタイムゾーンとサーバのタイムゾーンが異なるとき、「チケット作成日はユーザのタイムゾーンでの時刻表示、それ以外はサーバのタイムゾーンでの時刻表示」とかいう、変な状態になってしまう。
  2. datetime関数はSQLite固有なので、バックエンドDBにMySQLを使う場合はfrom_unixtimeを使うように、PostgreSQLならSELECT TIMESTAMP WITH TIME ZONE 'epoch' + 982384720.12 * INTERVAL '1 second';というように書き換える必要がある。

ならば、Genshiが createdカラムを日付文字列に変換する処理を流用してみよう

Genshiが日付文字列に変換する処理そのものはユーザのタイムゾーンを意識した変換をしてくれるのだが、残念ながら「どのカラムを対象とするか」がTracに含まれるGenshiテンプレートでハードコードされている*1。このファイルをどうにか差し替えてやることで、closed.date なども、ユーザのタイムゾーンを意識した変換ができるはず。

そこで、ITemplateProviderインタフェースを実装したプラグインを作って、ちょっと改造したテンプレートを同じ名前でをプラグイン側から提供するようにしてみたところ、あっさり report_view.html を差し替えることができた。

*1 なお、InterActが提供している Trac-Ja ではテンプレートそのものに修正を直接加えて、「日付」「日時」が後ろにあるカラム名、つまり例えば「作成日時」といったカラム名でも YYYY/MM/DD形式で表示されるように手が加えてある。

genshiテンプレートの優先順位

同じ名前のテンプレートを提供するプラグインが複数あったら、そっちに負ける可能性があるよね。そこで、tracにおいてgenshiテンプレートがどういう順番で読まれるのか。tracdをデバッガで追いかけてみたところ、優先順位は以下のようになっていた:

  1. プロジェクト固有のtemplatesフォルダ
  2. trac.ini の [inherit]templates_dirで指定したフォルダ
  3. trac本体の/trac/templatesフォルダ
  4. プラグインが提供するテンプレートフォルダ。
    1. プラグイン間の優先順位はエントリポイント名順。
    2. プラグイン内の優先順位はインポート順、定義順。

つまり。trac本体の/trac/ticket/templates/フォルダはtrac.ticket.web_ui.TicketModule が提供しているので、アルファベット順で若い名前のプラグインが提供しているテンプレートが優先されることになる。今回差し替えたかった report_view.html は /trac/ticket/templates にあったので、プラグインで割り込むことができた。

テンプレートを置き換えるんじゃなくて、動的に書き換えることを考える。

次に考えることのメモ。ITemplateStreamFilterを使えばいいんじゃないか。これも、同じURLをどういう順番でフィルタすることになるかを考える必要がある。でも py:when の test= を書き換えるのはむずかしいかもなぁ。

本日のツッコミ(全1件) [ツッコミを入れる]

matobaa [ツッコミのテスト]


2011-09-27 [長年日記]

トラブルシューティング中

久々に。apache reverse proxy + apache という構成で、その間でのネゴに失敗するようで、表が 502 Bad Gateway を返す、というトラブル。必ず発生するわけではないところが厄介。

tcpdump -w でダンプをとりつつ、再発させるリクエストをがんがん投げ込んでみて、なにに失敗しているかを調査してみている。まだ突き止められていない。

CLOSE_WAIT がぞろぞろ出てる。これが原因か? それとも 502 Bad Gateway の結果か? なんで TCPスタックの整合性が取れなくなってるのか不明。ひきつづき追求中。


2011-09-25 [長年日記]

CentOSで openldapをビルドしてみる

# yum install wget gcc

; get dependencies

# yum install openssl-devel

# yum install db4-devel

; get sources then build

# wget ftp://ftp.dti.ad.jp/pub/net/OpenLDAP/openldap-release/openldap-2.4.26.tgz

# tar xzf openldap-2.4.26.tgz

# cd openldap-2.4.26/

# ./configure --with-tls=openssl --enable-dynamic

# make depend

# make

# make test

# make install

既定値だと、バイナリが /usr/local/bin、設定ファイルは /usr/local/etc/openldap に入る。

CentOS6だとうまくいくのに

CentOS5だと失敗する。

BerkeleyDB version incompatible with BDB/HDB backends

だって。

ぐぐってみると、CentOS 5 に入ってる BerkeleyDBは4.3で、OpenLDAPは「4.2以降、ただし4.3を除く」なんだそうだ。

めんどくせー。CentOS6でやる。


ツッコミお待ちしております。 半期 四半期 全カテゴリ