Skip to content

Commit 65e0765

Browse files
committed
Merge pull request #110 from python-modernize/fix_classic_division
Add a classic_division fixer.
2 parents a55c9e3 + 433c96d commit 65e0765

File tree

5 files changed

+83
-0
lines changed

5 files changed

+83
-0
lines changed

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ Unreleased
22
==========
33

44
Changes since 0.4:
5+
6+
* Added the opt-in classic_division fixer.
57
* Updated the ``dict_six`` fixer to support ``six.viewitems()`` and friends.
8+
* Documentation corrections.
9+
610

711
Version 0.4
812
===========

docs/fixers.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,27 @@ to specify the ``-f default`` or ``--fix=default`` option, e.g.::
281281

282282
python-modernize -f default -f libmodernize.fixes.fix_open
283283

284+
.. 2to3fixer:: classic_division
285+
286+
When a use of the division operator -- ``/`` -- is found, add
287+
``from __future__ import division`` and change the operator to ``//``.
288+
If ``from __future__ import division`` is already present, this fixer is
289+
skipped.
290+
291+
This is intended for use in programs where ``/`` is conventionally only used
292+
for integer division, or where it is intended to do a manual pass after running
293+
python-modernize to look for cases that should not have been changed to ``//``.
294+
The results of division on non-integers may differ after running this fixer:
295+
for example, ``3.5 / 2 == 1.75``, but ``3.5 // 2 == 1.0``.
296+
297+
Some objects may override the ``__div__`` method for a use other than division,
298+
and thus would break when changed to use a ``__floordiv__`` method instead.
299+
300+
This fixer is opt-in because it may change the meaning of code as described
301+
above.
302+
303+
.. versionadded:: 0.5
304+
284305
.. 2to3fixer:: open
285306
286307
When a call to :func:`open <python2:open>` is discovered, add ``from io import open`` at the top

libmodernize/fixes/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,6 @@
4545

4646
# Fixes that are opt-in only.
4747
opt_in_fix_names = set([
48+
'libmodernize.fixes.fix_classic_division',
4849
'libmodernize.fixes.fix_open',
4950
])
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from __future__ import absolute_import
2+
3+
from lib2to3 import fixer_base
4+
from lib2to3 import pytree
5+
from lib2to3.pgen2 import token
6+
7+
import libmodernize
8+
9+
10+
class FixClassicDivision(fixer_base.BaseFix):
11+
_accept_type = token.SLASH
12+
13+
def start_tree(self, tree, name):
14+
super(FixClassicDivision, self).start_tree(tree, name)
15+
self.skip = "division" in tree.future_features
16+
17+
def match(self, node):
18+
return node.value == "/"
19+
20+
def transform(self, node, results):
21+
if self.skip:
22+
return
23+
libmodernize.add_future(node, u'division')
24+
return pytree.Leaf(token.SLASH, "//", prefix=node.prefix)

tests/test_fix_classic_division.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from __future__ import absolute_import
2+
3+
from utils import check_on_input
4+
5+
6+
CLASSIC_DIVISION = ("""\
7+
1 / 2
8+
""",
9+
"""\
10+
from __future__ import division
11+
1 // 2
12+
""")
13+
14+
NEW_DIVISION = ("""\
15+
from __future__ import division
16+
1 / 2
17+
""",
18+
"""\
19+
from __future__ import division
20+
1 / 2
21+
""")
22+
23+
24+
def test_optional():
25+
check_on_input(CLASSIC_DIVISION[0], CLASSIC_DIVISION[0])
26+
27+
def test_fix_classic_division():
28+
check_on_input(*CLASSIC_DIVISION,
29+
extra_flags=['-f', 'libmodernize.fixes.fix_classic_division'])
30+
31+
def test_new_division():
32+
check_on_input(*NEW_DIVISION,
33+
extra_flags=['-f', 'libmodernize.fixes.fix_classic_division'])

0 commit comments

Comments
 (0)