This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: 2to3 should remove from future_builtins import *
Type: behavior Stage: resolved
Components: 2to3 (2.x to 3.x conversion tool) Versions: Python 3.6, Python 2.7
process
Status: closed Resolution: wont fix
Dependencies: Superseder: Close 2to3 issues and list them here
View: 45544
Assigned To: Nosy List: benjamin.peterson, josh.r, marfire, maubp, zvyn
Priority: normal Keywords: patch

Created on 2013-09-28 14:52 by maubp, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
2to3_fix_future_builtins.patch zvyn, 2015-06-24 05:28 review
Messages (7)
msg198521 - (view) Author: Peter (maubp) Date: 2013-09-28 14:52
The 2to3 script should remove lines like this:

from future_builtins import zip

after running the zip fixer which respects the meaning of this command (issue 217). It does not, which results in an ImportError when trying to use the converted code under Python 3.

Similarly for lines like this after running the map fixer etc:

from future_builtins import map

Background:

Python 2.6 and 2.7 have an iterator-style zip function in future_builtins (and other things):

$ python2.6
Python 2.6.8 (unknown, Sep 28 2013, 12:09:28) 
[GCC 4.6.3] on linux3
Type "help", "copyright", "credits" or "license" for more information.
>>> import future_builtins
>>> dir(future_builtins)
['__doc__', '__file__', '__name__', '__package__', 'ascii', 'filter', 'hex', 'map', 'oct', 'zip']
>>> quit()

$ python2.7
Python 2.7.1 (r271:86832, Dec 26 2010, 19:03:20) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import future_builtins
>>> dir(future_builtins)
['__doc__', '__file__', '__name__', '__package__', 'ascii', 'filter', 'hex', 'map', 'oct', 'zip']
>>> quit()

The future_builtins module does not exist under Python 3, in particular its zip and map functions do not exist.

