AST: как посетить импорт с моим преобразователем: typeError: обязательное поле "lineno" отсутствует в stmt - PullRequest
0 голосов
/ 14 июня 2019

Я хочу, чтобы мой nodeTransformer посещал все импортированные (только из) модули с определенным синтаксисом.

Прямо сейчас я ловлю любой ImportFrom, открываю файл благодаря атрибуту node.module, чтобы получить источник, создать узел AST из источника. Каждый раз, когда я читаю источники, я также добавляю для каждого узла родительский узел:

    def getASTFromSources(f):

        print('currentdir ',os.getcwd())
        with open(f, "r") as source:
            #parentify the tree
            astTree=ast.parse(source.read())
            for node in ast.walk(astTree):
                for child in ast.iter_child_nodes(node):
                    child.parent = node
            return astTree

Затем я вызываю следующую функцию, чтобы заменить оператор импорта:

def insertAfterNode( node, nodeToInsert):
        parent = node.parent
        index= parent.body.index(node)
        parent.body.insert(index+1, nodeToInsert)
        nodeToInsert.parent=parent
        ast.fix_missing_locations(parent)

Полный код VisitImport:

    def visit_ImportFrom(self,node):
        if not node.module.startswith('transforms_'):
            return node

        path= getFilePathFromModuleName(node.module)
        astImport=SourceTransformer.getASTFromSources(path)

        SourceTransformer.insertAfterNode(node, astImport)

Однако в конце, независимо от того, применяется ли fix_missing_locations() ко всему дереву, компилятор жалуется:

code=compile(astTree, 'modifiedModule','exec')
TypeError: required field "lineno" missing from stmt

Также обратите внимание, что я также попытался просто заменить importNode исходным узлом:

def visit_ImportFrom(self,node):
        if not node.module.startswith('transforms_'):
            print (node.module)
            return node



        path= getFilePathFromModuleName(node.module)
        astImport=SourceTransformer.getASTFromSources(path)

        return astImport
"""I also tried that
        return ast.copy_location(astImport, node)"""

Что странно в том, что если сбросить мой последний аст результат с astunparse:

        print (astunparse.unparse(astTree))

в файле, я могу выполнить файл без проблем. Что означает, что это действительно проблема местоположения. Сейчас я просто буду использовать этот обходной путь (получить исходную строку с помощью astunparse, скомпилировать ее вместо этого), но это добавление еще одного слоя синтаксического анализа, я, очевидно, предпочитаю, если кто-то, имеющий опыт в области ast, объяснит мне, почему fix_missing_location не исправляет отсутствующие местоположения.

...