[Jython-checkins] jython: Fix #2347, sensitivity to actual package in PEP 328 tests.
jeff.allen
jython-checkins at python.org
Mon May 4 23:24:14 CEST 2015
https://hg.python.org/jython/rev/22368d55fbce
changeset: 7701:22368d55fbce
user: Jeff Allen <ja.py at farowl.co.uk>
date: Sat May 02 23:32:52 2015 +0100
summary:
Fix #2347, sensitivity to actual package in PEP 328 tests.
The function TestImportFunction.top() is rewritten to return a dict
that will serve as a top-level module, irrespective of the actual
parentage of the test. Comments and optional diagnostic commentary have
been added, because module import is tricky to understand.
files:
Lib/test/test_import_pep328.py | 169 ++++++++++++++------
NEWS | 3 +
2 files changed, 123 insertions(+), 49 deletions(-)
diff --git a/Lib/test/test_import_pep328.py b/Lib/test/test_import_pep328.py
--- a/Lib/test/test_import_pep328.py
+++ b/Lib/test/test_import_pep328.py
@@ -33,6 +33,16 @@
import sys
import types
+EXPLAIN = False # If True, produce commentary in TestImportFunction
+
+def dump_module(m):
+ "Print values of attributes relevant to import mechanism"
+ if isinstance(m, types.ModuleType):
+ m = m.__dict__
+ print " Module name: {}".format(m.get('__name__', ''))
+ for n in ['__package__', '__path__']:
+ print " {:12s} = {}".format(n, m.get(n,''))
+
origImport = __import__
class TestImportStatementError(exceptions.ImportError):
@@ -179,45 +189,53 @@
self.assertEqual(a.level, 0)
-class TestImportFunctionError(exceptions.ImportError):
+class TestImportFunctionSuccess(exceptions.ImportError):
pass
class TestImportFunction(unittest.TestCase):
"""Test the '__import__' function
- This class tests, how the '__import__'-function
- resolves module names. It uses the 'meta_path' hook,
- to intercept the actual module loading.
-
- Module Structure:
+ This class tests, how the '__import__'-function resolves module names.
+ It uses the 'meta_path' hook, to intercept the actual module loading.
+ When consulted through find_module, it claims to have access to the
+ following module structure:
Top
- \---- X package
- | \-- Y package
- | | \-- Z1 module
- | | \-- Z2 module
- | \-- Y2 package
- \---- X2 module
+ +---- X package
+ | +-- Y package
+ | | +-- Z1 module
+ | | +-- Z2 module
+ | +-- Y2 package
+ +---- X2 module
"""
nameX = "TestImportFunctionX"
def setUp(self):
- self.modX = imp.new_module(self.nameX)
- self.modX.__path__ = ['X']
-
- self.modX2 = imp.new_module(self.nameX + "2")
- self.modY = imp.new_module(self.nameX + ".Y")
- self.modY.__path__ = ['X/Y']
- self.modY2 = imp.new_module(self.nameX + ".Y2")
- self.modY2.__path__ = ['X/Y']
- self.modZ1 = imp.new_module(self.nameX + ".Y.Z1")
- self.modZ2 = imp.new_module(self.nameX + ".Y.Z2")
-
+ self.modX = self._new_module(None, self.nameX, True)
+ self.modY = self._new_module(self.modX, "Y", True)
+ self.modZ1 = self._new_module(self.modY, "Z1")
+ self.modZ2 = self._new_module(self.modY, "Z2")
+ self.modY2 = self._new_module(self.modX, "Y2", True)
+ self.modX2 = self._new_module(None, self.nameX + "2")
self.expected = "something_completely_different"
sys.meta_path.insert(0, self)
+ @staticmethod
+ def _new_module(in_package, name, is_package=False):
+ if not in_package:
+ m = imp.new_module(name)
+ else:
+ m = imp.new_module(in_package.__name__ + '.' + name)
+ if is_package:
+ m.__package__ = m.__name__ # surprisingly not the parent name
+ else:
+ m.__package__ = in_package.__name__
+ if is_package:
+ m.__path__ = [m.__name__.replace('.', '/')]
+ return m
+
def tearDown(self):
try:
sys.meta_path.remove(self)
@@ -248,164 +266,217 @@
sys.modules[self.modZ1.__name__] = self.modZ1
self.modY.Z1 = self.modZ1
- def top(self):
- if sys.modules.has_key("__main__"):
- return sys.modules["__main__"].__dict__
- return globals()
+ @staticmethod
+ def top():
+ "Return the __dict__ of a non-package, top-level module"
+ # When this program runs as python -m test.test_import_pep328, it is
+ # called __main__, but is inside package test, so we must fake it.
+ myName = TestImportFunction.nameX[:-1] + "Top"
+ return {'__name__': myName, '__package__': None, '__file__': None}
def find_module(self, fullname, path=None):
+ # Simulate the operation of a module finder object on the sys.meta_path
+ if EXPLAIN:
+ print "find_module:"
+ print " fullname =", fullname
+ print " path =", path
if self.expected and self.expected != fullname:
+ # Equivalent of "import name" was called and the import mechanism is
+ # trying something other than the expected full name. For example, X
+ # called "import X2", and something other than X2 is tried (first).
return None
self.fullname = fullname
self.path = path
return self
def load_module(self, fullname):
+ # Masquerade as the loader matching fullname
self.assertEqual(fullname, self.fullname)
- raise TestImportFunctionError()
+ # Signal success, disguised as an ImportError
+ raise TestImportFunctionSuccess()
def runImport(self, expected, name, globals, fromlist=None, level=None):
self.expected = expected
if isinstance(globals, types.ModuleType):
globals = globals.__dict__
+ if EXPLAIN:
+ print "\nrunImport:"
+ dotname = ('.'*level if level>0 else '') + name
+ callername = globals['__name__']
+ callerpkg = globals.get('__package__', None)
+ if fromlist:
+ print " from {} import {} # in {} in package {}".format(
+ dotname, fromlist, callername, callerpkg)
+ else:
+ print " import {} # in {} in package {}".format(
+ dotname, callername, callerpkg)
try:
if level is not None:
__import__(name, globals, None, fromlist, level)
else:
__import__(name, globals, None, fromlist)
- except TestImportFunctionError:
+ except TestImportFunctionSuccess:
return
- self.fail("Expected a TestImportFunctionError")
+ self.fail("Expected a TestImportFunctionSuccess")
def testRelativeOrAbsolute_top_X2_1(self):
+ # In context of a non-package, top-level module, find X2.
+ # The finder should only be consulted with the absolute name.
self.runImport(None, self.modX2.__name__, self.top())
self.assertEqual(self.fullname, self.modX2.__name__)
self.assertEqual(self.path, None)
def testRelativeOrAbsolute_top_X2_2(self):
+ # In context of a non-package, top-level module, find X2.
+ # The finder should only be consulted with the absolute name.
self.runImport(None, self.modX2.__name__, self.top(), None, -1)
self.assertEqual(self.fullname, self.modX2.__name__)
self.assertEqual(self.path, None)
def testRelativeOrAbsolute_top_Y_1(self):
+ # In context of a non-package, top-level module, find X.Y.
+ # The finder should only be consulted with the absolute name.
self.importX()
self.runImport(None, self.modY.__name__, self.top())
self.assertEqual(self.fullname, self.modY.__name__)
- self.assertEqual(self.path, ['X'])
+ self.assertEqual(self.path, [self.nameX])
def testRelativeOrAbsolute_top_Y_2(self):
+ # In context of a non-package, top-level module, find X.Y.
+ # The finder should only be consulted with the absolute name.
self.importX()
self.runImport(None, self.modY.__name__, self.top(), None, -1)
self.assertEqual(self.fullname, self.modY.__name__)
- self.assertEqual(self.path, ['X'])
+ self.assertEqual(self.path, [self.nameX])
def testAbsolute_top_X2(self):
+ # In context of a non-package, top-level module, find X2 absolutely.
self.runImport(None, self.modX2.__name__, globals(), None, 0)
self.assertEqual(self.fullname, self.modX2.__name__)
self.assertEqual(self.path, None)
def testAbsolute_top_Y(self):
+ # In context of a non-package, top-level module, find X.Y absolutely.
self.importX()
self.runImport(None, self.modY.__name__, globals(), None, 0)
self.assertEqual(self.fullname, self.modY.__name__)
- self.assertEqual(self.path, ['X'])
+ self.assertEqual(self.path, [self.nameX])
# Relative case
def testRelativeOrAbsolute_X_X2_rel1(self):
+ # In context of package X, look for X2 at X.X2 (where actually it isn't).
self.importX()
self.runImport(None, self.modX2.__name__, self.modX)
self.assertEqual(self.fullname, self.nameX + "." + self.modX2.__name__)
- self.assertEqual(self.path, ['X'])
+ self.assertEqual(self.path, [self.nameX])
def testRelativeOrAbsolute_X_X2_rel2(self):
+ # In context of package X, look for X2 at X.X2 (where actually it isn't).
self.importX()
self.runImport(None, self.modX2.__name__, self.modX, None, -1)
- self.assertEqual(self.path, ['X'])
+ self.assertEqual(self.path, [self.nameX])
self.assertEqual(self.fullname, self.nameX + "." + self.modX2.__name__)
# Absolute case
def testRelativeOrAbsolute_X_X2_abs1(self):
+ # In context of package X, find X2 at absolute X2 (on second attempt).
self.importX()
self.runImport(self.modX2.__name__, self.modX2.__name__, self.modX)
self.assertEqual(self.fullname, self.modX2.__name__)
self.assertEqual(self.path, None)
def testRelativeOrAbsolute_X_X2_abs2(self):
+ # In context of package X, find X2 at absolute X2 (on second attempt).
self.importX()
self.runImport(self.modX2.__name__, self.modX2.__name__, self.modX, None, -1)
self.assertEqual(self.path, None)
self.assertEqual(self.fullname, self.modX2.__name__)
def testAbsolute_X_X2(self):
+ # In context of package X, find X2 at explicitly absolute X2.
self.importX()
self.runImport(None, self.modX2.__name__, self.modX, None, 0)
self.assertEqual(self.fullname, self.modX2.__name__)
self.assertEqual(self.path, None)
def testAbsolute_X_Y(self):
+ # In context of package X, find Y at explicitly absolute X.Y.
self.importX()
self.runImport(None, self.modY.__name__, self.modX, None, 0)
self.assertEqual(self.fullname, self.modY.__name__)
- self.assertEqual(self.path, ['X'])
+ self.assertEqual(self.path, [self.nameX])
def testRelative_Z1_Z2(self):
+ # In context of module Z1, from . import Z2.
self.importZ1()
self.runImport(None, "", self.modZ1, ['Z2'], 1)
self.assertEqual(self.fullname, self.modZ2.__name__)
- self.assertEqual(self.path, ['X/Y'])
+ self.assertEqual(self.path, [self.nameX + '/Y'])
def testRelative_Z1_Y2(self):
+ # In context of module Z1, from .. import Y2.
self.importZ1()
self.runImport(None, "", self.modZ1, ["Y2"], 2)
self.assertEqual(self.fullname, self.modX.__name__ + ".Y2")
- self.assertEqual(self.path, ['X'])
+ self.assertEqual(self.path, [self.nameX])
def testRelative_Z1_X2(self):
- # """beyond top level"""
+ # In context of module Z1, from ... import X2 (incorrectly beyond top level).
self.importZ1()
- self.assertRaises(ValueError, self.runImport, None, "", self.modZ1, [self.modX2.__name__], 3)
+ with self.assertRaises(ValueError):
+ self.runImport(None, "", self.modZ1, [self.modX2.__name__], 3)
def testRelative_X2_X(self):
- # """not a package"""
+ # In context of module X2, from . import X (incorrectly)
+ # This is incorrect as X2 is not in a package (is a top-level module).
self.importX2()
- self.assertRaises(ValueError, self.runImport, None, "", self.modX2, [self.modX.__name__], 1)
+ with self.assertRaises(ValueError):
+ self.runImport(None, "", self.modX2, [self.modX.__name__], 1)
def testRelative_X2_Y(self):
- # """not a package"""
+ # In context of module X2, from .X import Y (incorrectly).
+ # This is incorrect as X2 is not in a package (is a top-level module).
self.importX2()
self.importX()
- self.assertRaises(ValueError, self.runImport, None, self.modX.__name__, self.modX2, ["Y"], 1)
+ with self.assertRaises(ValueError):
+ self.runImport(None, self.modX.__name__, self.modX2, ["Y"], 1)
def testRelative_X_Z1_1(self):
+ # In context of package X, from .Y import Z1.
self.importX()
self.runImport(None, "Y", self.modX, ['Z1'], 1)
self.assertEqual(self.fullname, self.modY.__name__)
- self.assertEqual(self.path, ['X'])
+ self.assertEqual(self.path, [self.nameX])
def testRelative_X_Z1_2(self):
+ # In context of package X, from .Y import Z1.
self.importY()
self.runImport(None, "Y", self.modX, ['Z1'], 1)
self.assertEqual(self.fullname, self.modZ1.__name__)
- self.assertEqual(self.path, ['X/Y'])
+ self.assertEqual(self.path, [self.nameX + '/Y'])
def testRelative_Y_Z1(self):
+ # In context of package Y: from .Z1 import A, B.
self.importY()
self.runImport(None, "Z1", self.modY, ['A', 'B'], 1)
self.assertEqual(self.fullname, self.modZ1.__name__)
- self.assertEqual(self.path, ['X/Y'])
+ self.assertEqual(self.path, [self.nameX + '/Y'])
def testRelative_Y2_Z1_1(self):
+ # In context of package Y2, from ..Y import Z1.
self.importY2()
self.runImport(None, "Y", self.modY2, ['Z1'], 2)
self.assertEqual(self.fullname, self.modY.__name__)
- self.assertEqual(self.path, ['X'])
+ self.assertEqual(self.path, [self.nameX])
def testRelative_Y2_Z1_2(self):
+ # In context of package Y2, from ..Y import Z1.
self.importY2()
self.importY()
self.runImport(None, "Y", self.modY2, ['Z1'], 2)
self.assertEqual(self.fullname, self.modZ1.__name__)
- self.assertEqual(self.path, ['X/Y'])
+ self.assertEqual(self.path, [self.nameX + '/Y'])
+
try:
from test import test_support
diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,9 @@
For more details, please see https://hg.python.org/jython
+ Bugs fixed
+ - [ 2347 ] failures in test_import_pep328 when run with -m
+
Jython 2.7rc3
Bugs fixed
- [ 2326 ] Java's weakly consistent iteration of ConcurrentMap is compatible with mutation
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list