Skip to content

Commit a030bae

Browse files
[3.12] gh-117860: Add tests for resolving names when import rebind names (GH-118176) (GH-118432)
Add tests for "import", pkgutil.resolve_name() and unittest.mock.path() for cases when "import a.b as x" and "from a import b as x" give different results. (cherry picked from commit c0eaa23) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent 1b12ad5 commit a030bae

File tree

8 files changed

+149
-0
lines changed

8 files changed

+149
-0
lines changed

Lib/test/test_import/__init__.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,34 @@ def test_import_from_unloaded_package(self):
10891089
import package2.submodule1
10901090
package2.submodule1.submodule2
10911091

1092+
def test_rebinding(self):
1093+
# The same data is also used for testing pkgutil.resolve_name()
1094+
# in test_pkgutil and mock.patch in test_unittest.
1095+
path = os.path.join(os.path.dirname(__file__), 'data')
1096+
with uncache('package3', 'package3.submodule'), DirsOnSysPath(path):
1097+
from package3 import submodule
1098+
self.assertEqual(submodule.attr, 'rebound')
1099+
import package3.submodule as submodule
1100+
self.assertEqual(submodule.attr, 'rebound')
1101+
with uncache('package3', 'package3.submodule'), DirsOnSysPath(path):
1102+
import package3.submodule as submodule
1103+
self.assertEqual(submodule.attr, 'rebound')
1104+
from package3 import submodule
1105+
self.assertEqual(submodule.attr, 'rebound')
1106+
1107+
def test_rebinding2(self):
1108+
path = os.path.join(os.path.dirname(__file__), 'data')
1109+
with uncache('package4', 'package4.submodule'), DirsOnSysPath(path):
1110+
import package4.submodule as submodule
1111+
self.assertEqual(submodule.attr, 'submodule')
1112+
from package4 import submodule
1113+
self.assertEqual(submodule.attr, 'submodule')
1114+
with uncache('package4', 'package4.submodule'), DirsOnSysPath(path):
1115+
from package4 import submodule
1116+
self.assertEqual(submodule.attr, 'origin')
1117+
import package4.submodule as submodule
1118+
self.assertEqual(submodule.attr, 'submodule')
1119+
10921120

