classification
Title: relative import broken
Type: Stage: committed/rejected
Components: Interpreter Core Versions: Python 2.6
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: brett.cannon Nosy List: Oren_Held, barry, brett.cannon, flox, gangesmaster, loewis, meador.inge
Priority: release blocker Keywords: needs review, patch

Created on 2010-02-10 19:09 by gangesmaster, last changed 2010-08-16 22:44 by flox. This issue is now closed.

Files
File name Uploaded Description Edit
bar.py gangesmaster, 2010-02-10 19:09
issue-7902.patch meador.inge, 2010-02-24 05:27 patch against 2.7 trunk
Messages (11)
msg99176 - (view) Author: ganges master (gangesmaster) Date: 2010-02-10 19:09
the relative-import mechanism is broken... at least on python2.6 but i'd guess on later versions as well.

consider this package layout:
    /tmp/foo/
    /tmp/foo/__init__.py
    /tmp/foo/bar.py

where bar.py is:
    # note this is a relative import and should fail!
    from .os import walk
    print walk
    # and this should also fail
    from . import os
    print os

running it yields a bug:

$ PYTHONPATH="/tmp" python
Python 2.6.4 (r264:75706, Dec  7 2009, 18:45:15) 
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import foo.bar
<function walk at 0xb7d2aa04>  # <<<< ?!?!
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/tmp/foo/bar.py", line 4, in <module>
    from . import os
ImportError: cannot import name os


"from . import os" fails as expected, but "from .os import walk" works -- although it should obviously fail too.


-tomer
msg99177 - (view) Author: ganges master (gangesmaster) Date: 2010-02-10 19:10
i believe brett is in charge of this, adding him to the noisy. sorry if it's not you :)
msg99179 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2010-02-10 21:11
So doing the import manually through __import__('os', globals(), locals(), ['walk'], 1) does not work. My guess is it has something to do with the IMPORT_FROM opcode (or something related), but I don't have time right now to dig deeper.
msg100006 - (view) Author: Meador Inge (meador.inge) * (Python committer) Date: 2010-02-24 05:27
> So doing the import manually through __import__('os', globals(), 
> locals(), ['walk'], 1) does not work. 

I get the same behavior for this reproduction case regardless of whether I use:
   import .os import walk
or:
   __import__('os', globals(), locals(), ['walk'], 1)
The bug is reproducible in the trunk.

I think the problem has to do with 'import_module_level' incorrectly doing an absolute lookup for 'os' when the relative lookup in 'foo' fails.  I have attached a patch with the relevant fix and test case.
msg106065 - (view) Author: Meador Inge (meador.inge) * (Python committer) Date: 2010-05-19 13:26
Does this patch seem reasonable?
msg106179 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2010-05-20 18:41
Thanks for the patch, Meador. All I did was tweak the test slightly. Committed in:

+ 2.7: r81380
+ 2.6: r81381
msg113926 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2010-08-14 19:41
Backporting this change to 2.6 has created an incompatibility in that branch, see for example issue9600. Apparently, it will only break code that is "conceptually wrong", but still "worked" on 2.6.

I'll suggest that this is a release-critical issue for 2.6.6. It should be considered whether the incompatibility is accepted, or fixed, or reverted.
msg114048 - (view) Author: Florent Xicluna (flox) * (Python committer) Date: 2010-08-16 15:17
Btw, the comment and failure message in r81380/r81381 look wrong.

-    # If absolute import syntax is used, then do not try to perform
-    # a relative import in the face of failure.
+    # If explicit relative import syntax is used, then do not try
+    # to perform an absolute import in the face of failure.

     self.fail("explicit relative import triggered "
-              "an implicit relative import")
+              "an implicit absolute import")


In addition the TestCase.assertRaises method could be used:

    def test_absolute_import_without_future(self):
        # If explicit relative import syntax is used, then do not try
        # to perform a relative import in the face of failure.
        # Issue #7902.
        with self.assertRaises(ImportError):
            from .os import sep
            self.fail("explicit relative import triggered an "
                      "implicit absolute import")
msg114065 - (view) Author: Florent Xicluna (flox) * (Python committer) Date: 2010-08-16 18:58
Comment changed in r84097, 3.2 branch, with minor fixes.
msg114067 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2010-08-16 19:11
Guido has spoken: http://mail.python.org/pipermail/python-dev/2010-August/103104.html

We'll keep the change for 2.6.6rc2.
msg114082 - (view) Author: Florent Xicluna (flox) * (Python committer) Date: 2010-08-16 22:44
Merged in 3.1 with r84115.
History
Date User Action Args
2011-01-17 17:01:49r.david.murraylinkissue10926 superseder
2010-08-16 22:44:22floxsetmessages: + msg114082
2010-08-16 19:11:12barrysetstatus: open -> closed
nosy: + barry
messages: + msg114067

2010-08-16 18:58:33floxsetmessages: + msg114065
2010-08-16 15:17:55floxsetnosy: + flox
messages: + msg114048
2010-08-14 19:41:30loewissetstatus: closed -> open
priority: normal -> release blocker
2010-08-14 19:41:04loewissetnosy: + loewis
messages: + msg113926
2010-05-20 18:41:46brett.cannonsetstatus: open -> closed
resolution: fixed
messages: + msg106179

stage: patch review -> committed/rejected
2010-05-19 20:10:51brett.cannonsetkeywords: + needs review
assignee: brett.cannon
stage: patch review
2010-05-19 13:26:03meador.ingesetmessages: + msg106065
2010-02-24 05:27:37meador.ingesetfiles: + issue-7902.patch

nosy: + meador.inge
messages: + msg100006

keywords: + patch
2010-02-12 08:41:33Oren_Heldsetnosy: + Oren_Held
2010-02-10 21:11:35brett.cannonsetmessages: + msg99179
2010-02-10 19:10:55gangesmastersetnosy: + brett.cannon
messages: + msg99177
2010-02-10 19:09:21gangesmastercreate