Index: Lib/test/test_import_pep328.py =================================================================== --- Lib/test/test_import_pep328.py (revision 0) +++ Lib/test/test_import_pep328.py (revision 0) @@ -0,0 +1,419 @@ +# test_import_pep328 - Test various aspects of import +# +# Copyright (c) 2010 by science+computing ag +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at# +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Licensed to PSF under a Contributor Agreement. +# See http://www.python.org/2.4/license for licensing details. + +''' +Import related tests: + +- Test how 'import ...' and 'from ... import ...' invoke the + '__import__' function. +- Test the module name resolution of the '__import__'-function. + +The reference is C-python. +''' +import unittest +import exceptions +import imp +import __builtin__ +import sys +import types + +origImport = __import__ + +class TestImportStatementError(exceptions.ImportError): + def __init__(self, args): + names = ['name', 'globals', 'locals', 'fromlist', 'level'] + self.len = len(args) + for a in args: + n = names.pop(0) + setattr(self, n, a) + for n in names: + setattr(self, n, None) + + +class TestImportStatement(unittest.TestCase): + """Test the 'import' and 'from ... import' statements + + This class tests, how the compiler calls the + '__import__'-function for various forms of the + 'import' and 'from ... import' statements. + """ + + AI = "from __future__ import absolute_import ;" + + def importFunction(*args): + if args[0] == '__future__': + return origImport(*args) + raise TestImportStatementError(args) + importFunction = staticmethod(importFunction) + + def setUp(self): + __builtin__.__import__ = self.importFunction + + def tearDown(self): + __builtin__.__import__ = origImport + + def runImport(self, statement): + l = {} + g = {} + try: + exec statement in g, l + except TestImportStatementError,e: + self.assert_(e.globals is g, "globals is changed") + self.assert_(e.locals is l, "locals is changed") + return e + self.fail("Expected a TestImportStatementError") + + def testFromDotsOnly(self): + dots = '' + for i in range(1,10): + dots += '.' + a = self.runImport("from %s import (A,B)" % (dots,)) + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "") + self.assertEqual(a.level, i) + self.assertEqual(a.fromlist, ('A', 'B')) + + def testFromDotsOnlyAs(self): + dots = '' + for i in range(1,10): + dots += '.' + a = self.runImport("from %s import A as B" % (dots,)) + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "") + self.assertEqual(a.fromlist, ('A',)) + self.assertEqual(a.level, i) + + def testFromDotsAndName(self): + dots = '' + for i in range(1,10): + dots += '.' + a = self.runImport("from %sX import A" % (dots,)) + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "X") + self.assertEqual(a.fromlist, ('A',)) + self.assertEqual(a.level, i) + + def testFromDotsAndDotedName(self): + dots = '' + for i in range(1,10): + dots += '.' + a = self.runImport("from %sX.Y import A" % (dots,)) + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, ('A',)) + self.assertEqual(a.level, i) + + def testAbsoluteFromDotedNameAs(self): + a = self.runImport(self.AI + "from X.Y import A as B") + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, ('A',)) + self.assertEqual(a.level, 0) + + def testRelativeOrAbsoluteFromDotedNameAs(self): + a = self.runImport("from X.Y import A as B") + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, ('A',)) + self.assertEqual(a.len, 4) + + def testAbsoluteFromDotedNameAll(self): + a = self.runImport(self.AI + "from X.Y import *") + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, ('*',)) + self.assertEqual(a.level, 0) + + def testRelativeOrAbsoluteFromDotedNameAll(self): + a = self.runImport("from X.Y import *") + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, ('*',)) + self.assertEqual(a.len, 4) + + def testAbsoluteImportName(self): + a = self.runImport(self.AI + "import X") + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "X") + self.assertEqual(a.fromlist, None) + self.assertEqual(a.level, 0) + + def testAbsoluteImportDotedName(self): + a = self.runImport(self.AI + "import X.Y") + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, None) + self.assertEqual(a.level, 0) + + def testRelativeOrAbsoluteImportName(self): + a = self.runImport("import X") + self.assertEqual(a.name, "X") + self.assertEqual(a.fromlist, None) + self.assertEqual(a.len, 4) + + def testRelativeOrAbsoluteImportDotedName(self): + a = self.runImport("import X.Y") + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, None) + self.assertEqual(a.len, 4) + + def testAbsoluteImportDotedNameAs(self): + a = self.runImport(self.AI + "import X.Y as Z") + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, None) + self.assertEqual(a.level, 0) + + +class TestImportFunctionError(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: + + Top + \---- 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.expected = "something_completely_different" + sys.meta_path.insert(0, self) + + def tearDown(self): + try: + sys.meta_path.remove(self) + except ValueError: + pass + for k in sys.modules.keys(): + if k.startswith(self.nameX): + del sys.modules[k] + + def importX(self): + sys.modules[self.modX.__name__] = self.modX + def importX2(self): + sys.modules[self.modX2.__name__] = self.modX2 + def importY(self): + self.importX() + sys.modules[self.modY.__name__] = self.modY + self.modX.Y = self.modY + def importY2(self): + self.importX() + sys.modules[self.modY2.__name__] = self.modY2 + self.modX.Y2 = self.modY2 + def importZ1(self): + self.importY() + 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() + + + def find_module(self, fullname, path=None): + if self.expected and self.expected != fullname: + return None + self.fullname = fullname + self.path = path + return self + + def load_module(self, fullname): + self.assertEqual(fullname, self.fullname) + raise TestImportFunctionError() + + def runImport(self, expected, name, globals, fromlist=None, level=None): + self.expected = expected + if isinstance(globals, types.ModuleType): + globals = globals.__dict__ + try: + if level is not None: + __import__(name, globals, None, fromlist, level) + else: + __import__(name, globals, None, fromlist) + except TestImportFunctionError: + return + self.fail("Expected a TestImportFunctionError") + + def testRelativeOrAbsolute_top_X2_1(self): + 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): + 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): + self.importX() + self.runImport(None, self.modY.__name__, self.top()) + self.assertEqual(self.fullname, self.modY.__name__) + self.assertEqual(self.path, ['X']) + + def testRelativeOrAbsolute_top_Y_2(self): + self.importX() + self.runImport(None, self.modY.__name__, self.top(), None, -1) + self.assertEqual(self.fullname, self.modY.__name__) + self.assertEqual(self.path, ['X']) + + + def testAbsolute_top_X2(self): + 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): + self.importX() + self.runImport(None, self.modY.__name__, globals(), None, 0) + self.assertEqual(self.fullname, self.modY.__name__) + self.assertEqual(self.path, ['X']) + + # Relative case + def testRelativeOrAbsolute_X_X2_rel1(self): + self.importX() + self.runImport(None, self.modX2.__name__, self.modX) + self.assertEqual(self.fullname, self.nameX + "." + self.modX2.__name__) + self.assertEqual(self.path, ['X']) + + def testRelativeOrAbsolute_X_X2_rel2(self): + self.importX() + self.runImport(None, self.modX2.__name__, self.modX, None, -1) + self.assertEqual(self.path, ['X']) + self.assertEqual(self.fullname, self.nameX + "." + self.modX2.__name__) + + # Absolute case + def testRelativeOrAbsolute_X_X2_abs1(self): + 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): + 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): + 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): + self.importX() + self.runImport(None, self.modY.__name__, self.modX, None, 0) + self.assertEqual(self.fullname, self.modY.__name__) + self.assertEqual(self.path, ['X']) + + def testRelative_Z1_Z2(self): + self.importZ1() + self.runImport(None, "", self.modZ1, ['Z2'], 1) + self.assertEqual(self.fullname, self.modZ2.__name__) + self.assertEqual(self.path, ['X/Y']) + + def testRelative_Z1_Y2(self): + self.importZ1() + self.runImport(None, "", self.modZ1, ["Y2"], 2) + self.assertEqual(self.fullname, self.modX.__name__+".Y2") + self.assertEqual(self.path, ['X']) + + def testRelative_Z1_X2(self): + # """beyond top level""" + self.importZ1() + self.assertRaises(ValueError, self.runImport, None, "", self.modZ1, [self.modX2.__name__], 3) + + def testRelative_X2_X(self): + # """not a package""" + self.importX2() + self.assertRaises(ValueError, self.runImport, None, "", self.modX2, [self.modX.__name__], 1) + + def testRelative_X2_Y(self): + # """not a package""" + self.importX2() + self.importX() + self.assertRaises(ValueError, self.runImport, None, self.modX.__name__, self.modX2, ["Y"], 1) + + def testRelative_X_Z1_1(self): + self.importX() + self.runImport(None, "Y", self.modX, ['Z1'], 1) + self.assertEqual(self.fullname, self.modY.__name__) + self.assertEqual(self.path, ['X']) + + def testRelative_X_Z1_2(self): + self.importY() + self.runImport(None, "Y", self.modX, ['Z1'], 1) + self.assertEqual(self.fullname, self.modZ1.__name__) + self.assertEqual(self.path, ['X/Y']) + + def testRelative_Y_Z1(self): + self.importY() + self.runImport(None, "Z1", self.modY, ['A', 'B'], 1) + self.assertEqual(self.fullname, self.modZ1.__name__) + self.assertEqual(self.path, ['X/Y']) + + def testRelative_Y2_Z1_1(self): + self.importY2() + self.runImport(None, "Y", self.modY2, ['Z1'], 2) + self.assertEqual(self.fullname, self.modY.__name__) + self.assertEqual(self.path, ['X']) + + def testRelative_Y2_Z1_2(self): + 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']) + +try: + from test import test_support +except ImportError: + test_main = unittest.main +else: + def test_main(): + test_support.run_unittest(TestImportStatement, + TestImportFunction) + +if __name__ == '__main__': + test_main()