comparison planemo/lib/python3.7/site-packages/libfuturize/fixes/fix_division_safe.py @ 1:56ad4e20f292 draft

"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author guerler
date Fri, 31 Jul 2020 00:32:28 -0400
parents
children
comparison
equal deleted inserted replaced
0:d30785e31577 1:56ad4e20f292
1 """
2 For the ``future`` package.
3
4 Adds this import line:
5
6 from __future__ import division
7
8 at the top and changes any old-style divisions to be calls to
9 past.utils.old_div so the code runs as before on Py2.6/2.7 and has the same
10 behaviour on Py3.
11
12 If "from __future__ import division" is already in effect, this fixer does
13 nothing.
14 """
15
16 import re
17 from lib2to3.fixer_util import Leaf, Node, Comma
18 from lib2to3 import fixer_base
19 from libfuturize.fixer_util import (token, future_import, touch_import_top,
20 wrap_in_fn_call)
21
22
23 def match_division(node):
24 u"""
25 __future__.division redefines the meaning of a single slash for division,
26 so we match that and only that.
27 """
28 slash = token.SLASH
29 return node.type == slash and not node.next_sibling.type == slash and \
30 not node.prev_sibling.type == slash
31
32 const_re = re.compile('^[0-9]*[.][0-9]*$')
33
34 def is_floaty(node):
35 return _is_floaty(node.prev_sibling) or _is_floaty(node.next_sibling)
36
37
38 def _is_floaty(expr):
39 if isinstance(expr, list):
40 expr = expr[0]
41
42 if isinstance(expr, Leaf):
43 # If it's a leaf, let's see if it's a numeric constant containing a '.'
44 return const_re.match(expr.value)
45 elif isinstance(expr, Node):
46 # If the expression is a node, let's see if it's a direct cast to float
47 if isinstance(expr.children[0], Leaf):
48 return expr.children[0].value == u'float'
49 return False
50
51
52 class FixDivisionSafe(fixer_base.BaseFix):
53 # BM_compatible = True
54 run_order = 4 # this seems to be ignored?
55
56 _accept_type = token.SLASH
57
58 PATTERN = """
59 term<(not('/') any)+ '/' ((not('/') any))>
60 """
61
62 def start_tree(self, tree, name):
63 """
64 Skip this fixer if "__future__.division" is already imported.
65 """
66 super(FixDivisionSafe, self).start_tree(tree, name)
67 self.skip = "division" in tree.future_features
68
69 def match(self, node):
70 u"""
71 Since the tree needs to be fixed once and only once if and only if it
72 matches, we can start discarding matches after the first.
73 """
74 if node.type == self.syms.term:
75 matched = False
76 skip = False
77 children = []
78 for child in node.children:
79 if skip:
80 skip = False
81 continue
82 if match_division(child) and not is_floaty(child):
83 matched = True
84
85 # Strip any leading space for the first number:
86 children[0].prefix = u''
87
88 children = [wrap_in_fn_call("old_div",
89 children + [Comma(), child.next_sibling.clone()],
90 prefix=node.prefix)]
91 skip = True
92 else:
93 children.append(child.clone())
94 if matched:
95 return Node(node.type, children, fixers_applied=node.fixers_applied)
96
97 return False
98
99 def transform(self, node, results):
100 if self.skip:
101 return
102 future_import(u"division", node)
103 touch_import_top(u'past.utils', u'old_div', node)
104 return results