10931121
class OverridingImportBuiltinTests(unittest.TestCase):
10941122
def test_override_builtin(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
"""Rebinding the package attribute after importing the module."""
2+
from .submodule import submodule
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
attr = 'submodule'
2+
class A:
3+
attr = 'submodule'
4+
class submodule:
5+
attr = 'rebound'
6+
class B:
7+
attr = 'rebound'
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""Binding the package attribute without importing the module."""
2+
class submodule:
3+
attr = 'origin'
4+
class B:
5+
attr = 'origin'
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
attr = 'submodule'
2+
class A:
3+
attr = 'submodule'

Lib/test/test_pkgutil.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
import shutil
1313
import zipfile
1414

15+
from test.support.import_helper import DirsOnSysPath
16+
from test.test_importlib.util import uncache
17+
1518
# Note: pkgutil.walk_packages is currently tested in test_runpy. This is
1619
# a hack to get a major issue resolved for 3.3b2. Longer term, it should
1720
# be moved back here, perhaps by factoring out the helper code for
@@ -318,6 +321,38 @@ def test_name_resolution(self):
318321
with self.assertRaises(exc):
319322
pkgutil.resolve_name(s)
320323

324+
def test_name_resolution_import_rebinding(self):
325+
# The same data is also used for testing import in test_import and
326+
# mock.patch in test_unittest.
327+
path = os.path.join(os.path.dirname(__file__), 'test_import', 'data')
328+
with uncache('package3', 'package3.submodule'), DirsOnSysPath(path):
329+
self.assertEqual(pkgutil.resolve_name('package3.submodule.attr'), 'submodule')
330+
with uncache('package3', 'package3.submodule'), DirsOnSysPath(path):
331+
self.assertEqual(pkgutil.resolve_name('package3.submodule:attr'), 'submodule')
332+
with uncache('package3', 'package3.submodule'), DirsOnSysPath(path):
333+
self.assertEqual(pkgutil.resolve_name('package3:submodule.attr'), 'rebound')
334+
self.assertEqual(pkgutil.resolve_name('package3.submodule.attr'), 'submodule')
335+
self.assertEqual(pkgutil.resolve_name('package3:submodule.attr'), 'rebound')
336+
with uncache('package3', 'package3.submodule'), DirsOnSysPath(path):
337+
self.assertEqual(pkgutil.resolve_name('package3:submodule.attr'), 'rebound')
338+
self.assertEqual(pkgutil.resolve_name('package3.submodule:attr'), 'submodule')
339+
self.assertEqual(pkgutil.resolve_name('package3:submodule.attr'), 'rebound')
340+
341+
def test_name_resolution_import_rebinding2(self):
342+
path = os.path.join(os.path.dirname(__file__), 'test_import', 'data')
343+
with uncache('package4', 'package4.submodule'), DirsOnSysPath(path):
344+
self.assertEqual(pkgutil.resolve_name('package4.submodule.attr'), 'submodule')
345+
with uncache('package4', 'package4.submodule'), DirsOnSysPath(path):
346+
self.assertEqual(pkgutil.resolve_name('package4.submodule:attr'), 'submodule')
347+
with uncache('package4', 'package4.submodule'), DirsOnSysPath(path):
348+
self.assertEqual(pkgutil.resolve_name('package4:submodule.attr'), 'origin')
349+
self.assertEqual(pkgutil.resolve_name('package4.submodule.attr'), 'submodule')
350+
self.assertEqual(pkgutil.resolve_name('package4:submodule.attr'), 'submodule')
351+
with uncache('package4', 'package4.submodule'), DirsOnSysPath(path):
352+
self.assertEqual(pkgutil.resolve_name('package4:submodule.attr'), 'origin')
353+
self.assertEqual(pkgutil.resolve_name('package4.submodule:attr'), 'submodule')
354+
self.assertEqual(pkgutil.resolve_name('package4:submodule.attr'), 'submodule')
355+
321356

322357
class PkgutilPEP302Tests(unittest.TestCase):
323358

Lib/test/test_unittest/testmock/testpatch.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
from collections import OrderedDict
88

99
import unittest
10+
import test
1011
from test.test_unittest.testmock import support
1112
from test.test_unittest.testmock.support import SomeClass, is_instance
1213

14+
from test.support.import_helper import DirsOnSysPath
1315
from test.test_importlib.util import uncache
1416
from unittest.mock import (
1517
NonCallableMock, CallableMixin, sentinel,
@@ -1728,6 +1730,71 @@ def test(mock):
17281730
'exception traceback not propagated')
17291731

17301732

1733+
def test_name_resolution_import_rebinding(self):
1734+
# Currently mock.patch uses pkgutil.resolve_name(), but repeat
1735+
# similar tests just for the case.
1736+
# The same data is also used for testing import in test_import and
1737+
# pkgutil.resolve_name() in test_pkgutil.
1738+
path = os.path.join(os.path.dirname(test.__file__), 'test_import', 'data')
1739+
def check(name):
1740+
p = patch(name)
1741+
p.start()
1742+
p.stop()
1743+
def check_error(name):
1744+
p = patch(name)
1745+
self.assertRaises(AttributeError, p.start)
1746+
with uncache('package3', 'package3.submodule'), DirsOnSysPath(path):
1747+
check('package3.submodule.A.attr')
1748+
check_error('package3.submodule.B.attr')
1749+
with uncache('package3', 'package3.submodule'), DirsOnSysPath(path):
1750+
check('package3.submodule:A.attr')
1751+
check_error('package3.submodule:B.attr')
1752+
with uncache('package3', 'package3.submodule'), DirsOnSysPath(path):
1753+
check('package3:submodule.B.attr')
1754+
check_error('package3:submodule.A.attr')
1755+
check('package3.submodule.A.attr')
1756+
check_error('package3.submodule.B.attr')
1757+
check('package3:submodule.B.attr')
1758+
check_error('package3:submodule.A.attr')
1759+
with uncache('package3', 'package3.submodule'), DirsOnSysPath(path):
1760+
check('package3:submodule.B.attr')
1761+
check_error('package3:submodule.A.attr')
1762+
check('package3.submodule:A.attr')
1763+
check_error('package3.submodule:B.attr')
1764+
check('package3:submodule.B.attr')
1765+
check_error('package3:submodule.A.attr')
1766+
1767+
def test_name_resolution_import_rebinding2(self):
1768+
path = os.path.join(os.path.dirname(test.__file__), 'test_import', 'data')
1769+
def check(name):
1770+
p = patch(name)
1771+
p.start()
1772+
p.stop()
1773+
def check_error(name):
1774+
p = patch(name)
1775+
self.assertRaises(AttributeError, p.start)
1776+
with uncache('package4', 'package4.submodule'), DirsOnSysPath(path):
1777+
check('package4.submodule.A.attr')
1778+
check_error('package4.submodule.B.attr')
1779+
with uncache('package4', 'package4.submodule'), DirsOnSysPath(path):
1780+
check('package4.submodule:A.attr')
1781+
check_error('package4.submodule:B.attr')
1782+
with uncache('package4', 'package4.submodule'), DirsOnSysPath(path):
1783+
check('package4:submodule.B.attr')
1784+
check_error('package4:submodule.A.attr')
1785+
check('package4.submodule.A.attr')
1786+
check_error('package4.submodule.B.attr')
1787+
check('package4:submodule.A.attr')
1788+
check_error('package4:submodule.B.attr')
1789+
with uncache('package4', 'package4.submodule'), DirsOnSysPath(path):
1790+
check('package4:submodule.B.attr')
1791+
check_error('package4:submodule.A.attr')
1792+
check('package4.submodule:A.attr')
1793+
check_error('package4.submodule:B.attr')
1794+
check('package4:submodule.A.attr')
1795+
check_error('package4:submodule.B.attr')
1796+
1797+
17311798
def test_create_and_specs(self):
17321799
for kwarg in ('spec', 'spec_set', 'autospec'):
17331800
p = patch('%s.doesnotexist' % __name__, create=True,

Makefile.pre.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2157,6 +2157,8 @@ TESTSUBDIRS= idlelib/idle_test \
21572157
test/test_import/data/circular_imports/subpkg2/parent \
21582158
test/test_import/data/package \
21592159
test/test_import/data/package2 \
2160+
test/test_import/data/package3 \
2161+
test/test_import/data/package4 \
21602162
test/test_import/data/unwritable \
21612163
test/test_importlib \
21622164
test/test_importlib/builtin \

0 commit comments

Comments
 (0)