2017-10-18 70 views
0

我有一个类,它通过类变量实现了一些类型检查。 然后,当实例化类时,定义的变量将成为该类的必需参数,并具有所需的类型。图案看起来像这样:根据pylint插件的参数设置多个推断类型

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中这些类型的实例处理。

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

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) 

回答

0

还有Name对象。这些基本上是之前之前的文件中的字符串。为了得到他们可能会,他们必须.infer()他们。这将文件“basestring”中的单词转换为astroid类ish对象basestring(呃,实际上它返回一个生成器......但在这里有广泛的笔画)。

然后,考虑到这些astroid class-ish对象,您必须将该类“实例化”为astroid instance-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) 
相关问题