0

Мне интересно написать программу, которая использует встроенный в Python AST module для случайного изменения констант в произвольном источнике Python.с использованием модуля ast для преобразования случайных констант в исходный код Python

Это преобразование, вероятно, связано с обходом абстрактного представления синтаксического дерева с использованием операций, определенных модулем AST. Модуль предлагает два варианта: во-первых, ast.walk() возвращает ссылки на все узлы в AST, но не предлагает контекстной информации, что делает невозможным повторное сборку дерева. Во-вторых, в документации описывается второй метод, включающий класс ast.NodeTransformer: несколько источников documentation описывают, как использовать NodeTransformer.

Однако в документации NodeTransformer не упоминается, как случайным образом применять условные замены к AST. В частности, я хотел бы изменить эту функцию, чтобы создать функцию, которая выбирает случайный узел в ast, выбирает константу, связанную с узлом в случайном порядке, и заменяет эту константу случайным образом выбранным константой того же типа.

Я подозреваю, что я пытаюсь понять, как правильно модифицировать NodeTransformer, потому что я редко программирую в объектно-ориентированном стиле (обычно придерживаясь функциональной парадигмы). Надеюсь, указывать мне в правильном направлении легко достанет один из вас.

+1

Я дал ответ ниже, но я не уверен, что действительно понимаю вашу задачу здесь. «Случайный узел в AST» может не иметь каких-либо постоянных узлов, «связанных с ним», или это может быть весь АСТ и иметь все константы в «ассоциированном с ним» кодеке, так что это похоже на нечетную область для случайного выбор. Решение, которое я дал ниже, можно легко распространить на нечто вроде «для каждого постоянного узла, произвольно решающего, изменять или не изменять его значение», но это может или не может удовлетворить ваши потребности. – BrenBarn

+0

Я думаю, что ваш ответ предоставляет необходимую информацию для меня, чтобы исправить правильный ответ на мой оригинальный вопрос. Я вернусь, когда у меня появятся возможности с решением, но пока я уверен, что вы натолкнулись на свой ответ. –

ответ

1

Если все, что вы хотите сделать, это изменить константы случайным образом, то вам действительно не нужен контекст узла. Вы можете просто ходить по дереву, ищущему постоянные узлы, и если вы его видите, измените его значение. Вот простой пример:

source = """ 
x = 2 
""" 

# exec the source as-is 
mod = {} 
exec compile(source, '<blah>', 'exec') in mod 

print(mod['x']) 
# prints 2 

t = ast.parse(source) 
# change all numerical constants to 8 
for node in ast.walk(t): 
    if isinstance(node, ast.Num): 
     node.n = 8 
# exec the modified AST 
modMod = {} 
exec compile(t, '<blah>', 'exec') in modMod 

print(modMod['x']) 
# prints 8 

Если вы хотите, чтобы сделать случайный выбор о том, следует ли изменить константу, вы могли бы сделать это так же хорошо. Я не уверен, что понимаю вашу постановку проблемы о выборе «случайного узла в AST». Иерархическая природа АСТ означает, что случайный узел может быть чем угодно: от одной константы до всего модуля, поэтому кажется немного странным, чтобы сначала выбрать случайный узел, а затем выбрать в нем постоянный узел. Почему бы просто не выбрать случайный постоянный узел в первую очередь?

+0

«Почему бы просто не выбрать случайный постоянный узел в первую очередь?» Это именно то, что я хочу сделать. –

 Смежные вопросы

  • Нет связанных вопросов^_^