blob: 42edc78b1c543a9ffe551c7dea7291c875fc90d9 [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 Cannon23cbd8a2009-01-18 00:24:28 +00003import sys
4import unittest
Brett Cannon849113a2016-01-22 15:25:50 -08005import warnings
6
Brett Cannon23cbd8a2009-01-18 00:24:28 +00007
Brett Cannon330f71b2013-11-08 13:34:59 -05008class RelativeImports:
Brett Cannon23cbd8a2009-01-18 00:24:28 +00009
10 """PEP 328 introduced relative imports. This allows for imports to occur
11 from within a package without having to specify the actual package name.
12
13 A simple example is to import another module within the same package
14 [module from module]::
15
16 # From pkg.mod1 with pkg.mod2 being a module.
17 from . import mod2
18
19 This also works for getting an attribute from a module that is specified
20 in a relative fashion [attr from module]::
21
22 # From pkg.mod1.
23 from .mod2 import attr
24
25 But this is in no way restricted to working between modules; it works
26 from [package to module],::
27
28 # From pkg, importing pkg.module which is a module.
29 from . import module
30
31 [module to package],::
32
33 # Pull attr from pkg, called from pkg.module which is a module.
34 from . import attr
35
36 and [package to package]::
37
38 # From pkg.subpkg1 (both pkg.subpkg[1,2] are packages).
39 from .. import subpkg2
40
41 The number of dots used is in no way restricted [deep import]::
42
43 # Import pkg.attr from pkg.pkg1.pkg2.pkg3.pkg4.pkg5.
44 from ...... import attr
45
46 To prevent someone from accessing code that is outside of a package, one
47 cannot reach the location containing the root package itself::
48
49 # From pkg.__init__ [too high from package]
50 from .. import top_level
51
52 # From pkg.module [too high from module]
53 from .. import top_level
54
55 Relative imports are the only type of import that allow for an empty
56 module name for an import [empty name].
57
58 """
59
60 def relative_import_test(self, create, globals_, callback):
61 """Abstract out boilerplace for setting up for an import test."""
62 uncache_names = []
63 for name in create:
64 if not name.endswith('.__init__'):
65 uncache_names.append(name)
66 else:
67 uncache_names.append(name[:-len('.__init__')])
Brett Cannon86aae6a2013-12-06 12:07:25 -050068 with util.mock_spec(*create) as importer:
Brett Cannonbcb26c52009-02-01 04:00:05 +000069 with util.import_state(meta_path=[importer]):
Brett Cannon849113a2016-01-22 15:25:50 -080070 with warnings.catch_warnings():
71 warnings.simplefilter("ignore")
72 for global_ in globals_:
73 with util.uncache(*uncache_names):
74 callback(global_)
Brett Cannon23cbd8a2009-01-18 00:24:28 +000075
76
77 def test_module_from_module(self):
78 # [module from module]
79 create = 'pkg.__init__', 'pkg.mod2'
80 globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.mod1'}
81 def callback(global_):
Brett Cannon330f71b2013-11-08 13:34:59 -050082 self.__import__('pkg') # For __import__().
83 module = self.__import__('', global_, fromlist=['mod2'], level=1)
Brett Cannon23cbd8a2009-01-18 00:24:28 +000084 self.assertEqual(module.__name__, 'pkg')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000085 self.assertTrue(hasattr(module, 'mod2'))
Brett Cannon23cbd8a2009-01-18 00:24:28 +000086 self.assertEqual(module.mod2.attr, 'pkg.mod2')
87 self.relative_import_test(create, globals_, callback)
88
89 def test_attr_from_module(self):
90 # [attr from module]
91 create = 'pkg.__init__', 'pkg.mod2'
92 globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.mod1'}
93 def callback(global_):
Brett Cannon330f71b2013-11-08 13:34:59 -050094 self.__import__('pkg') # For __import__().
95 module = self.__import__('mod2', global_, fromlist=['attr'],
Brett Cannond720b362009-02-01 04:28:04 +000096 level=1)
Brett Cannon23cbd8a2009-01-18 00:24:28 +000097 self.assertEqual(module.__name__, 'pkg.mod2')
98 self.assertEqual(module.attr, 'pkg.mod2')
99 self.relative_import_test(create, globals_, callback)
100
101 def test_package_to_module(self):
102 # [package to module]
103 create = 'pkg.__init__', 'pkg.module'
104 globals_ = ({'__package__': 'pkg'},
105 {'__name__': 'pkg', '__path__': ['blah']})
106 def callback(global_):
Brett Cannon330f71b2013-11-08 13:34:59 -0500107 self.__import__('pkg') # For __import__().
108 module = self.__import__('', global_, fromlist=['module'],
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000109 level=1)
110 self.assertEqual(module.__name__, 'pkg')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000111 self.assertTrue(hasattr(module, 'module'))
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000112 self.assertEqual(module.module.attr, 'pkg.module')
113 self.relative_import_test(create, globals_, callback)
114
115 def test_module_to_package(self):
116 # [module to package]
117 create = 'pkg.__init__', 'pkg.module'
118 globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.module'}
119 def callback(global_):
Brett Cannon330f71b2013-11-08 13:34:59 -0500120 self.__import__('pkg') # For __import__().
121 module = self.__import__('', global_, fromlist=['attr'], level=1)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000122 self.assertEqual(module.__name__, 'pkg')
123 self.relative_import_test(create, globals_, callback)
124
125 def test_package_to_package(self):
126 # [package to package]
127 create = ('pkg.__init__', 'pkg.subpkg1.__init__',
128 'pkg.subpkg2.__init__')
129 globals_ = ({'__package__': 'pkg.subpkg1'},
130 {'__name__': 'pkg.subpkg1', '__path__': ['blah']})
131 def callback(global_):
Brett Cannon330f71b2013-11-08 13:34:59 -0500132 module = self.__import__('', global_, fromlist=['subpkg2'],
Brett Cannond720b362009-02-01 04:28:04 +0000133 level=2)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000134 self.assertEqual(module.__name__, 'pkg')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000135 self.assertTrue(hasattr(module, 'subpkg2'))
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000136 self.assertEqual(module.subpkg2.attr, 'pkg.subpkg2.__init__')
137
138 def test_deep_import(self):
139 # [deep import]
140 create = ['pkg.__init__']
141 for count in range(1,6):
142 create.append('{0}.pkg{1}.__init__'.format(
143 create[-1][:-len('.__init__')], count))
144 globals_ = ({'__package__': 'pkg.pkg1.pkg2.pkg3.pkg4.pkg5'},
145 {'__name__': 'pkg.pkg1.pkg2.pkg3.pkg4.pkg5',
146 '__path__': ['blah']})
147 def callback(global_):
Brett Cannon330f71b2013-11-08 13:34:59 -0500148 self.__import__(globals_[0]['__package__'])
149 module = self.__import__('', global_, fromlist=['attr'], level=6)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000150 self.assertEqual(module.__name__, 'pkg')
151 self.relative_import_test(create, globals_, callback)
152
153 def test_too_high_from_package(self):
154 # [too high from package]
155 create = ['top_level', 'pkg.__init__']
156 globals_ = ({'__package__': 'pkg'},
157 {'__name__': 'pkg', '__path__': ['blah']})
158 def callback(global_):
Brett Cannon330f71b2013-11-08 13:34:59 -0500159 self.__import__('pkg')
Brett Cannon2153dc02009-08-27 23:49:21 +0000160 with self.assertRaises(ValueError):
Brett Cannon330f71b2013-11-08 13:34:59 -0500161 self.__import__('', global_, fromlist=['top_level'],
Brett Cannon2153dc02009-08-27 23:49:21 +0000162 level=2)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000163 self.relative_import_test(create, globals_, callback)
164
165 def test_too_high_from_module(self):
166 # [too high from module]
167 create = ['top_level', 'pkg.__init__', 'pkg.module']
168 globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.module'}
169 def callback(global_):
Brett Cannon330f71b2013-11-08 13:34:59 -0500170 self.__import__('pkg')
Brett Cannon2153dc02009-08-27 23:49:21 +0000171 with self.assertRaises(ValueError):
Brett Cannon330f71b2013-11-08 13:34:59 -0500172 self.__import__('', global_, fromlist=['top_level'],
Brett Cannon2153dc02009-08-27 23:49:21 +0000173 level=2)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000174 self.relative_import_test(create, globals_, callback)
175
176 def test_empty_name_w_level_0(self):
177 # [empty name]
Brett Cannon2153dc02009-08-27 23:49:21 +0000178 with self.assertRaises(ValueError):
Brett Cannon330f71b2013-11-08 13:34:59 -0500179 self.__import__('')
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000180
181 def test_import_from_different_package(self):
182 # Test importing from a different package than the caller.
183 # in pkg.subpkg1.mod
184 # from ..subpkg2 import mod
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000185 create = ['__runpy_pkg__.__init__',
186 '__runpy_pkg__.__runpy_pkg__.__init__',
187 '__runpy_pkg__.uncle.__init__',
188 '__runpy_pkg__.uncle.cousin.__init__',
189 '__runpy_pkg__.uncle.cousin.nephew']
190 globals_ = {'__package__': '__runpy_pkg__.__runpy_pkg__'}
191 def callback(global_):
Brett Cannon330f71b2013-11-08 13:34:59 -0500192 self.__import__('__runpy_pkg__.__runpy_pkg__')
193 module = self.__import__('uncle.cousin', globals_, {},
Brett Cannonbcb26c52009-02-01 04:00:05 +0000194 fromlist=['nephew'],
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000195 level=2)
196 self.assertEqual(module.__name__, '__runpy_pkg__.uncle.cousin')
197 self.relative_import_test(create, globals_, callback)
198
Brett Cannon49f8d8b2012-04-14 21:50:00 -0400199 def test_import_relative_import_no_fromlist(self):
200 # Import a relative module w/ no fromlist.
201 create = ['crash.__init__', 'crash.mod']
202 globals_ = [{'__package__': 'crash', '__name__': 'crash'}]
203 def callback(global_):
Brett Cannon330f71b2013-11-08 13:34:59 -0500204 self.__import__('crash')
205 mod = self.__import__('mod', global_, {}, [], 1)
Brett Cannon49f8d8b2012-04-14 21:50:00 -0400206 self.assertEqual(mod.__name__, 'crash.mod')
207 self.relative_import_test(create, globals_, callback)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000208
Brett Cannon273323c2012-04-17 19:05:11 -0400209 def test_relative_import_no_globals(self):
210 # No globals for a relative import is an error.
Brett Cannon849113a2016-01-22 15:25:50 -0800211 with warnings.catch_warnings():
212 warnings.simplefilter("ignore")
213 with self.assertRaises(KeyError):
214 self.__import__('sys', level=1)
Brett Cannon273323c2012-04-17 19:05:11 -0400215
Brett Cannon9fa81262016-01-22 16:39:02 -0800216 def test_relative_import_no_package(self):
217 with self.assertRaises(ImportError):
218 self.__import__('a', {'__package__': '', '__spec__': None},
219 level=1)
220
Brett Cannon4f38cb42016-02-20 12:52:06 -0800221 def test_relative_import_no_package_exists_absolute(self):
Brett Cannon0911c0d2016-02-20 12:59:36 -0800222 with self.assertRaises(ImportError):
Brett Cannon4f38cb42016-02-20 12:52:06 -0800223 self.__import__('sys', {'__package__': '', '__spec__': None},
224 level=1)
225
Eric Snow3497c0b2014-05-16 11:40:40 -0600226
227(Frozen_RelativeImports,
228 Source_RelativeImports
229 ) = util.test_both(RelativeImports, __import__=util.__import__)
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000230
Brett Cannon23cbd8a2009-01-18 00:24:28 +0000231
232if __name__ == '__main__':
Brett Cannon330f71b2013-11-08 13:34:59 -0500233 unittest.main()