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