1from .. import util 2 3from importlib import machinery 4import sys 5import types 6import unittest 7 8PKG_NAME = 'fine' 9SUBMOD_NAME = 'fine.bogus' 10 11 12class BadSpecFinderLoader: 13 @classmethod 14 def find_spec(cls, fullname, path=None, target=None): 15 if fullname == SUBMOD_NAME: 16 spec = machinery.ModuleSpec(fullname, cls) 17 return spec 18 19 @staticmethod 20 def create_module(spec): 21 return None 22 23 @staticmethod 24 def exec_module(module): 25 if module.__name__ == SUBMOD_NAME: 26 raise ImportError('I cannot be loaded!') 27 28 29class BadLoaderFinder: 30 @classmethod 31 def find_module(cls, fullname, path): 32 if fullname == SUBMOD_NAME: 33 return cls 34 35 @classmethod 36 def load_module(cls, fullname): 37 if fullname == SUBMOD_NAME: 38 raise ImportError('I cannot be loaded!') 39 40 41class APITest: 42 43 """Test API-specific details for __import__ (e.g. raising the right 44 exception when passing in an int for the module name).""" 45 46 def test_raises_ModuleNotFoundError(self): 47 with self.assertRaises(ModuleNotFoundError): 48 util.import_importlib('some module that does not exist') 49 50 def test_name_requires_rparition(self): 51 # Raise TypeError if a non-string is passed in for the module name. 52 with self.assertRaises(TypeError): 53 self.__import__(42) 54 55 def test_negative_level(self): 56 # Raise ValueError when a negative level is specified. 57 # PEP 328 did away with sys.module None entries and the ambiguity of 58 # absolute/relative imports. 59 with self.assertRaises(ValueError): 60 self.__import__('os', globals(), level=-1) 61 62 def test_nonexistent_fromlist_entry(self): 63 # If something in fromlist doesn't exist, that's okay. 64 # issue15715 65 mod = types.ModuleType(PKG_NAME) 66 mod.__path__ = ['XXX'] 67 with util.import_state(meta_path=[self.bad_finder_loader]): 68 with util.uncache(PKG_NAME): 69 sys.modules[PKG_NAME] = mod 70 self.__import__(PKG_NAME, fromlist=['not here']) 71 72 def test_fromlist_load_error_propagates(self): 73 # If something in fromlist triggers an exception not related to not 74 # existing, let that exception propagate. 75 # issue15316 76 mod = types.ModuleType(PKG_NAME) 77 mod.__path__ = ['XXX'] 78 with util.import_state(meta_path=[self.bad_finder_loader]): 79 with util.uncache(PKG_NAME): 80 sys.modules[PKG_NAME] = mod 81 with self.assertRaises(ImportError): 82 self.__import__(PKG_NAME, 83 fromlist=[SUBMOD_NAME.rpartition('.')[-1]]) 84 85 def test_blocked_fromlist(self): 86 # If fromlist entry is None, let a ModuleNotFoundError propagate. 87 # issue31642 88 mod = types.ModuleType(PKG_NAME) 89 mod.__path__ = [] 90 with util.import_state(meta_path=[self.bad_finder_loader]): 91 with util.uncache(PKG_NAME, SUBMOD_NAME): 92 sys.modules[PKG_NAME] = mod 93 sys.modules[SUBMOD_NAME] = None 94 with self.assertRaises(ModuleNotFoundError) as cm: 95 self.__import__(PKG_NAME, 96 fromlist=[SUBMOD_NAME.rpartition('.')[-1]]) 97 self.assertEqual(cm.exception.name, SUBMOD_NAME) 98 99 100class OldAPITests(APITest): 101 bad_finder_loader = BadLoaderFinder 102 103 104(Frozen_OldAPITests, 105 Source_OldAPITests 106 ) = util.test_both(OldAPITests, __import__=util.__import__) 107 108 109class SpecAPITests(APITest): 110 bad_finder_loader = BadSpecFinderLoader 111 112 113(Frozen_SpecAPITests, 114 Source_SpecAPITests 115 ) = util.test_both(SpecAPITests, __import__=util.__import__) 116 117 118if __name__ == '__main__': 119 unittest.main() 120