Skip to content

Commit 7c7534a

Browse files
committed
Add fix_oldstr_wrap and refactor fix_division_safe
1 parent 3fc8f2c commit 7c7534a

File tree

3 files changed

+107
-8
lines changed

3 files changed

+107
-8
lines changed

libfuturize/fixer_util.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from lib2to3.pytree import Leaf, Node
1414
from lib2to3.pygram import python_symbols as syms, python_grammar
1515
from lib2to3.pygram import token
16+
from lib2to3.fixer_util import (Node, Call, Name, syms, Comma, Number)
1617
import re
1718

1819

@@ -429,3 +430,23 @@ def is_shebang_comment(node):
429430
return bool(re.match(SHEBANG_REGEX, node.prefix))
430431

431432

433+
def wrap_in_fn_call(fn_name, args, prefix=None):
434+
"""
435+
Example:
436+
>>> wrap_in_fn_call("oldstr", (arg,))
437+
oldstr(arg)
438+
439+
>>> wrap_in_fn_call("olddiv", (arg1, arg2))
440+
olddiv(arg1, arg2)
441+
"""
442+
assert len(args) > 0
443+
if len(args) == 1:
444+
newargs = args
445+
elif len(args) == 2:
446+
expr1, expr2 = args
447+
newargs = [expr1, Comma(), expr2]
448+
else:
449+
assert NotImplementedError('write me')
450+
return Call(Name(fn_name), newargs, prefix=prefix)
451+
452+

libfuturize/fixes/fix_division_safe.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
"""
1212

1313
from lib2to3 import fixer_base
14-
from lib2to3.fixer_util import (Node, Call, Name, parenthesize,
15-
syms, LParen, RParen, Comma, Number)
14+
from lib2to3.fixer_util import syms
1615
from libfuturize.fixer_util import token, future_import, touch_import_top
1716

17+
1818
def match_division(node):
1919
u"""
2020
__future__.division redefines the meaning of a single slash for division,
@@ -25,10 +25,6 @@ def match_division(node):
2525
not node.prev_sibling.type == slash
2626

2727

28-
def parenthesize_two(expr1, expr2):
29-
return Node(syms.atom, [LParen(), expr1, Comma(), expr2, RParen()])
30-
31-
3228
class FixDivisionSafe(fixer_base.BaseFix):
3329
# BM_compatible = True
3430
run_order = 4 # this seems to be ignored?
@@ -48,13 +44,15 @@ def match(self, node):
4844
len(node.children) == 3 and
4945
match_division(node.children[1])):
5046
expr1, expr2 = node.children[0], node.children[2]
51-
return expr1, expr2
47+
return expr1, expr2
48+
else:
49+
return False
5250

5351
def transform(self, node, results):
5452
future_import(u"division", node)
5553
touch_import_top(u'past.utils', u'old_div', node)
5654
expr1, expr2 = results[0].clone(), results[1].clone()
5755
# Strip any leading space for the first number:
5856
expr1.prefix = u''
59-
return Call(Name("old_div"), [expr1, Comma(), expr2], prefix=node.prefix)
57+
return wrap_in_fn_call("old_div", (expr1, expr2), prefix=node.prefix)
6058

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
"""
2+
For the ``future`` package.
3+
4+
Adds this import line:
5+
6+
from past.builtins import str as oldstr
7+
8+
at the top and wraps any unadorned string literals 'abc' or explicit byte-string
9+
literals b'abc' in oldstr() calls so the code has the same behaviour on Py3 as
10+
on Py2.6/2.7.
11+
"""
12+
13+
from __future__ import unicode_literals
14+
import re
15+
from lib2to3 import fixer_base
16+
from lib2to3.pgen2 import token
17+
from lib2to3.fixer_util import syms
18+
from libfuturize.fixer_util import (future_import, touch_import_top,
19+
wrap_in_fn_call)
20+
21+
22+
_literal_re = re.compile(r"[^uUrR]?[\'\"]")
23+
24+
25+
class FixOldstrWrap(fixer_base.BaseFix):
26+
BM_compatible = True
27+
PATTERN = "STRING"
28+
29+
def transform(self, node, results):
30+
import pdb
31+
pdb.set_trace()
32+
if node.type == token.STRING:
33+
touch_import_top(u'past.types', u'oldstr', node)
34+
if _literal_re.match(node.value):
35+
new = node.clone()
36+
# Strip any leading space or comments:
37+
# TODO: check: do we really want to do this?
38+
new.prefix = u''
39+
new.value = u'b' + new.value
40+
wrapped = wrap_in_fn_call("oldstr", [new], prefix=node.prefix)
41+
return wrapped
42+
43+
def transform(self, node, results):
44+
expr1, expr2 = results[0].clone(), results[1].clone()
45+
# Strip any leading space for the first number:
46+
expr1.prefix = u''
47+
return wrap_in_fn_call("old_div", expr1, expr2, prefix=node.prefix)
48+
49+
50+
class FixDivisionSafe(fixer_base.BaseFix):
51+
# BM_compatible = True
52+
run_order = 4 # this seems to be ignored?
53+
54+
_accept_type = token.SLASH
55+
56+
PATTERN = """
57+
term<(not('/') any)+ '/' ((not('/') any))>
58+
"""
59+
60+
def match(self, node):
61+
u"""
62+
Since the tree needs to be fixed once and only once if and only if it
63+
matches, then we can start discarding matches after we make the first.
64+
"""
65+
if (node.type == self.syms.term and
66+
len(node.children) == 3 and
67+
match_division(node.children[1])):
68+
expr1, expr2 = node.children[0], node.children[2]
69+
return expr1, expr2
70+
else:
71+
return False
72+
73+
def transform(self, node, results):
74+
future_import(u"division", node)
75+
touch_import_top(u'past.utils', u'old_div', node)
76+
expr1, expr2 = results[0].clone(), results[1].clone()
77+
# Strip any leading space for the first number:
78+
expr1.prefix = u''
79+
return wrap_in_fn_call("old_div", expr1, expr2, prefix=node.prefix)
80+

0 commit comments

Comments
 (0)