Ast парсинг ast.Expr типов
Есть кое-что, чего я не понимаю в смещении белья, которое вычисляется модулем ast. Обычно, когда я получаю белье некоторого аст-объекта, он дает мне первую строку, с которой встречается объект.
Например, в приведенном ниже случае, Линия foo
st='def foo():\n print "hello"'
import ast
print ast.parse(st).body[0].lineno
print ast.parse(st).body[0].body[0].lineno
вернет 1 для функции foo и вернет 2 для распечатки Привет, мир
Однако, если я анализирую многострочную строку документации (ast.Expr), предоставленное бельё является последней строкой.
st='def foo():\n """\n Test\n """'
import ast
print ast.parse(st).body[0].lineno
print ast.parse(st).body[0].body[0].lineno
Результатом по-прежнему будет строка 1 для функции, но это будет строка 4 для строки документации. Я ожидал бы, что это будет на линии 2, так как именно тогда начинается строка документации.
Я предполагаю, что я спрашиваю, есть ли способ всегда получить первое белье из всех аст-объектов, включая ast.Expr .
1 ответ
Исходные местоположения AST оставляют желать лучшего, но многое из этого доступно в библиотеке ASTTokens, которая снабжает узлы AST более полезной информацией о местоположении. В вашем примере:
import asttokens
st='def foo():\n """\n Test\n """'
atok = asttokens.ASTTokens(st, parse=True)
print atok.tree.body[0].first_token.start[0]
print atok.tree.body[0].body[0].first_token.start[0]
Печать 1 и 2 по желанию. Возможно, более интересно,
print atok.get_text_range(atok.tree.body[0])
print atok.get_text_range(atok.tree.body[0].body[0])
Печатает диапазоны исходного текста, соответствующие узлам: (0,35) и (15,35) в этом случае.