2017-10-18 14 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クラス-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) 
関連する問題