15e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis# Copyright 2006 Google, Inc. All Rights Reserved.
25e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis# Licensed to PSF under a Contributor Agreement.
35e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
45e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis"""Fixer for execfile.
55e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
65e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. LöwisThis converts usages of the execfile function into calls to the built-in
75e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisexec() function.
85e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis"""
95e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
10e607823af57c176c3be23985f5bbf9260f6bd836Benjamin Petersonfrom .. import fixer_base
1137fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Petersonfrom ..fixer_util import (Comma, Name, Call, LParen, RParen, Dot, Node,
1237fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Peterson                          ArgList, String, syms)
135e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
145e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
15e607823af57c176c3be23985f5bbf9260f6bd836Benjamin Petersonclass FixExecfile(fixer_base.BaseFix):
16a81eae1fd71eed670d1c28bf940ea99b4bfa2335Benjamin Peterson    BM_compatible = True
175e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
185e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis    PATTERN = """
195e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis    power< 'execfile' trailer< '(' arglist< filename=any [',' globals=any [',' locals=any ] ] > ')' > >
205e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis    |
215e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis    power< 'execfile' trailer< '(' filename=any ')' > >
225e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis    """
235e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
245e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis    def transform(self, node, results):
255e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        assert results
265e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        filename = results["filename"]
275e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        globals = results.get("globals")
285e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        locals = results.get("locals")
2937fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Peterson
3037fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Peterson        # Copy over the prefix from the right parentheses end of the execfile
3137fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Peterson        # call.
3237fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Peterson        execfile_paren = node.children[-1].children[-1].clone()
3337fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Peterson        # Construct open().read().
3437fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Peterson        open_args = ArgList([filename.clone()], rparen=execfile_paren)
3584ad84e0bb15e7c64109e88060afdcb60ae7b740Benjamin Peterson        open_call = Node(syms.power, [Name(u"open"), open_args])
3684ad84e0bb15e7c64109e88060afdcb60ae7b740Benjamin Peterson        read = [Node(syms.trailer, [Dot(), Name(u'read')]),
3737fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Peterson                Node(syms.trailer, [LParen(), RParen()])]
3837fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Peterson        open_expr = [open_call] + read
3937fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Peterson        # Wrap the open call in a compile call. This is so the filename will be
4037fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Peterson        # preserved in the execed code.
4137fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Peterson        filename_arg = filename.clone()
426118040b7aee905bcddcb949c6815dc19ca23070Benjamin Peterson        filename_arg.prefix = u" "
4384ad84e0bb15e7c64109e88060afdcb60ae7b740Benjamin Peterson        exec_str = String(u"'exec'", u" ")
4437fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Peterson        compile_args = open_expr + [Comma(), filename_arg, Comma(), exec_str]
4584ad84e0bb15e7c64109e88060afdcb60ae7b740Benjamin Peterson        compile_call = Call(Name(u"compile"), compile_args, u"")
4637fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Peterson        # Finally, replace the execfile call with an exec call.
4737fc82348c4956ea543475ef755d63dfff04dbf4Benjamin Peterson        args = [compile_call]
485e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        if globals is not None:
495e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            args.extend([Comma(), globals.clone()])
505e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        if locals is not None:
515e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            args.extend([Comma(), locals.clone()])
526118040b7aee905bcddcb949c6815dc19ca23070Benjamin Peterson        return Call(Name(u"exec"), args, prefix=node.prefix)
53