views:

182

answers:

1

Omnicompletion for Python seems to fail when there is a "from" import instead of a normal one. For example, if I have these two files:

Test.py:

class Test:
    def method(self):
        pass

main.py:

from Test import Test

class Test2:
    def __init__(self):
       self.x = Test()

If I try to activate omnicompletion for self.x... it says "Pattern not found". However, if I change the import statement to:

import Test

and the self.x declaration to:

self.x = Test.Test()

then I'm able to use omnicompletion as expected (it suggests "method", for example).

I'm using Vim 7.2.245 and the default plugin for Python code completion (pythoncomplete). Should I set some variable? Or is this behavior expected?

Update:

Based on Jared's answer, I found out something by accident:

Omnicompletion doesn't work on this:

from StringIO import StringIO

class Test:
    def __init__(self):
        self.x = StringIO()
        self.x.<C-x><C-o>

s = Test()

But works on this:

from StringIO import StringIO

class Test:
    def __init__(self):
        self.x = StringIO()
        self.x.<C-x><C-o>

s = Test()
s.x = StringIO()

The only difference is the redeclaration of x (actually, it also works if I remove the declaration inside __init__).

I tested my example again, and I think the problem is not the "from" import, but the use of the imported class inside another class. If I change the file main.py to:

from Test import Test

class Test2:
    def __init__(self):
       self.x = Test()
       self.x.<C-x><C-o>

y = Test()
y.<C-x><C-o>

The first attempt to use omnicompletion fails, but the second works fine. So yep, looks like a bug in the plugin :)

+2  A: 

update: ooh, so I checked your example, and I get completion for

x = Test()
x.<C-x><C-o>

but not

o = object()
o.x = Test()
o.x.<C-x><C-o>

...I'm gonna do some digging

update 2: revenge of Dr. Strangelove

and...this is where it get's weird.

from StringIO import StringIO
class M:
    pass
s = M()
s.x = StringIO()
s.x.<C-x><C-o>

completes. but this

from StringIO import StringIO
class M: pass
s = M()
s.x = StringIO()
s.x.<C-x><C-o>

Did you catch the difference? nothing syntactically -- just a little whitespace

And yet it breaks completion. So there's definitely a parsing bug in there somewhere (why they don't just use the ast module, I have no idea...)

[end of updates]

On first blush, I can't reproduce your problem; here's my test file:

from os import path
path.<C-x><C-o>

and I get completion. Now, I know it's not exactly your situation, but it shows that pythoncomplete knows about 'from'.

And now the more in-depth example:

from StringIO import StringIO
s = StringIO()
s.<C-x><C-o>

And...completion! Could you try that example to see if it works with builtin modules for you? If that's the case, you should probably check paths...

If it still doesnt work, and you're up for some digging around, check out line #555 of pythoncomplete.vim [at /usr/share/vim/vim72/autoload/pythoncomplete.vim on my ubuntu machine]:

            elif token == 'from':                                    
                mod, token = self._parsedotname()                    
                if not mod or token != "import":                     
                    print "from: syntax error..."                    
                    continue                                         
                names = self._parseimportlist()                      
                for name, alias in names:                            
                    loc = "from %s import %s" % (mod,name)           
                    if len(alias) > 0: loc += " as %s" % alias       
                    self.scope.local(loc)                            
                freshscope = False                                   

as you can see, this is where it handles from statements.

Cheers

Jared Forsyth