根据 pylint 插件的参数设置多个推断类型 [英] Set multiple inferred types based on arguments for pylint plugin

查看:70
本文介绍了根据 pylint 插件的参数设置多个推断类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个通过类变量实现一些类型检查的类.然后,当类被实例化时,定义的变量成为类的必需参数,具有必需的类型.模式看起来像这样:

I have a class that implements some typechecking via class variables. Then, when the class is instantiated, the defined variables become required arguments for the class, with required types. The pattern looks something like this:

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()

Pylint 不喜欢这样.它将 arg1arg2 视为 ArgumentObj 的实例.所以我想编写一个插件来读取传递的类型,并将这些对象视为我的 MagicBaseClass 中这些类型的实例.

Pylint does not like this. It sees arg1 and arg2 as instances of ArgumentObj. So I want to write a plugin that reads the passed types, and treat those objects as instances of those types inside my MagicBaseClass.

所以,我已经能够弄清楚如何挖掘到正确的节点进行类转换,并且我可以访问我需要的所有数据,但我真的不知道如何处理它.踢球者是多种允许的类型.我现在找不到任何例子来处理这个问题,我能找到的文档基本上没用.

So, I've been able to figure out how to dig down to the correct nodes for the class transform, and I can access the all the data I need, but I don't really know what to do with it. The kicker is the multiple allowed types. I can't find any example now to handle that, and the docs I can find are basically useless.

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)

推荐答案

Name 对象.这些基本上是您的文件中的字符串 对它们进行任何操作之前.为了得到它们可能是什么,你必须 .infer() 它们.这将类似于文件basestring"中的单词转换为一个 astroid class-ish 对象 basestring(嗯,实际上它返回一个生成器......但在这里是粗略的).

There are Name objects. These are basically the strings in your file before anything is done to them. To get what they will possibly be, you must .infer() them. This turns something like the word in file "basestring" into a astroid class-ish object basestring (well, actually it returns a generator ... but broad strokes here).

然后,给定这些 astroid 类对象,您必须将类实例化"为一个 astroid 实例对象.

Then, given these astroid class-ish objects, you must "instantiate" the class to an astroid instance-ish object.

最后(重要的部分),node.locals.items(){name: 实例对象列表} 的字典.更新该字典可让您设置推断类型.

Finally (the important part), node.locals.items() is a dictionary of {name: list of instance-ish objects}. Updating that dictionary lets you set the inferred types.

所以我上面的粗略代码会变成这样:

So my broad-strokes code from above would turn into this:

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)

这篇关于根据 pylint 插件的参数设置多个推断类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