blob: a0f6b2d827db61fec37d34b3e07db543d87f9807 [file] [log] [blame]
Brett Cannon23cbd8a2009-01-18 00:24:28 +00001"""Test relative imports (PEP 328)."""
Brett Cannonbcb26c52009-02-01 04:00:05 +00002from .. import util
Brett Cannond720b362009-02-01 04:28:04 +00003from . import util as import_util
Brett Cannon23cbd8a2009-01-18 00:24:28 +00004import sys
5import unittest
6
7class RelativeImports(unittest.TestCase):
8
9 """PEP 328 introduced relative imports. This allows for imports to occur
10 from within a package without having to specify the actual package name.
11
12 A simple example is to import another module within the same package
13 [module from module]::
14
15 # From pkg.mod1 with pkg.mod2 being a module.
16 from . import mod2
17
18 This also works for getting an attribute from a module that is specified
19 in a relative fashion [attr from module]::
20
21 # From pkg.mod1.
22 from .mod2 import attr
23
24 But this is in no way restricted to working between modules; it works
25 from [package to module],::
26
27 # From pkg, importing pkg.module which is a module.
28 from . import module
29
30 [module to package],::
31
32 # Pull attr from pkg, called from pkg.module which is a module.
33 from . import attr
34
35 and [package to package]::
36
37 # From pkg.subpkg1 (both pkg.subpkg[1,2] are packages).
38 from .. import subpkg2
39
40 The number of dots used is in no way restricted [deep import]::
41
42 # Import pkg.attr from pkg.pkg1.pkg2.pkg3.pkg4.pkg5.
43 from ...... import attr
44
45 To prevent someone from accessing code that is outside of a package, one
46 cannot reach the location containing the root package itself::
47
48 # From pkg.__init__ [too high from package]
49 from .. import top_level
50
51 # From pkg.module [too high from module]
52 from .. import top_level
53
54 Relative imports are the only type of import that allow for an empty
55 module name for an import [empty name].
56
57 """
58
59 def relative_import_test(self, create, globals_, callback):
60 """Abstract out boilerplace for setting up for an import test."""
61 uncache_names = []
62 for name in create:
63 if not name.endswith('.__init__'):
64 uncache_names.append(name)
65 else:
66 uncache_names.append(name[:-len('.__init__')])
Brett Cannonbcb26c52009-02-01 04:00:05 +000067 with util.mock_modules(*create) as importer:
68 with util.import_state(meta_path=[importer]):
Brett Cannon23cbd8a2009-01-18 00:24:28 +000069 for global_ in globals_:
Brett Cannonbcb26c52009-02-01 04:00:05 +000070 with util.uncache(*uncache_names):
Brett Cannon23cbd8a2009-01-18 00:24:28 +000071 callback(global_)
72
73
74 def test_module_from_module(self):
75 # [module from module]
76 create = 'pkg.__init__', 'pkg.mod2'
77 globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.mod1'}
78 def callback(global_):
Brett Cannond720b362009-02-01 04:28:04 +000079 import_util.import_('pkg') # For __import__().
80 module = import_util.import_('', global_, fromlist=['mod2'], level=1)
Brett Cannon23cbd8a2009-01-18 00:24:28 +000081 self.assertEqual(module.__name__, 'pkg')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000082 self.assertTrue(hasattr(module, 'mod2'))
Brett Cannon23cbd8a2009-01-18 00:24:28 +000083 self.assertEqual(module.mod2.attr, 'pkg.mod2')
84 self.relative_import_test(create, globals_, callback)
85
86 def test_attr_from_module(self):
87 # [attr from module]
88 create = 'pkg.__init__', 'pkg.mod2'
89 globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.mod1'}
90 def callback(global_):
Brett Cannond720b362009-02-01 04:28:04 +000091 import_util.import_('pkg') # For __import__().
92 module = import_util.import_('mod2', global_, fromlist=['attr'],
93 level=1)
Brett Cannon23cbd8a2009-01-18 00:24:28 +000094 self.assertEqual(module.__name__, 'pkg.mod2')
95 self.assertEqual(module.attr, 'pkg.mod2')
96 self.relative_import_test(create, globals_, callback)
97
98 def test_package_to_module(self):
99 # [package to module]
100 create = 'pkg.__init__', 'pkg.module'
101 globals_ = ({'__package__': 'pkg'},
102 {'__name__': 'pkg', '__path__': ['blah']})
103 def callback(global_):
Brett Cannond720b362009-02-01 04:28:04 +0000104 import_util.import_('pkg') # For __import__().
105 module = import_util.import_('', global_, fromlist=['module'],
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000106 level=1)
107 self.assertEqual(module.__name__, 'pkg')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000108 self.assertTrue(hasattr(module, 'module'))
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000109 self.assertEqual(module.module.attr, 'pkg.module')
110 self.relative_import_test(create, globals_, callback)
111
112 def test_module_to_package(self):
113 # [module to package]
114 create = 'pkg.__init__', 'pkg.module'
115 globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.module'}
116 def callback(global_):
Brett Cannond720b362009-02-01 04:28:04 +0000117 import_util.import_('pkg') # For __import__().
118 module = import_util.import_('', global_, fromlist=['attr'], level=1)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000119 self.assertEqual(module.__name__, 'pkg')
120 self.relative_import_test(create, globals_, callback)
121
122 def test_package_to_package(self):
123 # [package to package]
124 create = ('pkg.__init__', 'pkg.subpkg1.__init__',
125 'pkg.subpkg2.__init__')
126 globals_ = ({'__package__': 'pkg.subpkg1'},
127 {'__name__': 'pkg.subpkg1', '__path__': ['blah']})
128 def callback(global_):
Brett Cannond720b362009-02-01 04:28:04 +0000129 module = import_util.import_('', global_, fromlist=['subpkg2'],
130 level=2)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000131 self.assertEqual(module.__name__, 'pkg')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000132 self.assertTrue(hasattr(module, 'subpkg2'))
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000133 self.assertEqual(module.subpkg2.attr, 'pkg.subpkg2.__init__')
134
135 def test_deep_import(self):
136 # [deep import]
137 create = ['pkg.__init__']
138 for count in range(1,6):
139 create.append('{0}.pkg{1}.__init__'.format(
140 create[-1][:-len('.__init__')], count))
141 globals_ = ({'__package__': 'pkg.pkg1.pkg2.pkg3.pkg4.pkg5'},
142 {'__name__': 'pkg.pkg1.pkg2.pkg3.pkg4.pkg5',
143 '__path__': ['blah']})
144 def callback(global_):
Brett Cannond720b362009-02-01 04:28:04 +0000145 import_util.import_(globals_[0]['__package__'])
146 module = import_util.import_('', global_, fromlist=['attr'], level=6)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000147 self.assertEqual(module.__name__, 'pkg')
148 self.relative_import_test(create, globals_, callback)
149
150 def test_too_high_from_package(self):
151 # [too high from package]
152 create = ['top_level', 'pkg.__init__']
153 globals_ = ({'__package__': 'pkg'},
154 {'__name__': 'pkg', '__path__': ['blah']})
155 def callback(global_):
Brett Cannond720b362009-02-01 04:28:04 +0000156 import_util.import_('pkg')
Brett Cannon2153dc02009-08-27 23:49:21 +0000157 with self.assertRaises(ValueError):
158 import_util.import_('', global_, fromlist=['top_level'],
159 level=2)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000160 self.relative_import_test(create, globals_, callback)
161
162 def test_too_high_from_module(self):
163 # [too high from module]
164 create = ['top_level', 'pkg.__init__', 'pkg.module']
165 globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.module'}
166 def callback(global_):
Brett Cannond720b362009-02-01 04:28:04 +0000167 import_util.import_('pkg')
Brett Cannon2153dc02009-08-27 23:49:21 +0000168 with self.assertRaises(ValueError):
169 import_util.import_('', global_, fromlist=['top_level'],
170 level=2)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000171 self.relative_import_test(create, globals_, callback)
172
173 def test_empty_name_w_level_0(self):
174 # [empty name]
Brett Cannon2153dc02009-08-27 23:49:21 +0000175 with self.assertRaises(ValueError):
176 import_util.import_('')
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000177
178 def test_import_from_different_package(self):
179 # Test importing from a different package than the caller.
180 # in pkg.subpkg1.mod
181 # from ..subpkg2 import mod
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000182 create = ['__runpy_pkg__.__init__',
183 '__runpy_pkg__.__runpy_pkg__.__init__',
184 '__runpy_pkg__.uncle.__init__',
185 '__runpy_pkg__.uncle.cousin.__init__',
186 '__runpy_pkg__.uncle.cousin.nephew']
187 globals_ = {'__package__': '__runpy_pkg__.__runpy_pkg__'}
188 def callback(global_):
Brett Cannond720b362009-02-01 04:28:04 +0000189 import_util.import_('__runpy_pkg__.__runpy_pkg__')
190 module = import_util.import_('uncle.cousin', globals_, {},
Brett Cannonbcb26c52009-02-01 04:00:05 +0000191 fromlist=['nephew'],
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000192 level=2)
193 self.assertEqual(module.__name__, '__runpy_pkg__.uncle.cousin')
194 self.relative_import_test(create, globals_, callback)
195
196
197
198def test_main():
199 from test.support import run_unittest
200 run_unittest(RelativeImports)
201
202if __name__ == '__main__':
203 test_main()