11
10
from .. import fixer_base
12
from ..fixer_util import Comma, Name, Call, LParen, RParen, Dot
11
from ..fixer_util import (Comma, Name, Call, LParen, RParen, Dot, Node,
12
ArgList, String, syms)
15
15
class FixExecfile(fixer_base.BaseFix):
23
23
def transform(self, node, results):
26
25
filename = results["filename"]
27
26
globals = results.get("globals")
28
27
locals = results.get("locals")
29
args = [Name('open'), LParen(), filename.clone(), RParen(), Dot(),
30
Name('read'), LParen(), RParen()]
31
args[0].set_prefix("")
29
# Copy over the prefix from the right parentheses end of the execfile
31
execfile_paren = node.children[-1].children[-1].clone()
32
# Construct open().read().
33
open_args = ArgList([filename.clone()], rparen=execfile_paren)
34
open_call = Node(syms.power, [Name("open"), open_args])
35
read = [Node(syms.trailer, [Dot(), Name('read')]),
36
Node(syms.trailer, [LParen(), RParen()])]
37
open_expr = [open_call] + read
38
# Wrap the open call in a compile call. This is so the filename will be
39
# preserved in the execed code.
40
filename_arg = filename.clone()
41
filename_arg.set_prefix(" ")
42
exec_str = String("'exec'", " ")
43
compile_args = open_expr + [Comma(), filename_arg, Comma(), exec_str]
44
compile_call = Call(Name("compile"), compile_args, "")
45
# Finally, replace the execfile call with an exec call.
32
47
if globals is not None:
33
48
args.extend([Comma(), globals.clone()])
34
49
if locals is not None:
35
50
args.extend([Comma(), locals.clone()])
37
51
return Call(Name("exec"), args, prefix=node.get_prefix())