1515
1616import re
1717import lib2to3 .pytree as pytree
18- from lib2to3 .fixer_util import Leaf , Node
18+ from lib2to3 .fixer_util import Leaf , Node , Comma
1919from lib2to3 import fixer_base
2020from lib2to3 .fixer_util import syms , does_tree_import
2121from libfuturize .fixer_util import (token , future_import , touch_import_top ,
@@ -33,8 +33,14 @@ def match_division(node):
3333
3434const_re = re .compile ('^[0-9]*[.][0-9]*$' )
3535
36+ def is_floaty (node , div_idx ):
37+ return _is_floaty (node .children [0 :div_idx ]) or _is_floaty (node .children [div_idx + 1 :])
38+
3639
3740def _is_floaty (expr ):
41+ if isinstance (expr , list ):
42+ expr = expr [0 ]
43+
3844 if isinstance (expr , Leaf ):
3945 # If it's a leaf, let's see if it's a numeric constant containing a '.'
4046 return const_re .match (expr .value )
@@ -44,6 +50,24 @@ def _is_floaty(expr):
4450 return expr .children [0 ].value == u'float'
4551 return False
4652
53+ def find_division (node ):
54+ for i , child in enumerate (node .children ):
55+ if match_division (child ):
56+ return i
57+ return False
58+
59+ def clone_div_operands (node , div_idx ):
60+ children = []
61+ for i , child in enumerate (node .children ):
62+ if i == div_idx :
63+ children .append (Comma ())
64+ else :
65+ children .append (child .clone ())
66+
67+ # Strip any leading space for the first number:
68+ children [0 ].prefix = u''
69+
70+ return children
4771
4872class FixDivisionSafe (fixer_base .BaseFix ):
4973 # BM_compatible = True
@@ -60,33 +84,26 @@ def start_tree(self, tree, name):
6084 Skip this fixer if "__future__.division" is already imported.
6185 """
6286 super (FixDivisionSafe , self ).start_tree (tree , name )
63- self .skip = "division" in tree .future_features
87+ self .skip = "division" not in tree .future_features
6488
6589 def match (self , node ):
6690 u"""
6791 Since the tree needs to be fixed once and only once if and only if it
6892 matches, we can start discarding matches after the first.
6993 """
70- if (node .type == self .syms .term and
71- len (node .children ) == 3 and
72- match_division (node .children [1 ])):
73- expr1 , expr2 = node .children [0 ], node .children [2 ]
74- return expr1 , expr2
75- else :
76- return False
94+ if node .type == self .syms .term :
95+ div_idx = find_division (node )
96+ if div_idx is not False :
97+ # if expr1 or expr2 are obviously floats, we don't need to wrap in
98+ # old_div, as the behavior of division between any number and a float
99+ # should be the same in 2 or 3
100+ if not is_floaty (node , div_idx ):
101+ return clone_div_operands (node , div_idx )
102+ return False
77103
78104 def transform (self , node , results ):
79105 if self .skip :
80106 return
81107 future_import (u"division" , node )
82-
83- expr1 , expr2 = results [0 ].clone (), results [1 ].clone ()
84- # Strip any leading space for the first number:
85- expr1 .prefix = u''
86- # if expr1 or expr2 are obviously floats, we don't need to wrap in
87- # old_div, as the behavior of division between any number and a float
88- # should be the same in 2 or 3
89- if _is_floaty (expr1 ) or _is_floaty (expr2 ):
90- return
91108 touch_import_top (u'past.utils' , u'old_div' , node )
92- return wrap_in_fn_call ("old_div" , ( expr1 , expr2 ) , prefix = node .prefix )
109+ return wrap_in_fn_call ("old_div" , results , prefix = node .prefix )
0 commit comments