tracプラグインの書き方

trac(0.12)のプラグインを書いてみました。以下のファイルをプロジェクトディレクトリにあるpluginsにおいたら設定無しに動きます。プラグインを普通のpythonファイルで書くときにしないといけないことは、revisionを書くことと、最低1つtrac.core.Componentを継承したclass(今回の場合HelloTimelineがそれ)を作ることです。tracははじめにpluginesなどのディレクトリからプラグインを探してロードします。そのときclassが読み込まれるので、Componentの__metaclass__として指定されているComponentMetaの__new__が動いて、tracの管理下に置かれてます。管理下におかれたクラスは実装しているinterfaceの種類に応じて呼び出されるようになっています。

プラグインはそのロードのされ方以外は実装上コアとなるtimeline, ticket, wikiなどの機能と同じ方法で作られています。なので、tracは外から見ると1つのまとまった機能を提供しますが、中身はバラバラになっていて、機能を除いたり、追加したりすることが簡単にできるようになっているようです。

[このプラグインはtimeline上の現在の時刻のところにtitleがTITLE,リンクがtimeline#url,descriptionがDESCRIPTIONが書きだされるだけのものです。]

from trac.core import *
from trac.timeline.api import ITimelineEventProvider
from genshi.builder import tag
from datetime import datetime
from trac.util.datefmt import utc
from trac.util.translation import _, tag_

revision = "$Rev: 0001 $"
#url = "$URL: https://domain/plugins/modulename.py $"

class HelloTimeline(Component):
    implements(ITimelineEventProvider)
    # ITimelineEventProvider methods
    def get_timeline_filters(self, req):
        #raise Exception, req.perm
        yield ('helloworld', _('hello opened and closed'))
    def get_timeline_events(self, req, start, stop, filters):
        author = 'author'
        yield ('helloworld', datetime.now(utc), author, ('#url', 'DESCRIPTION'))
    def render_timeline_event(self, context, field, event):
        url, desc = event[3]
        if field == 'url':
            return url
        elif field == 'title':
            return tag_('%(page)s created', page=tag.em('TITLE'))
        elif field == 'description':
          return tag(tag.a(href='###', title='Foo', accesskey=None)(desc))