mirror of https://github.com/python/cpython
Merge.
This commit is contained in:
commit
4fa7a9fd1a
|
@ -568,7 +568,7 @@ class RelativeImportTests(unittest.TestCase):
|
||||||
|
|
||||||
def test_relimport_star(self):
|
def test_relimport_star(self):
|
||||||
# This will import * from .test_import.
|
# This will import * from .test_import.
|
||||||
from . import relimport
|
from .. import relimport
|
||||||
self.assertTrue(hasattr(relimport, "RelativeImportTests"))
|
self.assertTrue(hasattr(relimport, "RelativeImportTests"))
|
||||||
|
|
||||||
def test_issue3221(self):
|
def test_issue3221(self):
|
||||||
|
@ -1068,6 +1068,46 @@ class ImportTracebackTests(unittest.TestCase):
|
||||||
__isolated=False)
|
__isolated=False)
|
||||||
|
|
||||||
|
|
||||||
|
class CircularImportTests(unittest.TestCase):
|
||||||
|
|
||||||
|
"""See the docstrings of the modules being imported for the purpose of the
|
||||||
|
test."""
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""Make sure no modules pre-exist in sys.modules which are being used to
|
||||||
|
test."""
|
||||||
|
for key in list(sys.modules.keys()):
|
||||||
|
if key.startswith('test.test_import.data.circular_imports'):
|
||||||
|
del sys.modules[key]
|
||||||
|
|
||||||
|
def test_direct(self):
|
||||||
|
try:
|
||||||
|
import test.test_import.data.circular_imports.basic
|
||||||
|
except ImportError:
|
||||||
|
self.fail('circular import through relative imports failed')
|
||||||
|
|
||||||
|
def test_indirect(self):
|
||||||
|
try:
|
||||||
|
import test.test_import.data.circular_imports.indirect
|
||||||
|
except ImportError:
|
||||||
|
self.fail('relative import in module contributing to circular '
|
||||||
|
'import failed')
|
||||||
|
|
||||||
|
def test_subpackage(self):
|
||||||
|
try:
|
||||||
|
import test.test_import.data.circular_imports.subpackage
|
||||||
|
except ImportError:
|
||||||
|
self.fail('circular import involving a subpackage failed')
|
||||||
|
|
||||||
|
def test_rebinding(self):
|
||||||
|
try:
|
||||||
|
import test.test_import.data.circular_imports.rebinding as rebinding
|
||||||
|
except ImportError:
|
||||||
|
self.fail('circular import with rebinding of module attribute failed')
|
||||||
|
from test.test_import.data.circular_imports.subpkg import util
|
||||||
|
self.assertIs(util.util, rebinding.util)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Test needs to be a package, so we can do relative imports.
|
# Test needs to be a package, so we can do relative imports.
|
||||||
unittest.main()
|
unittest.main()
|
|
@ -0,0 +1,3 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
unittest.main('test.test_import')
|
|
@ -0,0 +1,2 @@
|
||||||
|
"""Circular imports through direct, relative imports."""
|
||||||
|
from . import basic2
|
|
@ -0,0 +1 @@
|
||||||
|
from . import basic
|
|
@ -0,0 +1 @@
|
||||||
|
from . import basic, basic2
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""Test the binding of names when a circular import shares the same name as an
|
||||||
|
attribute."""
|
||||||
|
from .rebinding2 import util
|
|
@ -0,0 +1,3 @@
|
||||||
|
from .subpkg import util
|
||||||
|
from . import rebinding
|
||||||
|
util = util.util
|
|
@ -0,0 +1,2 @@
|
||||||
|
"""Circular import involving a sub-package."""
|
||||||
|
from .subpkg import subpackage2
|
|
@ -0,0 +1,2 @@
|
||||||
|
#from .util import util
|
||||||
|
from .. import subpackage
|
|
@ -0,0 +1,2 @@
|
||||||
|
def util():
|
||||||
|
pass
|
|
@ -0,0 +1,2 @@
|
||||||
|
def util():
|
||||||
|
pass
|
|
@ -10,6 +10,9 @@ Release date: TBA
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #17636: Circular imports involving relative imports are now
|
||||||
|
supported.
|
||||||
|
|
||||||
- Issue #22604: Fix assertion error in debug mode when dividing a complex
|
- Issue #22604: Fix assertion error in debug mode when dividing a complex
|
||||||
number by (nan+0j).
|
number by (nan+0j).
|
||||||
|
|
||||||
|
|
|
@ -4693,11 +4693,29 @@ static PyObject *
|
||||||
import_from(PyObject *v, PyObject *name)
|
import_from(PyObject *v, PyObject *name)
|
||||||
{
|
{
|
||||||
PyObject *x;
|
PyObject *x;
|
||||||
|
_Py_IDENTIFIER(__name__);
|
||||||
|
PyObject *fullmodname, *pkgname;
|
||||||
|
|
||||||
x = PyObject_GetAttr(v, name);
|
x = PyObject_GetAttr(v, name);
|
||||||
if (x == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
if (x != NULL || !PyErr_ExceptionMatches(PyExc_AttributeError))
|
||||||
|
return x;
|
||||||
|
/* Issue #17636: in case this failed because of a circular relative
|
||||||
|
import, try to fallback on reading the module directly from
|
||||||
|
sys.modules. */
|
||||||
|
PyErr_Clear();
|
||||||
|
pkgname = _PyObject_GetAttrId(v, &PyId___name__);
|
||||||
|
if (pkgname == NULL)
|
||||||
|
return NULL;
|
||||||
|
fullmodname = PyUnicode_FromFormat("%U.%U", pkgname, name);
|
||||||
|
Py_DECREF(pkgname);
|
||||||
|
if (fullmodname == NULL)
|
||||||
|
return NULL;
|
||||||
|
x = PyDict_GetItem(PyImport_GetModuleDict(), fullmodname);
|
||||||
|
if (x == NULL)
|
||||||
PyErr_Format(PyExc_ImportError, "cannot import name %R", name);
|
PyErr_Format(PyExc_ImportError, "cannot import name %R", name);
|
||||||
}
|
else
|
||||||
|
Py_INCREF(x);
|
||||||
|
Py_DECREF(fullmodname);
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue