[Python-checkins] cpython: Issue #18018: Raise an ImportError if a relative import is attempted

brett.cannon python-checkins at python.org
Fri Jan 22 19:39:08 EST 2016


https://hg.python.org/cpython/rev/c4e4886c6052
changeset:   100054:c4e4886c6052
user:        Brett Cannon <brett at python.org>
date:        Fri Jan 22 16:39:02 2016 -0800
summary:
  Issue #18018: Raise an ImportError if a relative import is attempted
with no known parent package.

Previously SystemError was raised if the parent package didn't exist
(e.g., __package__ was set to '').
Thanks to Florent Xicluna and Yongzhi Pan for reporting the issue.

files:
  Doc/whatsnew/3.6.rst                                     |   4 +++
  Lib/test/test_importlib/import_/test_relative_imports.py |   5 ++++
  Misc/NEWS                                                |   3 ++
  Python/import.c                                          |  11 +++++++--
  4 files changed, 20 insertions(+), 3 deletions(-)


diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst
--- a/Doc/whatsnew/3.6.rst
+++ b/Doc/whatsnew/3.6.rst
@@ -278,6 +278,10 @@
   to ``__spec__.parent`` then :exc:`ImportWarning` is raised.
   (Contributed by Brett Cannon in :issue:`25791`.)
 
+* When a relative import is performed and no parent package is known, then
+  :exc:`ImportError` will be raised. Previously, :exc:`SystemError` could be
+  raised. (Contribute by Brett Cannon in :issue:`18018`.)
+
 
 Changes in the C API
 --------------------
diff --git a/Lib/test/test_importlib/import_/test_relative_imports.py b/Lib/test/test_importlib/import_/test_relative_imports.py
--- a/Lib/test/test_importlib/import_/test_relative_imports.py
+++ b/Lib/test/test_importlib/import_/test_relative_imports.py
@@ -213,6 +213,11 @@
             with self.assertRaises(KeyError):
                 self.__import__('sys', level=1)
 
+    def test_relative_import_no_package(self):
+        with self.assertRaises(ImportError):
+            self.__import__('a', {'__package__': '', '__spec__': None},
+                            level=1)
+
 
 (Frozen_RelativeImports,
  Source_RelativeImports
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 Core and Builtins
 -----------------
 
+- Issue #18018: Import raises ImportError instead of SystemError if a relative
+  import is attempted without a known parent package.
+
 - Issue #25843: When compiling code, don't merge constants if they are equal
   but have a different types. For example, ``f1, f2 = lambda: 1, lambda: 1.0``
   is now correctly compiled to two different functions: ``f1()`` returns ``1``
diff --git a/Python/import.c b/Python/import.c
--- a/Python/import.c
+++ b/Python/import.c
@@ -1424,7 +1424,7 @@
                 PyErr_SetString(PyExc_TypeError, "package must be a string");
                 goto error;
             }
-            else if (spec != NULL) {
+            else if (spec != NULL && spec != Py_None) {
                 int equal;
                 PyObject *parent = PyObject_GetAttrString(spec, "parent");
                 if (parent == NULL) {
@@ -1444,7 +1444,7 @@
                 }
             }
         }
-        else if (spec != NULL) {
+        else if (spec != NULL && spec != Py_None) {
             package = PyObject_GetAttrString(spec, "parent");
             if (package == NULL) {
                 goto error;
@@ -1491,7 +1491,12 @@
             }
         }
 
-        if (PyDict_GetItem(interp->modules, package) == NULL) {
+        if (PyUnicode_CompareWithASCIIString(package, "") == 0) {
+            PyErr_SetString(PyExc_ImportError,
+                    "attempted relative import with no known parent package");
+            goto error;
+        }
+        else if (PyDict_GetItem(interp->modules, package) == NULL) {
             PyErr_Format(PyExc_SystemError,
                     "Parent module %R not loaded, cannot perform relative "
                     "import", package);

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list