diff -r f81bdca9113d -r 311977bce179 Lib/test/test_import/__init__.py --- a/Lib/test/test_import/__init__.py Wed Jul 29 01:39:30 2015 +0200 +++ b/Lib/test/test_import/__init__.py Tue Jul 28 16:41:06 2015 -0700 @@ -1112,6 +1112,12 @@ from test.test_import.data.circular_imports.subpkg import util self.assertIs(util.util, rebinding.util) + def test_wildcard(self): + try: + import test.test_import.data.circular_imports.wildcard + except ImportError: + self.fail('circular import with a wildcard failed') + if __name__ == '__main__': # Test needs to be a package, so we can do relative imports. diff -r f81bdca9113d -r 311977bce179 Lib/test/test_import/data/circular_imports/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/test/test_import/data/circular_imports/__init__.py Tue Jul 28 16:41:06 2015 -0700 @@ -0,0 +1,1 @@ +__all__ = ['wildcard'] diff -r f81bdca9113d -r 311977bce179 Lib/test/test_import/data/circular_imports/wildcard.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/test/test_import/data/circular_imports/wildcard.py Tue Jul 28 16:41:06 2015 -0700 @@ -0,0 +1,2 @@ +"""Circular imports with from pkg import *""" +from . import * diff -r f81bdca9113d -r 311977bce179 Python/ceval.c --- a/Python/ceval.c Wed Jul 29 01:39:30 2015 +0200 +++ b/Python/ceval.c Tue Jul 28 16:41:06 2015 -0700 @@ -5105,8 +5105,10 @@ { _Py_IDENTIFIER(__all__); _Py_IDENTIFIER(__dict__); + _Py_IDENTIFIER(__name__); PyObject *all = _PyObject_GetAttrId(v, &PyId___all__); PyObject *dict, *name, *value; + PyObject *fullmodname, *pkgname; int skip_leading_underscores = 0; int pos, err; @@ -5147,6 +5149,33 @@ continue; } value = PyObject_GetAttr(v, name); + if (value == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) + { + /* Issue #23477: if a circular import happens within a wildcard + import, some partially loaded modules may not have been saved + to the package's __dict__ yet, so we'll try getting them from + sys.modules before giving up. + */ + PyErr_Clear(); + pkgname = _PyObject_GetAttrId(v, &PyId___name__); + if (pkgname != NULL) + { + fullmodname = PyUnicode_FromFormat("%U.%U", pkgname, name); + if (fullmodname != NULL) + { + value = PyDict_GetItem(PyImport_GetModuleDict(), + fullmodname); + if (value == NULL) + PyErr_Format(PyExc_ImportError, + "cannot import name %R", + name); + else + Py_INCREF(value); + Py_DECREF(fullmodname); + } + Py_DECREF(pkgname); + } + } if (value == NULL) err = -1; else if (PyDict_CheckExact(locals))