新しいアクションの追加はもう少しトリッキーです。というのも optparse が使っている二つのアクションの分類を理解する必要があるからです。
この分類には重複する部分があります。デフォルトの ``store'' アクションには
store
、store_const
、append
、count
などがありますが、
デフォルトの ``typed'' オプションは store
、append
、callback
の三つです。
アクションを追加する際に、以下の Option のクラス属性(全て文字列のリストです) の中の少なくとも一つに付け加えることでそのアクションを分類する必要があります。
ALWAYS_TYPED_ACTIONS
ALWAYS_TYPED_ACTIONS
のリストにあるオプションに、
デフォルト型 string
を割り当てるということだけです。
実際に新しいアクションを実装するには、Option の take_action() メソッドをオーバライドしてそのアクションを認識する場合分けを追加しなければなりません。
例えば、extend
アクションというのを追加してみましょう。このアクションは
標準的な append
アクションと似ていますが、コマンドラインから一つだけ値を
読み取って既存のリストに追加するのではなく、複数の値をコンマ区切りの文字列として
読み取ってそれらで既存のリストを拡張します。すなわち、もし "-names"
が
string
型の extend
オプションだとすると、次のコマンドライン
--names=foo,bar --names blah --names ding,dong
の結果は次のリストになります。
["foo", "bar", "blah", "ding", "dong"]
再び Option のサブクラスを定義します。
class MyOption (Option): ACTIONS = Option.ACTIONS + ("extend",) STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",) TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",) ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",) def take_action(self, action, dest, opt, value, values, parser): if action == "extend": lvalue = value.split(",") values.ensure_value(dest, []).extend(lvalue) else: Option.take_action( self, action, dest, opt, value, values, parser)
注意すべきは次のようなところです。
extend
はコマンドラインの値を予期していると同時にその値をどこかに格納します
ので、STORE_ACTIONS と TYPED_ACTIONS の両方に入ります。
extend
アクションに string
型を割り当てるように
extend
アクションは ALWAYS_TYPED_ACTIONS
にも入れてあります。
values
は optparse_parser.Values クラスのインスタンスであり、
非常に有用な ensure_value() メソッドを提供しています。
ensure_value() は本質的に安全弁付きの getattr() です。
次のように呼び出します。
values.ensure_value(attr, value)
values
に attr
属性が無いか None だった場合に、
ensure_value() は最初に value
をセットし、
それから value
を返します。
この振る舞いは extend
、append
、count
のように、データを変数に
集積し、またその変数がある型 (最初の二つはリスト、最後のは整数) であると期待されるアクション
を作るのにとても使い易いものです。ensure_value() を使えば、
作ったアクションを使うスクリプトはオプションに保存先にデフォルト値をセットすることに
煩わされずに済みます。デフォルトを None にしておけば ensure_value() が
それが必要になったときに適当な値を返してくれます。