1"""Test that the semantics relating to the 'fromlist' argument are correct.""" 2from test.test_importlib import util 3import warnings 4import unittest 5 6 7class ReturnValue: 8 9 """The use of fromlist influences what import returns. 10 11 If direct ``import ...`` statement is used, the root module or package is 12 returned [import return]. But if fromlist is set, then the specified module 13 is actually returned (whether it is a relative import or not) 14 [from return]. 15 16 """ 17 18 def test_return_from_import(self): 19 # [import return] 20 with util.mock_spec('pkg.__init__', 'pkg.module') as importer: 21 with util.import_state(meta_path=[importer]): 22 module = self.__import__('pkg.module') 23 self.assertEqual(module.__name__, 'pkg') 24 25 def test_return_from_from_import(self): 26 # [from return] 27 with util.mock_spec('pkg.__init__', 'pkg.module')as importer: 28 with util.import_state(meta_path=[importer]): 29 module = self.__import__('pkg.module', fromlist=['attr']) 30 self.assertEqual(module.__name__, 'pkg.module') 31 32 33(Frozen_ReturnValue, 34 Source_ReturnValue 35 ) = util.test_both(ReturnValue, __import__=util.__import__) 36 37 38class HandlingFromlist: 39 40 """Using fromlist triggers different actions based on what is being asked 41 of it. 42 43 If fromlist specifies an object on a module, nothing special happens 44 [object case]. This is even true if the object does not exist [bad object]. 45 46 If a package is being imported, then what is listed in fromlist may be 47 treated as a module to be imported [module]. And this extends to what is 48 contained in __all__ when '*' is imported [using *]. And '*' does not need 49 to be the only name in the fromlist [using * with others]. 50 51 """ 52 53 def test_object(self): 54 # [object case] 55 with util.mock_spec('module') as importer: 56 with util.import_state(meta_path=[importer]): 57 module = self.__import__('module', fromlist=['attr']) 58 self.assertEqual(module.__name__, 'module') 59 60 def test_nonexistent_object(self): 61 # [bad object] 62 with util.mock_spec('module') as importer: 63 with util.import_state(meta_path=[importer]): 64 module = self.__import__('module', fromlist=['non_existent']) 65 self.assertEqual(module.__name__, 'module') 66 self.assertFalse(hasattr(module, 'non_existent')) 67 68 def test_module_from_package(self): 69 # [module] 70 with util.mock_spec('pkg.__init__', 'pkg.module') as importer: 71 with util.import_state(meta_path=[importer]): 72 module = self.__import__('pkg', fromlist=['module']) 73 self.assertEqual(module.__name__, 'pkg') 74 self.assertTrue(hasattr(module, 'module')) 75 self.assertEqual(module.module.__name__, 'pkg.module') 76 77 def test_nonexistent_from_package(self): 78 with util.mock_spec('pkg.__init__') as importer: 79 with util.import_state(meta_path=[importer]): 80 module = self.__import__('pkg', fromlist=['non_existent']) 81 self.assertEqual(module.__name__, 'pkg') 82 self.assertFalse(hasattr(module, 'non_existent')) 83 84 def test_module_from_package_triggers_ModuleNotFoundError(self): 85 # If a submodule causes an ModuleNotFoundError because it tries 86 # to import a module which doesn't exist, that should let the 87 # ModuleNotFoundError propagate. 88 def module_code(): 89 import i_do_not_exist 90 with util.mock_spec('pkg.__init__', 'pkg.mod', 91 module_code={'pkg.mod': module_code}) as importer: 92 with util.import_state(meta_path=[importer]): 93 with self.assertRaises(ModuleNotFoundError) as exc: 94 self.__import__('pkg', fromlist=['mod']) 95 self.assertEqual('i_do_not_exist', exc.exception.name) 96 97 def test_empty_string(self): 98 with util.mock_spec('pkg.__init__', 'pkg.mod') as importer: 99 with util.import_state(meta_path=[importer]): 100 module = self.__import__('pkg.mod', fromlist=['']) 101 self.assertEqual(module.__name__, 'pkg.mod') 102 103 def basic_star_test(self, fromlist=['*']): 104 # [using *] 105 with util.mock_spec('pkg.__init__', 'pkg.module') as mock: 106 with util.import_state(meta_path=[mock]): 107 mock['pkg'].__all__ = ['module'] 108 module = self.__import__('pkg', fromlist=fromlist) 109 self.assertEqual(module.__name__, 'pkg') 110 self.assertTrue(hasattr(module, 'module')) 111 self.assertEqual(module.module.__name__, 'pkg.module') 112 113 def test_using_star(self): 114 # [using *] 115 self.basic_star_test() 116 117 def test_fromlist_as_tuple(self): 118 self.basic_star_test(('*',)) 119 120 def test_star_with_others(self): 121 # [using * with others] 122 context = util.mock_spec('pkg.__init__', 'pkg.module1', 'pkg.module2') 123 with context as mock: 124 with util.import_state(meta_path=[mock]): 125 mock['pkg'].__all__ = ['module1'] 126 module = self.__import__('pkg', fromlist=['module2', '*']) 127 self.assertEqual(module.__name__, 'pkg') 128 self.assertTrue(hasattr(module, 'module1')) 129 self.assertTrue(hasattr(module, 'module2')) 130 self.assertEqual(module.module1.__name__, 'pkg.module1') 131 self.assertEqual(module.module2.__name__, 'pkg.module2') 132 133 def test_nonexistent_in_all(self): 134 with util.mock_spec('pkg.__init__') as importer: 135 with util.import_state(meta_path=[importer]): 136 importer['pkg'].__all__ = ['non_existent'] 137 module = self.__import__('pkg', fromlist=['*']) 138 self.assertEqual(module.__name__, 'pkg') 139 self.assertFalse(hasattr(module, 'non_existent')) 140 141 def test_star_in_all(self): 142 with util.mock_spec('pkg.__init__') as importer: 143 with util.import_state(meta_path=[importer]): 144 importer['pkg'].__all__ = ['*'] 145 module = self.__import__('pkg', fromlist=['*']) 146 self.assertEqual(module.__name__, 'pkg') 147 self.assertFalse(hasattr(module, '*')) 148 149 def test_invalid_type(self): 150 with util.mock_spec('pkg.__init__') as importer: 151 with util.import_state(meta_path=[importer]), \ 152 warnings.catch_warnings(): 153 warnings.simplefilter('error', BytesWarning) 154 with self.assertRaisesRegex(TypeError, r'\bfrom\b'): 155 self.__import__('pkg', fromlist=[b'attr']) 156 with self.assertRaisesRegex(TypeError, r'\bfrom\b'): 157 self.__import__('pkg', fromlist=iter([b'attr'])) 158 159 def test_invalid_type_in_all(self): 160 with util.mock_spec('pkg.__init__') as importer: 161 with util.import_state(meta_path=[importer]), \ 162 warnings.catch_warnings(): 163 warnings.simplefilter('error', BytesWarning) 164 importer['pkg'].__all__ = [b'attr'] 165 with self.assertRaisesRegex(TypeError, r'\bpkg\.__all__\b'): 166 self.__import__('pkg', fromlist=['*']) 167 168 169(Frozen_FromList, 170 Source_FromList 171 ) = util.test_both(HandlingFromlist, __import__=util.__import__) 172 173 174if __name__ == '__main__': 175 unittest.main() 176