Skip to content

Commit bcaa3dc

Browse files
committed
Issue #17636: Circular imports involving relative imports are now supported.
1 parent 7f3978e commit bcaa3dc

13 files changed

Lines changed: 85 additions & 3 deletions

File tree

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ def tearDown(self):
568568

569569
def test_relimport_star(self):
570570
# This will import * from .test_import.
571-
from . import relimport
571+
from .. import relimport
572572
self.assertTrue(hasattr(relimport, "RelativeImportTests"))
573573

574574
def test_issue3221(self):
@@ -1068,6 +1068,46 @@ def test_unencodable_filename(self):
10681068
__isolated=False)
10691069

10701070

1071+
class CircularImportTests(unittest.TestCase):
1072+
1073+
"""See the docstrings of the modules being imported for the purpose of the
1074+
test."""
1075+
1076+
def tearDown(self):
1077+
"""Make sure no modules pre-exist in sys.modules which are being used to
1078+
test."""
1079+
for key in list(sys.modules.keys()):
1080+
if key.startswith('test.test_import.data.circular_imports'):
1081+
del sys.modules[key]
1082+
1083+
def test_direct(self):
1084+
try:
1085+
import test.test_import.data.circular_imports.basic
1086+
except ImportError:
1087+
self.fail('circular import through relative imports failed')
1088+
1089+
def test_indirect(self):
1090+
try:
1091+
import test.test_import.data.circular_imports.indirect
1092+
except ImportError:
1093+
self.fail('relative import in module contributing to circular '
1094+
'import failed')
1095+
1096+
def test_subpackage(self):
1097+
try:
1098+
import test.test_import.data.circular_imports.subpackage
1099+
except ImportError:
1100+
self.fail('circular import involving a subpackage failed')
1101+
1102+
def test_rebinding(self):
1103+
try:
1104+
import test.test_import.data.circular_imports.rebinding as rebinding
1105+
except ImportError:
1106+
self.fail('circular import with rebinding of module attribute failed')
1107+
from test.test_import.data.circular_imports.subpkg import util
1108+
self.assertIs(util.util, rebinding.util)
1109+
1110+
10711111
if __name__ == '__main__':
10721112
# Test needs to be a package, so we can do relative imports.
10731113
unittest.main()

Lib/test/test_import/__main__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import unittest
2+
3+
unittest.main('test.test_import')
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
"""Circular imports through direct, relative imports."""
2+
from . import basic2
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import basic
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import basic, basic2
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""Test the binding of names when a circular import shares the same name as an
2+
attribute."""
3+
from .rebinding2 import util
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .subpkg import util
2+
from . import rebinding
3+
util = util.util
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
"""Circular import involving a sub-package."""
2+
from .subpkg import subpackage2
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#from .util import util
2+
from .. import subpackage
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def util():
2+
pass

0 commit comments

Comments
 (0)