[IPython-User] Tab completion doesn't work on class/instance where __getattr__ has been overridden

Jeremy Conlin jlconlin@gmail....
Wed Mar 2 08:28:35 CST 2011


On Tue, Mar 1, 2011 at 4:43 PM, Robert Kern <robert.kern@gmail.com> wrote:
> On 3/1/11 1:58 PM, Jeremy Conlin wrote:
>> I have a class (subclassed from list) where I have overwridden the
>> __getattr__ method as:
>>
>>      def __getattr__(self, name):
>>          if name.startswith("__"): raise AttributeError
>>          def _multiplexed(*args, **kwargs):
>>              return [getattr(R, name)(*args, **kwargs) for R in self]
>>          return _multiplexed
>>
>> Now when I try to use tab completion, iPython just beeps at me and
>> doesn't complete anything.  If I remove this method from my class, I
>> can do tab completion.
>>
>> Does the tab completion use __getattr__ somewhere?  Can I add
>> something to my definition to make tab completion work in iPython?
>
> It works for me with the HEAD of IPython. What version are you using?
>
> [~]
> |8> class A(list):
> ..>     def __getattr__(self, name):
> ..>         if name.startswith('__'): raise AttributeError
> ..>         return 10
> ..>
>
> [~]
> |9> a = A()
>
> [~]
> |10> a.
> a.append   a.extend   a.insert   a.remove   a.sort
> a.count    a.index    a.pop      a.reverse

I am using iPython 0.10.1 with Python 2.7.1.  I have created a minimal
example which is copied below.  On my system, iPython does not tab
complete the instance of myList.

Jeremy


class myList(list):

    def __init__(self, items):

        super(myList, self).__init__(items)
        self.name = 'myList'


    def __getattr__(self, name):
        if name.startswith("__"): raise AttributeError
        def _multiplexed(*args, **kwargs):
            return [getattr(R, name)(*args, **kwargs) for R in self]
        return _multiplexed

    def __dir__(self):
        heritage = dir(super(self.__class__, self)) # inherited attributes
        return sorted(heritage + self.__class__.__dict__.keys() +
                self.__dict__.keys())

    def __getslice__(self, begin, end):
        return self.__getitem__(slice(begin, end))

    def __getitem__(self, index):
        if isinstance(index, slice):
            return self.__class__([self[x] for x in range(
                *index.indices( len(self) ) ) ] )
        elif isinstance(index, int):
            return super(myList, self).__getitem__(index)
        else:
            return self[self.index(index)]


if __name__ == "__main__":
    import string
    import random
    print("\nI'm tesing out custom slicing.\n")

    N = 10
    L = myList([random.choice(string.ascii_letters) for L in range(N)])

    Lupper = L.upper()


More information about the IPython-User mailing list