[Jython-checkins] jython (2.5): #1871 Relative import in module gets imported to top level (regression)

frank.wierzbicki jython-checkins at python.org
Tue May 15 04:06:15 CEST 2012


http://hg.python.org/jython/rev/207e3db21d5b
changeset:   6651:207e3db21d5b
branch:      2.5
parent:      6648:c62b1a8fa99b
user:        Frank Wierzbicki <fwierzbicki at gmail.com>
date:        Mon May 14 18:44:09 2012 -0700
summary:
  #1871 Relative import in module gets imported to top level (regression)

files:
  Lib/test/test_pkg_jy.py      |  104 +++++++++++++++++++++++
  NEWS                         |    1 +
  src/org/python/core/imp.java |    5 +
  3 files changed, 110 insertions(+), 0 deletions(-)


diff --git a/Lib/test/test_pkg_jy.py b/Lib/test/test_pkg_jy.py
new file mode 100644
--- /dev/null
+++ b/Lib/test/test_pkg_jy.py
@@ -0,0 +1,104 @@
+# Test packages (dotted-name import)
+
+# XXX: This test is borrowed from CPython 2.7 as it tickles
+# http://bugs.jython.org/issue1871 so it should be removed in Jython 2.7
+import sys
+import os
+import tempfile
+import textwrap
+import unittest
+from test import test_support
+
+
+# Helpers to create and destroy hierarchies.
+
+def cleanout(root):
+    names = os.listdir(root)
+    for name in names:
+        fullname = os.path.join(root, name)
+        if os.path.isdir(fullname) and not os.path.islink(fullname):
+            cleanout(fullname)
+        else:
+            os.remove(fullname)
+    os.rmdir(root)
+
+def fixdir(lst):
+    if "__builtins__" in lst:
+        lst.remove("__builtins__")
+    return lst
+
+
+class Test(unittest.TestCase):
+
+    def setUp(self):
+        self.root = None
+        self.pkgname = None
+        self.syspath = list(sys.path)
+
+    def tearDown(self):
+        sys.path[:] = self.syspath
+        if self.root: # Only clean if the test was actually run
+            cleanout(self.root)
+
+        # delete all modules concerning the tested hierarchy
+        if self.pkgname:
+            modules = [name for name in sys.modules
+                       if self.pkgname in name.split('.')]
+            for name in modules:
+                del sys.modules[name]
+
+    def run_code(self, code):
+        exec(textwrap.dedent(code), globals(), {"self": self})
+
+    def mkhier(self, descr):
+        root = tempfile.mkdtemp()
+        sys.path.insert(0, root)
+        if not os.path.isdir(root):
+            os.mkdir(root)
+        for name, contents in descr:
+            comps = name.split()
+            fullname = root
+            for c in comps:
+                fullname = os.path.join(fullname, c)
+            if contents is None:
+                os.mkdir(fullname)
+            else:
+                f = open(fullname, "w")
+                f.write(contents)
+                if contents and contents[-1] != '\n':
+                    f.write('\n')
+                f.close()
+        self.root = root
+        # package name is the name of the first item
+        self.pkgname = descr[0][0]
+
+    def test_5(self):
+        hier = [
+        ("t5", None),
+        ("t5 __init__"+os.extsep+"py", "import t5.foo"),
+        ("t5 string"+os.extsep+"py", "spam = 1"),
+        ("t5 foo"+os.extsep+"py",
+         "from . import string; assert string.spam == 1"),
+         ]
+        self.mkhier(hier)
+
+        import t5
+        s = """
+            from t5 import *
+            self.assertEqual(dir(), ['foo', 'self', 'string', 't5'])
+            """
+        self.run_code(s)
+
+        import t5
+        self.assertEqual(fixdir(dir(t5)),
+                         ['__doc__', '__file__', '__name__',
+                          '__path__', 'foo', 'string', 't5'])
+        self.assertEqual(fixdir(dir(t5.foo)),
+                         ['__doc__', '__file__', '__name__',
+                          'string'])
+        self.assertEqual(fixdir(dir(t5.string)),
+                         ['__doc__', '__file__', '__name__',
+                          'spam'])
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,7 @@
 
 Jython 2.5.3b2
   Bugs Fixed
+    - [ 1871 ] Relative import in module gets imported to top level (regression)
     - [ 1854 ] set().pop() race condition
     - [ 1730 ] functools.partial incorrectly makes __doc__ property readonly
     - [ 1537 ] expat: org.python.apache.xerces.parsers.SAXParser
diff --git a/src/org/python/core/imp.java b/src/org/python/core/imp.java
--- a/src/org/python/core/imp.java
+++ b/src/org/python/core/imp.java
@@ -862,6 +862,11 @@
                 return;
             }
 
+            //This can happen with imports like "from . import foo"
+            if (name.length() == 0) {
+                name = mod.__findattr__("__name__").toString();
+            }
+
             StringBuilder modNameBuffer = new StringBuilder(name);
             for (PyObject item : fromlist.asIterable()) {
                 if (!Py.isInstance(item, PyString.TYPE)) {

-- 
Repository URL: http://hg.python.org/jython


More information about the Jython-checkins mailing list