Я хочу, чтобы мой 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 не исправляет отсутствующие местоположения.