changeset: 100054:c4e4886c6052 user: Brett Cannon date: Fri Jan 22 16:39:02 2016 -0800 files: Doc/whatsnew/3.6.rst Lib/test/test_importlib/import_/test_relative_imports.py Misc/NEWS Python/import.c description: 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. diff -r 9d65a195246b -r c4e4886c6052 Doc/whatsnew/3.6.rst --- a/Doc/whatsnew/3.6.rst Fri Jan 22 15:55:56 2016 -0800 +++ b/Doc/whatsnew/3.6.rst Fri Jan 22 16:39:02 2016 -0800 @@ -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 -r 9d65a195246b -r c4e4886c6052 Lib/test/test_importlib/import_/test_relative_imports.py --- a/Lib/test/test_importlib/import_/test_relative_imports.py Fri Jan 22 15:55:56 2016 -0800 +++ b/Lib/test/test_importlib/import_/test_relative_imports.py Fri Jan 22 16:39:02 2016 -0800 @@ -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 -r 9d65a195246b -r c4e4886c6052 Misc/NEWS --- a/Misc/NEWS Fri Jan 22 15:55:56 2016 -0800 +++ b/Misc/NEWS Fri Jan 22 16:39:02 2016 -0800 @@ -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 -r 9d65a195246b -r c4e4886c6052 Python/import.c --- a/Python/import.c Fri Jan 22 15:55:56 2016 -0800 +++ b/Python/import.c Fri Jan 22 16:39:02 2016 -0800 @@ -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);