complete

昨日dict.setdefault()について id:bonlife さんに教えてもらった(Thanx!)のだけど、あの後リファレンスくらいちゃんと読もうと猛反省。

最近メイン環境をLeopardに移しました。これのデフォルト/usr/bin/python(2.5.1)を使おうと思ってるので、まずはこいつの環境整備しとこう。と、以下を参考に.inputrc に [Tab]を追加してTAB補完ONに。。。
Python チュートリアル - A. 対話入力編集とヒストリ置換
んで、いきなり躓く。動かん‥ Linuxのほうではうまくいったのに。

ググってみたらいきなり見つけました。
IPython tab completion fix on Leopard
IPythonの話ですが普通のpythonでもおんなじでした。

import readline, rlcompleter
readline.parse_and_bind('bind ^I rl_complete')

をPYTHONSTARTUPのファイルに入れて補完ができるようになりました。かなり快適ー*1

しかし、osxautomationのページを読む限り、workaroundとなってます。実はなんかアップデートしたらおKな話?

しかも、なんかこれで補完すると

>>> d.[tab]
    :
    :
d.__init__          d.__iter__          d.__iter__          d.__le__            
d.__le__            d.__len__           d.__len__           d.__lt__            
d.__lt__            d.__ne__            d.__ne__            d.__new__           
d.__new__           d.__new__           d.__reduce__        d.__reduce__        
d.__reduce__        d.__reduce_ex__     d.__reduce_ex__     d.__reduce_ex__     
d.__repr__          d.__repr__          d.__repr__          d.__setattr__       
    :

のように複数表示されるものとかが出てきます。なんだかよくわかんない。
というか自前でコンパイルして入れ直すべきなんだろか? IPythonにするべき? あ〜も〜わかんないことだらけだ。精進精進。

追記:

原因判明。

pythonのrlcompleter.pyのattr_matches()をみると*2

    def attr_matches(self, text):
        words = dir(object)             # (1)
        if hasattr(object,'__class__'):
            words.append('__class__')
            words = words + get_class_members(object.__class__) #(2)
              :
def get_class_members(klass):
    ret = dir(klass)
    if hasattr(klass,'__bases__'):
        for base in klass.__bases__:
            ret = ret + get_class_members(base) #(3)

となっていて (1) 本人オブジェクトの属性 + (2) クラス属性 + (3) 基底クラスの属性(recursive) と全部足し込んでいます。そいで何個も見えていた訳ですね。だから

class A1(object):
  pass

class A2(A1):
  pass

class A3(A2):
  pass

class A4(A3):
  pass

class A5(A4):
  pass

とかしといて

>>> obj = A5()
>>> obj.[TAB]
    :
obj.__new__           obj.__new__           obj.__reduce__        
obj.__reduce__        obj.__reduce__        obj.__reduce__        
obj.__reduce__        obj.__reduce__        obj.__reduce__        
obj.__reduce_ex__     obj.__reduce_ex__     obj.__reduce_ex__     
obj.__reduce_ex__     obj.__reduce_ex__     obj.__reduce_ex__     
obj.__reduce_ex__     obj.__repr__          obj.__repr__          
obj.__repr__          obj.__repr__          obj.__repr__          
obj.__repr__          obj.__repr__          obj.__setattr__       
obj.__setattr__       obj.__setattr__       obj.__setattr__       

あわわわわわ。まあ考えてみたら当たり前ですね。

ちなみにworkaround云々については、setup.pyに

            # MacOSX 10.4 has a broken readline. Don't try to build
            # the readline module unless the user has installed a fixed
            # readline package

とか書いてありました。Leopardでもなおってないつーことでしょうか。
というわけで一番の正解はコンパイルし直しですね。普段からhousekeepingは欠かさないようにしないと、結局節句働きになってしまうという典型例でした。

*1:いままでいちいち dir()の内容を filterしたりとかアホウなことをしてたのです

*2:本当はModule/readline.cからソースの迷宮に迷い込んでぐるぐる回ったあげくに正解にたどり着いた、というのはナイショ。おかげでreadlineの勉強になりました