如何通过astroid使pylint识别变量

时间:2016-07-10 14:32:45

标签: python django pylint

我正在努力教授" pylint识别成员函数,我的场景可以简化为以下内容:

主要模块:a.py

from plugins import plu

class FooClass(object):
    def bar(self):
        self.plu.foo("asdasd")

if __name__ == '__main__':
    a = FooClass()
    for plugin_name, plugin in plu.plugins.items():
       setattr(a, plugin_name, plugin())
 a.bar()

插件文件夹文件plu.py:

plugins = {}
class Plugin(object):
   def foo(self, arg):
       print("bar %s" % arg)

plugins['plu'] = Plugin

插件注册自己的想法和其他一些方法"介绍"它们在FooClass对象上。

a.py的输出是:

bar asdasd

(如预期的那样)

运行pylint -E a.py会产生以下错误:

pylint  -E a.py 
************* Module a
E:  5, 8: Instance of 'FooClass' has no 'plu' member (no-member)

我曾尝试编写以下pylint-plugin:

import astroid
from astroid import nodes


def transform_test_class(mod):
   if mod.name != 'a':
       return
   foo_cls = mod.lookup('FooClass')[1]
   plugin_cls_def =   astroid.MANAGER.ast_from_module_name('plugins.plu')
   foo_cls[0].locals['plu'] = plugin_cls_def.lookup('Plugin')[1]


def register(linter):
   astroid.MANAGER.register_transform(nodes.Module,    transform_test_class)

正在运行pylint --load-plugins=$(pwd)/pylint-plugin -E a.py的输出是:

************* Module a
E:  5, 8: No value for argument 'arg' in unbound method call (no-value-for-parameter)

从错误中我怀疑我以某种方式错误地引入了属性,因为pylint认为方法foo是无界的,但它确实是有界限的。我需要找到一种方法告诉pylint foo_cls[0].locals['plu']实际上是类Plugin的实例,而不是类本身。知道如何实现这一目标吗?

1 个答案:

答案 0 :(得分:2)

将插件类添加到FooClass的本地时,需要实例化该插件类。因此,请将此行foo_cls[0].locals['plu'] = plugin_cls_def.lookup('Plugin')[1]替换为foo_cls[0].locals['plu'] = [cls.instantiate_class() for cls in plugin_cls_def.lookup('Plugin')[1]]