从制表符完成中隐藏已弃用的方法

时间:2010-03-28 00:35:06

标签: python ipython

我想控制当用户在ipython中的自定义对象上使用制表符完成时出现哪些方法 - 特别是,我想隐藏我已弃用的​​函数。我仍然希望这些方法可以调用,但我不希望用户看到它们并在检查对象时开始使用它们。这是可能的吗?

4 个答案:

答案 0 :(得分:4)

部分答案。我将发布示例代码,然后解释为什么它只是部分答案 代码:

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

所以现在需要注意的是:它们不是方法(注意缺少自我作为第一个变量)。如果您需要您的用户(或您的代码)能够在任何已弃用的方法上调用im_class,im_func或im_self,那么这个hack将无法工作。此外,我非常确定会因为你在__getattr__内定义每个dep'd函数而受到性能影响。这不会影响您的其他属性查找(如果我将它们放在__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的tab-completion,但它们仍然存在于实例的__dict__属性中,用户可以在其中发现它们。

答案 1 :(得分:0)

在调用方法之前不会发出DeprecationWarning,因此您必须在类上有一个单独的属性来存储已弃用方法的名称,然后在建议完成之前检查它。

或者,你可以在寻找DeprecationWarning的方法中使用AST,但是如果在C中定义了类,或者方法可能发出{{} 1}}基于参数的类型或值。

答案 2 :(得分:0)

关于IPython中的完成机制,它在此处记录:

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

但是一个非常有趣的例子是traits completer,它正是你想要做的:它隐藏了一些自动完成的方法(基于它们的名字)。

以下是代码:

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

答案 3 :(得分:0)

似乎有一个特殊的magic method用于由dir()调用的内省:__dir__()。这不是你想要的吗?