15
15
16
16
import re
17
17
import lib2to3 .pytree as pytree
18
- from lib2to3 .fixer_util import Leaf , Node
18
+ from lib2to3 .fixer_util import Leaf , Node , Comma
19
19
from lib2to3 import fixer_base
20
20
from lib2to3 .fixer_util import syms , does_tree_import
21
21
from libfuturize .fixer_util import (token , future_import , touch_import_top ,
@@ -33,8 +33,14 @@ def match_division(node):
33
33
34
34
const_re = re .compile ('^[0-9]*[.][0-9]*$' )
35
35
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
+
36
39
37
40
def _is_floaty (expr ):
41
+ if isinstance (expr , list ):
42
+ expr = expr [0 ]
43
+
38
44
if isinstance (expr , Leaf ):
39
45
# If it's a leaf, let's see if it's a numeric constant containing a '.'
40
46
return const_re .match (expr .value )
@@ -44,6 +50,24 @@ def _is_floaty(expr):
44
50
return expr .children [0 ].value == u'float'
45
51
return False
46
52
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
47
71
48
72
class FixDivisionSafe (fixer_base .BaseFix ):
49
73
# BM_compatible = True
@@ -60,33 +84,26 @@ def start_tree(self, tree, name):
60
84
Skip this fixer if "__future__.division" is already imported.
61
85
"""
62
86
super (FixDivisionSafe , self ).start_tree (tree , name )
63
- self .skip = "division" in tree .future_features
87
+ self .skip = "division" not in tree .future_features
64
88
65
89
def match (self , node ):
66
90
u"""
67
91
Since the tree needs to be fixed once and only once if and only if it
68
92
matches, we can start discarding matches after the first.
69
93
"""
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
77
103
78
104
def transform (self , node , results ):
79
105
if self .skip :
80
106
return
81
107
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
91
108
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