$ python3.3
Python 3.3.2 (default, Sep 28 2013, 12:00:20) 
[GCC 4.6.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import future_builtins
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named 'future_builtins'

--------------------------------------------------

Sample script using zip which works under Python 2.6 and 2.7,

$ more zip_2to3_bug.py 
from future_builtins import zip
assert next(zip("abc", [1, 2, 3])) == ("a", 1)
print "Done"

$ python2.6 zip_2to3_bug.py 
Done

$ python2.7 zip_2to3_bug.py 
Done

Now let's use the 2to3 script (in place):

$ 2to3 -w zip_2to3_bug.py 
RefactoringTool: Skipping implicit fixer: buffer
RefactoringTool: Skipping implicit fixer: idioms
RefactoringTool: Skipping implicit fixer: set_literal
RefactoringTool: Skipping implicit fixer: ws_comma
RefactoringTool: Refactored zip_2to3_bug.py
--- zip_2to3_bug.py	(original)
+++ zip_2to3_bug.py	(refactored)
@@ -1,3 +1,3 @@
 from future_builtins import zip
 assert next(zip("abc", [1, 2, 3])) == ("a", 1)
-print "Done"
+print("Done")

Here's the (broken) output:

$ more zip_2to3_bug.py
from future_builtins import zip
assert next(zip("abc", [1, 2, 3])) == ("a", 1)
print("Done")

This breaks:

$ python3.3 zip_2to3_bug.py
Traceback (most recent call last):
  File "zip_2to3_bug.py", line 1, in <module>
    from future_builtins import zip
ImportError: No module named 'future_builtins'

Expected output should respect the fact I am using "from future_builtins import zip" therefore zip as an iterator already (this is working), and then remove the line "from future_builtins import zip":

$ more zip_2to3_bug.py
assert next(zip("abc", [1, 2, 3])) == ("a", 1)
print("Done")

--------------------------------------------------


Sample script using zip which works under Python 2.6 and 2.7,

$ more map_2to3_bug.py 
from future_builtins import map
x = [-2, -1, 0, 1, 2, 3]
y = next(map(abs, x))
assert y == 2 
print "Done"

$ python2.6 map_2to3_bug.py 
Done

$ python2.7 map_2to3_bug.py 
Done

Now let's use the 2to3 script (in place):

$ 2to3 -w map_2to3_bug.py 
RefactoringTool: Skipping implicit fixer: buffer
RefactoringTool: Skipping implicit fixer: idioms
RefactoringTool: Skipping implicit fixer: set_literal
RefactoringTool: Skipping implicit fixer: ws_comma
RefactoringTool: Refactored map_2to3_bug.py
--- map_2to3_bug.py	(original)
+++ map_2to3_bug.py	(refactored)
@@ -2,4 +2,4 @@
 x = [-2, -1, 0, 1, 2, 3]
 y = next(map(abs, x))
 assert y == 2 
-print "Done"
+print("Done")
RefactoringTool: Files that were modified:
RefactoringTool: map_2to3_bug.py

Here's the (broken) output:

$ more map_2to3_bug.py
from future_builtins import map
x = [-2, -1, 0, 1, 2, 3]
y = next(map(abs, x))
assert y == 2 
print("Done")

This breaks:

$ python3.3 map_2to3_bug.py
Traceback (most recent call last):
  File "map_2to3_bug.py", line 1, in <module>
    from future_builtins import map
ImportError: No module named 'future_builtins'


Expected output should respect the fact I am using "from future_builtins import map" and therefore treat map according (this is working), and then remove the line "from future_builtins import map":

$ more zip_2to3_bug.py
x = [-2, -1, 0, 1, 2, 3]
y = next(map(abs, x))
assert y == 2 
print("Done")
msg198598 - (view) Author: Peter (maubp) Date: 2013-09-29 15:27
Thinking about this, perhaps the bug is that Python 3 doesn't have a future_builtins module? Consider:


$ python2.6
Python 2.6.8 (unknown, Sep 28 2013, 12:09:28) 
[GCC 4.6.3] on linux3
Type "help", "copyright", "credits" or "license" for more information.
>>> from __future__ import with_statement
>>> from __future__ import print_function
>>> from future_builtins import map, zip
>>> quit()


versus:


$ python3.3
Python 3.3.2 (default, Sep 28 2013, 12:00:20) 
[GCC 4.6.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from __future__ import with_statement
>>> from __future__ import print_function
>>> from future_builtins import map, zip
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named 'future_builtins'
>>> quit()


The expectation from the __future__ imports is that once a feature is part of Python, the import is a harmless no-op. You could expect the same from  future_builtins as well.
msg227249 - (view) Author: Kevin Christopher Henry (marfire) Date: 2014-09-22 03:09
I'm interested in working on this, but it's not clear to me if this has been accepted as a bug. I converted a large project recently and was shocked to find that all 100+ files were broken because of the needless "from future_builtins..." line. Perversely, this most hurts those who made the most effort to make their code forward-compatible with Python 3.

One complication is that you can't simply substitute a blank line, since that could produce invalid code if the import is inside a try/except block. (This doesn't affect "from __future__..." since that can only be at the start of a file.) Substituting a "pass" should work fine though. That would be a bit unsightly, but then again so is the blank line at the start of the file produced by removing "from __future__...". More important is to produce code that actually works under Python 3.

Another issue is that it's possible to simply "import future_builtins" and then use, for example, "future_builtins.zip(...)". So trying to fix that usage as well would be (I assume) a lot more complicated. Personally it seems fine with me to just fix the "from __future_builtins__..." usage.
msg245719 - (view) Author: Milan Oberkirch (zvyn) * Date: 2015-06-24 05:28
Here is a simple patch that would solve this issue.
The new fixer 'future_builtins' removes `from future_builtins import foo` statements if they aren't nested in other constructs (try-except, classes, ...) and replaces them with `pass` otherwise.
msg245789 - (view) Author: Josh Rosenberg (josh.r) * (Python triager) Date: 2015-06-25 01:46
Shouldn't it also disable the relevant fixers for map, filter, zip, etc. as appropriate? Otherwise a whole bunch of calls will be wrapper in list() or the like to mimic a behavior the code never had in Py2 in the first place.
msg245800 - (view) Author: Milan Oberkirch (zvyn) * Date: 2015-06-25 05:28
The other fixers you mentioned are deactivated independently of this patch if an import from future_builtins exists. I gave it the same run_order as in the fix for __future__ imports which prevents 2to3 from deleting the calls before other fixers check for their existence.
msg245807 - (view) Author: Josh Rosenberg (josh.r) * (Python triager) Date: 2015-06-25 10:14
Ah, my mistake. Apologies.
History
Date User Action Args
2022-04-11 14:57:51adminsetgithub: 63310
2021-10-20 22:46:00iritkatrielsetstatus: open -> closed
superseder: Close 2to3 issues and list them here
resolution: wont fix
stage: resolved
2015-06-25 10:14:59josh.rsetmessages: + msg245807
2015-06-25 05:28:54zvynsetmessages: + msg245800
2015-06-25 01:46:57josh.rsetnosy: + josh.r
messages: + msg245789
2015-06-24 05:28:04zvynsetfiles: + 2to3_fix_future_builtins.patch
versions: + Python 2.7, Python 3.6, - Python 3.5
nosy: + zvyn

messages: + msg245719

keywords: + patch
2014-09-22 03:09:17marfiresetnosy: + marfire

messages: + msg227249
versions: + Python 3.5, - Python 3.3
2013-10-05 00:28:23terry.reedysetnosy: + benjamin.peterson
2013-09-29 15:27:14maubpsetmessages: + msg198598
2013-09-28 14:52:33maubpcreate