将来、プラグインの作成方法が変更するかもしれません
プラグインはPythonプログラムです。特殊な機能を使わない限りhabuに依存しないので単体テストが簡単にできます(ただし、Twistedに深く依存すると単体テストはかんばってね)。また、habuとは関係なく動作させることもできます。
habuの配布物に含まれているhabu/filter/head.pyを例に説明します。次のコードは、head.pyの全文です。
各プラグインモジュールは必ずcreate(config, environ)関数を実装する必要があります。habuがモジュールをロードした後にcreate関数を実行して、インスタンス化します。configはプラグイン固有の設定の辞書です。environはhabuの環境全体にわたる設定情報の辞書です。environは設定ファイルのglobalセクションに対応します。create関数はexecute(content)メソッドを実装したオブジェクトを返します。executeメソッドが定義されたオブジェクトであれば、モジュールでもクラスインスタンスでも構いません。
create関数の名前は変えるかもしれません。 いや、多分もうちょっとかっこいい名前に変えるはず。
Headクラスは通常、コンストラクタにconfig, environを引数に指定した形で実装します。必要に応じてクラスメンバーとして保存します。ここでは、設定のstartとendを保持しています。
プラグインが実行されるときにはexecute(context)メソッドがコールされます。contextは入力データです。contextの詳細は後述します。ここでは、context["entries"]のリストの要素をstartからendまで抽出してcontextのオブジェクトに設定し直しています。返り値は、次のモジュールのexecuteメソッドの引数になります。
executeメソッドの返り値は、contextの辞書かtwisted.internet.defer.Deferredオブジェクト、または、それらのリストです。Deferredオブジェクトを返す場合は、非同期処理でデータを加工してからプラグインのチェーンを再開する場合に使用します。
基本的にはexecuteでcontextのデータを加工して、context自体を返すだけです。
executeメソッドの引き数に渡されるcontextはfeedparserがパースしたオブジェクトです。subscriptionではcontextは通常,Noneです。
contextは辞書です。contextはentriesをキーとしてリストを辞書の要素として持ちます。それ以外の情報は現在のhabuでは無視されます。
context["entries"]にRSSの各エントリが保存されます。各エントリは辞書です。エントリには次のキーと値が設定されています。
キー | タイプ | 意味 |
author | 文字列 | 作成者(オプション) |
author_detail | 辞書 | 作成者の詳細。 nameにauthorと同じ値。emailとかにメールアドレスが設定されるかも |
link | 文字列 | エントリへのアクセスするユニークな文字列(URL) |
update | 文字列 | 最終更新日の文字列表記 |
updated_parsed | タプル | 最終更新日の日時のタプル表記 |
title | 文字列 | エントリのタイトル |
summary | 文字列 | エントリの本文(description) |
summary_detail | 辞書 | summaryの詳細の辞書 typeにmimeタイプ,valueにhtmlやtextでの本文など |
上記以外のフィールドもありますが,未使用です。上記のフィールド以外にもプラグインが独自にデータを追加できます。
モジュールの名前とモジュールへのパスは,一意であり、かつ、Python的にvalidでなければなりません。モジュールへのパスに上記以外の制約はありません。識別用にパイプラインの開始はsubscription、RSSの加工はfilter、出力はpublisherを推奨します。
モジュールはhabuが各パイプラインを実行する直前にロードします。モジュールは,habuのプロセス全体でユニークなります。ロード後にモジュールはリロードされることはありません。モジュールは,設定ファイルのmoduleに指定した名前で区別されます。その後,モジュールのcreate関数がコールされて,インスタンス化されます。同一のパイプラインで同じモジュールを複数指定している場合は,指定した数だけインスタンス化されます。インスタンス化されたオブジェクトは,パイプラインの実行期間中生きています。そのあとは,いつ死ぬかはPythonインタープリタに聞いてください。
パイプラインのモジュール(オブジェクト)のチェーンです。通常、一つのパイプラインは一つのチェーンです。executeがリストを返すと、チェーンは複数に分岐して同時並行でその後のそのあとのフィルタ処理を順次実行します。複数に分岐したチェーンはfilter.joinによってまた、一つのチェーンに集約できます。ネットワーク上のデータを取得する場合など、複数のチェーンに分割して、その後のフィルタ処理の実行タイミングをずらすことで、CPUの負荷をおさえることができます。また、データをふるい落とす処理をする場合など、若干メモリ使用量をおさえられます(ほとんど誤差の範囲なので気にしなくてもいいかもしれません)。
Twistedの使い方は、「最新Pythonエクスプローラ 」をご覧ください。