代码之家  ›  专栏  ›  技术社区  ›  Tyler Fox

基于pylint插件的参数设置多个推断类型

  •  0
  • Tyler Fox  · 技术社区  · 7 年前

    我有一个类,它通过类变量实现了一些类型检查。 然后,当类实例化时,定义的变量成为类的必需参数,具有必需的类型。图案如下所示:

    class MyClass(MagicBaseClass):
        arg1 = ArgumentObj(allowedTypes=(basestring, ))
        arg2 = ArgumentObj(allowedTypes=(list, tuple))
    
        def myMethod(self):
            print type(self.arg1) # a basestring
            print type(self.arg2) # a list
    
    mc = MyClass(arg1='test', arg2=())
    mc.myMethod()
    

    派林不喜欢这样。它看到了 arg1 arg2 作为实例 ArgumentObj . 因此,我想编写一个插件来读取传递的类型,并将这些对象视为我的 MagicBaseClass

    因此,我已经能够找出如何深入挖掘到类转换的正确节点,我可以访问我需要的所有数据,但我真的不知道该怎么处理它。踢球者是允许的多种类型。我现在找不到任何例子来处理这个问题,我能找到的文档基本上都是无用的。

    from astroid import MANAGER
    from astroid import nodes, node_classes
    
    def transform_myClass(node):
        for key, value in node.locals.items():
            val = value[0]
            try:
                s = val.statement().value
                if s.func.name != 'ArgumentObj':
                    continue
            except AttributeError:
                continue
    
            for child in s.get_children():
                if not isinstance(child, node_classes.Keyword):
                    continue
                if child.arg == 'allowedTypes':
                    typeNames = child.value
                    #### And here is where I have no idea what to do next ####
    
    MANAGER.register_transform(nodes.ClassDef, transform_myClass)
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   Tyler Fox    7 年前

    Name 之前 他们什么都做了。要得到它们可能是什么,你必须 .infer() 他们这将类似于文件“basestring”中的单词的内容转换为星形类对象 basestring (好吧,实际上它返回一个生成器……但这里有广泛的笔划)。

    然后,给定这些astroid类ish对象,您必须将该类“实例化”为astroid实例ish对象。

    最后(重要部分), node.locals.items() {name: list of instance-ish objects} . 更新该字典可以设置推断类型。

    因此,我上面的广义笔划代码将变成:

    from astroid import MANAGER
    from astroid import nodes, node_classes
    
    def transform_myClass(node):
        updater = {}
        for key, value in node.locals.items():
            val = value[0]
            try:
                s = val.statement().value
                if s.func.name != 'ArgumentObj':
                    continue
            except AttributeError:
                continue
    
            # Collect all the inferred types in this list
            typeList = []
            for child in s.get_children():
                if not isinstance(child, node_classes.Keyword):
                    continue
    
                # What I needed to do was here:
                # Infer the child classes, and return the instantiated class
                if child.arg == 'allowedTypes':
                    for tc in child.value.get_children():
                        for cls in tc.infer():
                            typeList.append(cls.instantiate_class())
    
            updater[key] = typeList
    
        # Finally, I needed to update the locals
        # which sets the inferred types of the class members
        node.locals.update(updater)
    
    MANAGER.register_transform(nodes.ClassDef, transform_myClass)