我正在为在线编程环境编写一些工具。
它的一部分是一个测试用例检查器,它实际上基于一组(输入,输出)文件,将检查解决方法是否实际工作。
基本上,解决方法预计定义如下:
def solution(Nexter: inputs):
# blahblah some code here and there
n = inputs.next_int()
sub_process(inputs)
# simulating a print something
yield str(n)
然后可以翻译(一旦AST修改):
def solution():
# blahblah some code here and there
n = int(input())
sub_process()
print(str(n))
注意:Nexter
是一个定义为用户input()的生成器是否调用或执行预期输入+其他一些好东西的类。
我知道与从AST转换回源代码相关的问题(需要依赖第三方的东西)。我也知道有一个NodeTransformer类:
但它的使用仍然不清楚,我不知道我是否最好检查电话,expr等。
以下是我最终的结果:
signature = inspect.signature(iterative_greedy_solution)
if len(signature.parameters) == 1 and "inputs" in signature.parameters:
parameter = signature.parameters["inputs"]
annotation = parameter.annotation
if Nexter == annotation:
source = inspect.getsource(iterative_greedy_solution)
tree = ast.parse(source)
NexterInputsRewriter().generic_visit(tree)
class NexterInputsRewriter(ast.NodeTransformer):
def visit(self, node):
#???
这绝对不是有史以来最好的设计。下一次,我可能会采用相反的方式(即,在传递给测试人员时,使用简单的用户定义input()
定义{和输出,即print(...)
)并用测试用例输入替换它们断言实际产出是否与预期产出相匹配的类。
总结一下我想要实现的目标并且我并不确切地知道如何(除了子类化NodeTransformer
类之外):
inputs.next_int() = int(input())
找到了一个工具(https://python-ast-explorer.com/),它有助于可视化给定函数使用哪种ast.AST
导数。
答案 0 :(得分:0)
您可能可以使用 NodeTransformer
+ ast.unparse()
,但考虑到它不会保留您的任何评论,它不如查看其他一些 3rd 方解决方案有效。
这是由 refactor(我是作者)完成的示例转换,它是围绕 ast.unparse 的包装层,用于通过 AST 进行简单的源到源转换;
import ast
import refactor
from refactor import ReplacementAction
class ReplaceNexts(refactor.Rule):
def match(self, node):
# We need a call
assert isinstance(node, ast.Call)
# on an attribute (inputs.xxx)
assert isinstance(node.func, ast.Attribute)
# where the name for attribute is `inputs`
assert isinstance(node.func.value, ast.Name)
assert node.func.value.id == "inputs"
target_func_name = node.func.attr.removeprefix("next_")
# make a call to target_func_name (e.g int) with input()
target_func = ast.Call(
ast.Name(target_func_name),
args=[
ast.Call(ast.Name("input"), args=[], keywords=[]),
],
keywords=[],
)
return ReplacementAction(node, target_func)
session = refactor.Session([ReplaceNexts])
source = """\
def solution(Nexter: inputs):
# blahblah some code here and there
n = inputs.next_int()
sub_process(inputs)
st = inputs.next_str()
sub_process(st)
"""
print(session.run(source))
$ python t.py
def solution(Nexter: inputs):
# blahblah some code here and there
n = int(input())
sub_process(inputs)
st = str(input())
sub_process(st)