我希望我的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转储我的最终ast结果:
print (astunparse.unparse(astTree))
在文件中,我可以执行文件而没有任何问题。这意味着这确实是位置问题。现在,我将仅使用此变通方法(使用astunparse获取源字符串,而是对其进行编译),但这将添加另一层解析,如果有ast的熟练技术人员向我解释了为什么fix_missing_location无法修复丢失的位置,我显然更愿意这样做。 >