Скрыть устаревшие методы от завершения вкладки - PullRequest
3 голосов
/ 28 марта 2010

Я хотел бы контролировать, какие методы появляются, когда пользователь использует завершение табуляции для пользовательского объекта в ipython - в частности, я хочу скрыть функции, которые я устарел. Я все еще хочу, чтобы эти методы вызывались, но я не хочу, чтобы пользователи видели их и начинали использовать их, если они осматривают объект. Это возможно?

Ответы [ 4 ]

4 голосов
/ 06 апреля 2010

Частичный ответ для вас. Я опубликую пример кода, а затем объясню, почему это только частичный ответ.
Код:

class hidden(object): # or whatever its parent class is
    def __init__(self):
        self.value = 4
    def show(self):
        return self.value
    def change(self,n):
        self.value = n
    def __getattr__(self, attrname):
        # put the dep'd method/attribute names here
        deprecateds = ['dep_show','dep_change']
        if attrname in deprecateds:
            print("These aren't the methods you're looking for.")
            def dep_change(n):
                self.value = n
            def dep_show():
                return self.value
            return eval(attrname)
        else:
            raise AttributeError, attrname

Итак, теперь предостережение: они не методы (обратите внимание на отсутствие self в качестве первой переменной). Если вам нужно, чтобы ваши пользователи (или ваш код) могли вызывать im_class, im_func или im_self для любого из ваших устаревших методов, этот хак не будет работать. Кроме того, я уверен, что производительность снизится, потому что вы определяете каждую функцию dep'd внутри __getattr__. Это не повлияет на другие ваши поиски атрибутов (если бы я поместил их в __getattribute__, это было бы другое дело), ​​но это замедлит доступ к этим устаревшим методам. Это можно (в значительной степени, но не полностью) отрицать, помещая каждое определение функции в свое собственное блок if, вместо того, чтобы выполнять проверку членства в списке, но, в зависимости от того, насколько велика ваша функция, это может быть действительно раздражающим для поддержки.

ОБНОВЛЕНИЕ:

1) Если вы хотите создать методы устаревших функций (и вы это делаете), просто используйте

import types
return types.MethodType(eval(attrname), self)

вместо

return eval(attrname)

в приведенном выше фрагменте и добавьте self в качестве первого аргумента функции defs. Он превращает их в методы экземпляра (так что вы можете использовать im_class, im_func и im_self для вашего сердца).

2) Если хук __getattr__ вас не заинтриговал, есть еще один вариант (который я знаю) (albiet, со своими собственными предостережениями, и мы к ним вернемся): поместите определения устаревших функций внутри __init__, и скрыть их с помощью пользовательского __dir__. Вот как будет выглядеть приведенный выше код, сделанный таким образом:

class hidden(object):
    def __init__(self):
        self.value = 4
        from types import MethodType
        def dep_show(self):
            return self.value
        self.__setattr__('dep_show', MethodType(dep_show, self))
        def dep_change(self, n):
            self.value = n
        self.__setattr__('dep_change', MethodType(dep_change, self))
    def show(self):
        return self.value
    def change(self, n):
        self.value = n
    def __dir__(self):
        heritage = dir(super(self.__class__, self)) # inherited attributes
        hide = ['dep_show', 'dep_change']
        show = [k for k in self.__class__.__dict__.keys() + self.__dict__.keys() if not k in heritage + private]
        return sorted(heritage + show)

Преимущество в том, что вы не определяете функции заново при каждом поиске, что ускоряет вашу работу. Недостатком здесь является то, что поскольку вы не определяете функции заново при каждом поиске, они должны «сохраняться» (если хотите). Таким образом, хотя пользовательский метод __dir__ скрывает ваши устаревшие от dir(hiddenObj) и, следовательно, завершение вкладки IPython, они все еще существуют в атрибуте __dict__ экземпляра, где пользователи могут их обнаружить.

0 голосов
/ 10 апреля 2010

Похоже, существует специальный магический метод для интроспекции, который вызывается функцией dir (): __dir__(). Разве это не то, что вы ищете?

0 голосов
/ 09 апреля 2010

О механизме завершения в IPython, это задокументировано здесь:

http://ipython.scipy.org/doc/manual/html/api/generated/IPython.core.completer.html#ipcompleter

Но действительно интересный пример для вас - завершитель черт, который делает именно то, что вы хотите: он скрывает некоторые методы (на основе их имен) от автозаполнения.

Вот код:

http://projects.scipy.org/ipython/ipython/browser/ipython/trunk/IPython/Extensions/ipy_traits_completer.py

0 голосов
/ 28 марта 2010

DeprecationWarning не выдается до тех пор, пока метод не будет вызван, поэтому вам нужно иметь отдельный атрибут в классе, который хранит имена устаревших методов, а затем проверить это, прежде чем предлагать завершение.

В качестве альтернативы, вы можете пройти AST для метода, ищущего DeprecationWarning, но это не удастся, если либо класс определен в C, либо если метод может испускать DeprecationWarning на основе тип или значение аргументов.

...