summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrett Cannon <brett@python.org>2016-01-23 00:39:02 (GMT)
committerBrett Cannon <brett@python.org>2016-01-23 00:39:02 (GMT)
commit9fa812668faf0d2d7839845e1a0da19b87bdbc29 (patch)
tree80c2c811909e691d6ab1fc2fea7ad9ca1619bdd7
parent4b18dd339a9919e6f5fa3485c8b871ed19d9e391 (diff)
downloadcpython-9fa812668faf0d2d7839845e1a0da19b87bdbc29.zip
cpython-9fa812668faf0d2d7839845e1a0da19b87bdbc29.tar.gz
cpython-9fa812668faf0d2d7839845e1a0da19b87bdbc29.tar.bz2
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.
-rw-r--r--Doc/whatsnew/3.6.rst4
-rw-r--r--Lib/test/test_importlib/import_/test_relative_imports.py5
-rw-r--r--Misc/NEWS3
-rw-r--r--Python/import.c11
4 files changed, 20 insertions, 3 deletions
diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst
index 5872cc0..158dad3 100644
--- a/Doc/whatsnew/3.6.rst
+++ b/Doc/whatsnew/3.6.rst
@@ -278,6 +278,10 @@ Changes in the Python API
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
index 0409f22..1cad6b3 100644
--- a/Lib/test/test_importlib/import_/test_relative_imports.py
+++ b/Lib/test/test_importlib/import_/test_relative_imports.py
@@ -213,6 +213,11 @@ class RelativeImports:
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
index 165b428..676f2ca 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ Release date: tba
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
index 22f9d21..8ad5b4c 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -1424,7 +1424,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
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 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
}
}
}
- 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 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
}
}
- 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);