###
6.20.5.2 新たなアクションを追加する

アクションの追加は少しだけ厄介です。というのは、`optparse` がアクションを二種類に分類していることを理解しなければならないからです:

"store" アクション
  結果的に `optparse` の OptionValues インスタンスの属性に値を 保存することになるアクションです; このアクションをとるオプションは Option のコンストラクタに 'dest' 属性を指定する必要があります。
"typed" アクション
  コマンドラインから値をとり、それが特定の型か、あるいは特定の型に 変換される文字列になるはずのアクションです。このアクションをとる オプションは Option のコンストラクタに 'type' 属性を指定する必要があります。

デフォルトの ``store'' アクションには、``store''、 ``store_const''、 ``append''、および ``count'' があります。デフォルトの ``typed'' アクションは、``store''、 ``append''、および ``callback'' です。

アクションを追加する際、 アクションが ``store''、``typed''、 どちらでもない、両方である、のいずれか決めなければなりません。 `Option` (または `Option` サブクラス) の3つのクラス属性 がこの決定を制御します:

`ACTIONS`
  すべてのアクションは ACTIONS に文字列で列挙されていなければなりません。

`STORE_ACTIONS`
  "store" 系のアクションはここに列挙されていなければなりません。

`TYPED_ACTIONS`
  "typed" 系のアクションはここに列挙されていなければなりません。

自前の新たなアクションを実際に実装するには、`Option` の `take_action()` メソッドを上書きして、自前のアクションを 認識する場合を追加しなければなりません。

例として、``extend'' アクションを追加してみましょう。このアクションは 標準の ``append'' アクションに似ていますが、コマンドラインから単一の 値をとって既存のリストに追加する代わりに、 ``extend'' では コンマで区切られた単一の文字列から複数の値をとり、既存のリストに 追加します。すなわち、--names が ``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",)

        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` の両方に相当します。

- `MyOption.take_action()` ではこの新しいアクションだけを 実装し、標準の`Option.take_action()` で `optparse` アクションへ 制御を戻します。

- values は `Values` クラスのインスタンスで、 非常に便利な `ensure_value()` メソッドを提供しています。 `ensure_value()` は実質的には安全値 (safety value) のある `getattr()` です; このメソッドは以下のようにして 呼び出されます:

      values.ensure_value(attr, value)

values の `attr` 属性が存在しないか、または None の 場合、`ensure_value()` は属性の値を value に設定して から value を返します。この機能は ``extend''、 ``append''、 および ``count'' で便利です。というのは、これらのアクションは すべて、データを変数に蓄積し、その変数が特定の型であるはず (最初の二つはリストで、最後の一つは整数) だからです。 `ensure_value()` を使うことで、アクションを使う スクリプトにおいて、オプションの目的変数にデフォルトの値を設定 するよう配慮しなくてよくなります; こうした目的変数はデフォルトを None にしておいてよく、`ensure_value()` が必要なときに 正しい値にするよう面倒を見ることになります。