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
--------------------
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
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``
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) {
}
}
}
- else if (spec != NULL) {
+ else if (spec != NULL && spec != Py_None) {
package = PyObject_GetAttrString(spec, "parent");
if (package == NULL) {
goto error;
}
}
- 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);