Python jedi: как получить методы экземпляров?

Я построил простой текстовый редактор с некоторой функцией доступности для программного обеспечения для чтения экрана. Я использую Python для .NET(pythonnet), чтобы показать форму, содержащую богатое текстовое поле. Когда пользователь нажимает вкладку после периода, она всплывает в контекстном меню с пополнениями для выбранного элемента. Хорошо, он отлично работает с объектами Python, но он не работает с живыми объектами .net, нет решения этой проблемы. Теперь я хочу создать объект TreeView со всеми именами и определениями модуля, который я редактирую.

Итак, например, я печатаю:

import sys
import os
lst = list()

и т.д.... Если я использую jedi.names моего источника, я могу получить os, sys и lst. Для каждого имени я хочу получить вспомогательные определения, такие как функции для модуля sys и os, а также методы для lst. Я не могу найти способ сделать это с помощью джедая:

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

Это выглядит как ошибка, где jedi.evaluate.representation.Instance.__getattr__() ошибочно блокирует оценку .names_dict. Я добавил pull request в репозиторий jedi, чтобы исправить это. В то же время вы можете добавить 'names_dict' в белый список в Instance.__getattr__() в своей копии jedi/evaluate/representation.py или использовать код ниже, чтобы автоматически исправить этот метод для текущего сеанса.

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(), и нет очевидного патча для этого. Так что может быть что-то более глубокое, о чем я не знаю. Надеюсь, разработчик поможет установить это прямо в ответ на этот запрос на растяжение.