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: absolute_import future directive ignored by 2to3
Type: Stage:
Components: 2to3 (2.x to 3.x conversion tool) Versions: Python 3.1
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: benjamin.peterson, jaraco
Priority: normal Keywords:

Created on 2010-04-09 17:09 by jaraco, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
abs_imp_test.zip jaraco, 2010-04-09 17:09
Messages (4)
msg102733 - (view) Author: Jason R. Coombs (jaraco) * (Python committer) Date: 2010-04-09 17:09
I'm using Python 3.1.2 64-bit on Windows.

I've found that even if "absolute_import" is imported from __future__, 2to3 will convert imports to be treated as relative.

To demonstrate this behavior, I created a small package "abs_imp_test" (attached).

abs_imp_test.__init__ is 0 bytes.
abs_imp_test.string is a one-line file.
  foo = 'bar'
abs_imp_test.main contains 4 lines:
  from __future__ import absolute_import
  import string
  assert not hasattr(string, 'foo'), 'fail'
  print("success")

Put abs_imp_test package somewhere in the python path (just having it relative to current directory works).

Note that the code is designed to be future-proof (using the future directive), so will run under Python 2.6 and Python 3.1 without errors.

> python26\python -c "from abs_imp_test import main"
success
> python31\python -c "from abs_imp_test import main"
success

However, if I run 2to3 on main, it converts "import string" to "from . import string" which changes the fundamental meaning of the import and breaks the test.

> 2to3 abs_import_test
...
RefactoringTool: Files that were modified:
RefactoringTool: abs_imp_test\main.py

> python -c "from abs_imp_test import main"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "abs_imp_test\main.py", line 4, in <module>
    assert not hasattr(string, 'foo'), "fail"
AssertionError: fail

Is it possible that if the absolute_import future directive is present that the imports not be modified for relativity?
msg102734 - (view) Author: Jason R. Coombs (jaraco) * (Python committer) Date: 2010-04-09 17:18
More importantly, is there a workaround for main.py that will work in Python 2, and in Python 3 after 2to3, that doesn't require any module renaming?
msg102735 - (view) Author: Jason R. Coombs (jaraco) * (Python committer) Date: 2010-04-09 17:42
I found a workaround by excluding the "import" fixer that seems to work.

For the example,

> 2to3 -x import abs_imp_test

The command still modifies main, but it only removes the __future__ directive and doesn't modify the imports.

For my real-world package, which is using distutils, I added the following to get a build_py that will run 2to3:

try:
	from distutils.command.build_py import build_py_2to3 as build_py
	# exclude some fixers that break already compatible code
	from lib2to3.refactor import get_fixers_from_package
	fixers = get_fixers_from_package('lib2to3.fixes')
	for skip_fixer in ['import']:
		fixers.remove('lib2to3.fixes.fix_' + skip_fixer)
	build_py.fixer_names = fixers
except ImportError:
	from distutils.command.build_py import build_py

This works because the entire package is already using absolute imports wherever they are relevant, so removing the import fixer is appropriate.
msg102749 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2010-04-09 21:12
Fixed in r79917.
History
Date User Action Args
2022-04-11 14:56:59adminsetgithub: 52605
2010-04-09 21:12:12benjamin.petersonsetstatus: open -> closed
resolution: fixed
messages: + msg102749
2010-04-09 20:12:52r.david.murraysetnosy: + benjamin.peterson
2010-04-09 17:42:10jaracosetmessages: + msg102735
2010-04-09 17:18:53jaracosetmessages: + msg102734
2010-04-09 17:09:47jaracocreate