試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

PyGObjectでgobject.GObjectクラスを継承してGObjectプロパティを用いる(前半)

PyGObjectにおいて、gobjectモジュールのクラスGObjectを継承し、適切な設定をすることにより、Python標準のプロパティよりも高度な機能を持ったGObjectプロパティを用いることができる。
動的型付けな言語であるPythonにおいて値の書き込み時の型のチェックができることはメリットとして大きい他、受け付ける型によっては値の範囲もチェックさせることもできる他、書き込み専用やオブジェクト初期化時にのみ書き込み可能などのアクセス制御も設定できる。
ただし、GLibのライブラリに加えてPyGObjectのPythonモジュールパッケージも追加で必要となり、GNU/Linuxでは「python-gobject」や「pygobject」といったパッケージ名で簡単にインストールできるが、特にWindowsでは導入が面倒になるかもしれない。

2010年2月末時点のWindows向けパッケージは、GLibが2.22系,PyGObjectが2.20系(Python 2.6用)となっている。
gobject.GObjectクラスの継承に関する情報は非常に少なく、リファレンスに詳しい説明が書かれていない部分も多いこともあり、(後半も含めて)誤った内容を含んでいるかもしれない。

GObjectプロパティの定義

gobject.GObjectクラスを継承したクラスにおいて「__gproperties__」という名前の辞書をメンバとして用意する。
辞書はプロパティ名とその設定のタプルから成り、タプルの要素はデータの型によって異なるが、一般的には

データの型,ニックネーム,説明,(範囲,)初期値,アクセス制御フラグ

となり、例としては

__gproperties__ = \
{
  'a' : (gobject.TYPE_INT,          # 型
         'nick name of a',          # ニックネーム
         'description of a',        # 説明
         100,                       # 受け付ける最小値
         99999,                     # 受け付ける最大値
         100,                       # 初期値(上の範囲内におさめる)
                                    # 実際の初期値でなくてもよい
                                    # (コンストラクタ引数をすぐ入れる場合など)
         gobject.PARAM_READWRITE),  # アクセス制御
}

のようになる。
初期値については、コンストラクタ引数から受け取ってすぐに値を変更したりするのであれば、受け付ける範囲内の任意の値でよい。
型の指定に用いる値は
http://www.pygtk.org/articles/subclassing-gobject/sub-classing-gobject-in-python.htm
の「This is the list of the possible types:」以下に列挙されている。

アクセス制御

タプルの最後の要素を下のように指定する。

  • 読み込みのみ: gobject.PARAM_READABLE
  • 書き込みのみ: gobject.PARAM_WRITABLE
  • 常に読み書き可: gobject.PARAM_READWRITE
  • 初期化時のみ書き込み可/常に読み込み可: gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY

値の出し入れ

  • do_get_property(),do_set_property()という名前のメンバ関数をそれぞれ用意する。これらはプロパティの読み書き時に呼び出される
  • それぞれ、最初の引数には読み書きするプロパティに関する情報を持ったオブジェクトが渡され、メンバnameでプロパティの名前が得られる。do_set_property()はその後ろに(クラスの外でプロパティに代入された)値を引数として受け取る
  • do_get_property()は指定されたプロパティの値をreturn文で返すようにする
  • gobject.GObjectクラスにはPythonの辞書のようにキー文字列を用いてデータを出し入れするset_data(),get_data()といったメンバ関数が存在し、プロパティ名とデータとを関連付けて管理できる
  • プロパティ名,値の範囲,アクセス権などのチェックはdo_get_property(),do_set_property()とは別の部分で自動的に行われるため、これらの中でチェックをする必要はない

形としては、以下のメンバ関数の記述を含めるようにすればよいことになる。

def do_get_property(self, property):
  return self.get_data(property.name)
def do_set_property(self, property, value):
  self.set_data(property.name, value)

(2010/3/15)この形以外にも、プロパティ名によって処理を振り分けるやり方があり、メンバの値をそのままやりとりするプロパティ以外のときなどに使える。

def do_get_property(self, property):
  if property.name == '[プロパティ名1]':
    if ... :
      return [値1]
    elif ... :
      return [値2]
    ...
  elif property.name == '[プロパティ名2]':
    ...

  ...

  else:
    return self.get_data(property.name)

(「PyGObjectで gobject.GObjectクラスを継承してGObjectプロパティを用いる(後半)」に続く)

関連記事:

参考URL:

使用したバージョン:

  • Python 2.6.4
  • PyGObject 2.20.0
  • GLib 2.22.2