|
1 # Copyright 2006 Google, Inc. All Rights Reserved. |
|
2 # Licensed to PSF under a Contributor Agreement. |
|
3 |
|
4 """Fixer for print. |
|
5 |
|
6 Change: |
|
7 'print' into 'print()' |
|
8 'print ...' into 'print(...)' |
|
9 'print ... ,' into 'print(..., end=" ")' |
|
10 'print >>x, ...' into 'print(..., file=x)' |
|
11 |
|
12 No changes are applied if print_function is imported from __future__ |
|
13 |
|
14 """ |
|
15 |
|
16 # Local imports |
|
17 from .. import patcomp |
|
18 from .. import pytree |
|
19 from ..pgen2 import token |
|
20 from .. import fixer_base |
|
21 from ..fixer_util import Name, Call, Comma, String, is_tuple |
|
22 |
|
23 |
|
24 parend_expr = patcomp.compile_pattern( |
|
25 """atom< '(' [atom|STRING|NAME] ')' >""" |
|
26 ) |
|
27 |
|
28 |
|
29 class FixPrint(fixer_base.ConditionalFix): |
|
30 |
|
31 PATTERN = """ |
|
32 simple_stmt< any* bare='print' any* > | print_stmt |
|
33 """ |
|
34 |
|
35 skip_on = '__future__.print_function' |
|
36 |
|
37 def transform(self, node, results): |
|
38 assert results |
|
39 |
|
40 if self.should_skip(node): |
|
41 return |
|
42 |
|
43 bare_print = results.get("bare") |
|
44 |
|
45 if bare_print: |
|
46 # Special-case print all by itself |
|
47 bare_print.replace(Call(Name("print"), [], |
|
48 prefix=bare_print.get_prefix())) |
|
49 return |
|
50 assert node.children[0] == Name("print") |
|
51 args = node.children[1:] |
|
52 if len(args) == 1 and parend_expr.match(args[0]): |
|
53 # We don't want to keep sticking parens around an |
|
54 # already-parenthesised expression. |
|
55 return |
|
56 |
|
57 sep = end = file = None |
|
58 if args and args[-1] == Comma(): |
|
59 args = args[:-1] |
|
60 end = " " |
|
61 if args and args[0] == pytree.Leaf(token.RIGHTSHIFT, ">>"): |
|
62 assert len(args) >= 2 |
|
63 file = args[1].clone() |
|
64 args = args[3:] # Strip a possible comma after the file expression |
|
65 # Now synthesize a print(args, sep=..., end=..., file=...) node. |
|
66 l_args = [arg.clone() for arg in args] |
|
67 if l_args: |
|
68 l_args[0].set_prefix("") |
|
69 if sep is not None or end is not None or file is not None: |
|
70 if sep is not None: |
|
71 self.add_kwarg(l_args, "sep", String(repr(sep))) |
|
72 if end is not None: |
|
73 self.add_kwarg(l_args, "end", String(repr(end))) |
|
74 if file is not None: |
|
75 self.add_kwarg(l_args, "file", file) |
|
76 n_stmt = Call(Name("print"), l_args) |
|
77 n_stmt.set_prefix(node.get_prefix()) |
|
78 return n_stmt |
|
79 |
|
80 def add_kwarg(self, l_nodes, s_kwd, n_expr): |
|
81 # XXX All this prefix-setting may lose comments (though rarely) |
|
82 n_expr.set_prefix("") |
|
83 n_argument = pytree.Node(self.syms.argument, |
|
84 (Name(s_kwd), |
|
85 pytree.Leaf(token.EQUAL, "="), |
|
86 n_expr)) |
|
87 if l_nodes: |
|
88 l_nodes.append(Comma()) |
|
89 n_argument.set_prefix(" ") |
|
90 l_nodes.append(n_argument) |