python jedi:如何检索实例的方法?

时间:2016-06-07 18:04:47

标签: python autocomplete python-jedi

我构建了简单的文本编辑器,其中包含一些用于屏幕阅读软件的辅助功能。 我使用Python for .NET(pythonnet)来显示包含富文本框的表单。 当用户在一段时间后按Tab键时,它会弹出一个上下文菜单,其中包含所选元素的完成。 好吧,它适用于Python对象,但它不能与.net活动对象一起使用,没有解决这个问题的方法。 现在,我想构建一个TreeView对象,其中包含模块I&m;编辑的所有名称和定义。

所以,例如我输入:

import sys
import os
lst = list()

...等 如果我使用我的源代码的jedi.names,我可以检索os,sys和lst。 对于每个名称,我想要检索子定义,例如sys和os模块的函数,以及lst的方法。 我无法通过jedi找到一种方法:

names = jedi.names(MySource)
names[0].defined_names() # works for sys
names[1].defined_names() # works for os
names[2].defined_names() # doesn't work for lst instance of list().

有什么建议吗? 我试图使用越来越多的编辑器,但可访问性支持非常糟糕......

1 个答案:

答案 0 :(得分:7)

这看起来像一个错误,jedi.evaluate.representation.Instance.__getattr__()错误地阻止了.names_dict的评估。我在jedi存储库中添加了pull request来解决这个问题。与此同时,您可以添加' names_dict'到jedi/evaluate/representation.py副本中的whitelist in Instance.__getattr__(),或使用下面的代码自动为当前会话修补此方法。

import jedi

def patch_jedi():

    __old__getattr__ = jedi.evaluate.representation.Instance.__getattr__

    def __patched__getattr__(self, name):
        if name == 'names_dict':
            # do a simplified version of __old__getattr__, bypassing the name check
            return getattr(self.base, name)
        else:
            # use standard behavior
            return __old__getattr__(self, name)

    # test whether jedi has been updated to avoid the Instance.defined_names() bug
    try:
        jedi.names("lst = list()")[0].defined_names()
    except AttributeError as e:
        if e.args[0].startswith("Instance ") and e.args[0].endswith("Don't touch this (names_dict)!"):
            # patch jedi to avoid this error
            print "patching jedi"
            jedi.evaluate.representation.Instance.__getattr__ = __patched__getattr__
        else:
            # something else strange is going on
            raise

patch_jedi()
print jedi.names("lst = list()")[0].defined_names()
# or: print jedi.Script("lst = list()").goto_definitions()[0].defined_names()

我应该注意,我不熟悉jedi,所以我不知道defined_names()是否适用于创建实例的定义。上面的代码不会修复像jedi.names("lst = []")[0].defined_names()这样的引用,并且没有明显的补丁来做到这一点。因此,可能会有一些我不了解的更深层次的事情。希望开发人员能够帮助设置这一点以响应该拉取请求。