Vim 的全能补全失败,并显示“from” Python 中的导入

发布于 2024-09-08 19:16:58 字数 1468 浏览 11 评论 0原文

当存在“from”导入而不是普通导入时,Python 的 Omnicompletion 似乎会失败。 例如,如果我有这两个文件:

Test.py:

class Test:
    def method(self):
        pass

main.py:

from Test import Test

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

如果我尝试激活 self.x 的omnicompletion... 它会显示“找不到模式”。 但是,如果我将 import 语句更改为:

import Test

并将 self.x 声明更改为:

self.x = Test.Test()

那么我就可以按预期使用omnicompletion(例如,它建议“方法”)。

我正在使用 Vim 7.2.245 和 Python 代码完成的默认插件 (pythoncomplete)。 我应该设置一些变量吗?或者这种行为是预期的吗?

更新

根据Jared的回答,我偶然发现了一些东西:

Omnicompletion 不适用于此:

from StringIO import StringIO

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

s = Test()

但适用于此:

from StringIO import StringIO

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

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

唯一的区别是 x 的重新声明(实际上,如果我删除 __init__ 中的声明)。

我再次测试了我的示例,我认为问题不在于“from”导入,而是在另一个类中使用导入的类。 如果我将文件 main.py 更改为:

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>

第一次尝试使用omnicompletion 失败,但第二次尝试正常。 是的,看起来像是插件中的一个错误:)

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 :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

殊姿 2024-09-15 19:16:58

更新:哦,所以我检查了你的例子,我得到了完成,

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

但没有

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

......我要做一些挖掘

更新2: 博士的复仇.Strangelove

并且...这就是奇怪的地方。

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

完成。但这

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

你看出区别了吗? 语法上什么都没有——只是一点空白

但是它破坏了完整性。所以肯定在某个地方存在解析错误(为什么他们不只使用 ast 模块,我不知道......)

[更新结束]

乍一看,我无法重现你的问题;这是我的测试文件:

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

我完成了。现在,我知道这不完全是你的情况,但它表明 pythoncomplete 知道“from”。

现在是更深入的例子:

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

并且......完成!您可以尝试该示例来看看它是否适用于您的内置模块吗?如果是这样的话,您可能应该检查路径...

如果它仍然不起作用,那么您就需要进行一些挖掘周围,​​查看 pythoncomplete.vim 的第 #555 行 [在我的 ubuntu 机器上的 /usr/share/vim/vim72/autoload/pythoncomplete.vim]:

            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                                   

如您所见,这就是它处理的地方from 语句。

干杯

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文