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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
|
from test.test_importlib import util
importlib = util.import_importlib('importlib')
machinery = util.import_importlib('importlib.machinery')
import os
import sys
import tempfile
from types import ModuleType
import unittest
import warnings
import zipimport
class FinderTests:
"""Tests for PathFinder."""
find = None
check_found = None
def test_failure(self):
# Test None returned upon not finding a suitable loader.
module = '<test module>'
with util.import_state():
self.assertIsNone(self.find(module))
def test_sys_path(self):
# Test that sys.path is used when 'path' is None.
# Implicitly tests that sys.path_importer_cache is used.
module = '<test module>'
path = '<test path>'
importer = util.mock_spec(module)
with util.import_state(path_importer_cache={path: importer},
path=[path]):
found = self.find(module)
self.check_found(found, importer)
def test_path(self):
# Test that 'path' is used when set.
# Implicitly tests that sys.path_importer_cache is used.
module = '<test module>'
path = '<test path>'
importer = util.mock_spec(module)
with util.import_state(path_importer_cache={path: importer}):
found = self.find(module, [path])
self.check_found(found, importer)
def test_empty_list(self):
# An empty list should not count as asking for sys.path.
module = 'module'
path = '<test path>'
importer = util.mock_spec(module)
with util.import_state(path_importer_cache={path: importer},
path=[path]):
self.assertIsNone(self.find('module', []))
def test_path_hooks(self):
# Test that sys.path_hooks is used.
# Test that sys.path_importer_cache is set.
module = '<test module>'
path = '<test path>'
importer = util.mock_spec(module)
hook = util.mock_path_hook(path, importer=importer)
with util.import_state(path_hooks=[hook]):
found = self.find(module, [path])
self.check_found(found, importer)
self.assertIn(path, sys.path_importer_cache)
self.assertIs(sys.path_importer_cache[path], importer)
def test_empty_path_hooks(self):
# Test that if sys.path_hooks is empty a warning is raised,
# sys.path_importer_cache gets None set, and PathFinder returns None.
path_entry = 'bogus_path'
with util.import_state(path_importer_cache={}, path_hooks=[],
path=[path_entry]):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always', ImportWarning)
warnings.simplefilter('ignore', DeprecationWarning)
self.assertIsNone(self.find('os'))
self.assertIsNone(sys.path_importer_cache[path_entry])
self.assertEqual(len(w), 1)
self.assertIsSubclass(w[-1].category, ImportWarning)
def test_path_importer_cache_empty_string(self):
# The empty string should create a finder using the cwd.
path = ''
module = '<test module>'
importer = util.mock_spec(module)
hook = util.mock_path_hook(os.getcwd(), importer=importer)
with util.import_state(path=[path], path_hooks=[hook]):
found = self.find(module)
self.check_found(found, importer)
self.assertIn(os.getcwd(), sys.path_importer_cache)
def test_None_on_sys_path(self):
# Putting None in sys.path[0] caused an import regression from Python
# 3.2: http://bugs.python.org/issue16514
new_path = sys.path[:]
new_path.insert(0, None)
new_path_importer_cache = sys.path_importer_cache.copy()
new_path_importer_cache.pop(None, None)
new_path_hooks = [zipimport.zipimporter,
self.machinery.FileFinder.path_hook(
*self.importlib._bootstrap_external._get_supported_file_loaders())]
missing = object()
email = sys.modules.pop('email', missing)
try:
with util.import_state(meta_path=sys.meta_path[:],
path=new_path,
path_importer_cache=new_path_importer_cache,
path_hooks=new_path_hooks):
module = self.importlib.import_module('email')
self.assertIsInstance(module, ModuleType)
finally:
if email is not missing:
sys.modules['email'] = email
def test_finder_with_find_spec(self):
class TestFinder:
spec = None
def find_spec(self, fullname, target=None):
return self.spec
path = 'testing path'
with util.import_state(path_importer_cache={path: TestFinder()}):
self.assertIsNone(
self.machinery.PathFinder.find_spec('whatever', [path]))
success_finder = TestFinder()
success_finder.spec = self.machinery.ModuleSpec('whatever', __loader__)
with util.import_state(path_importer_cache={path: success_finder}):
got = self.machinery.PathFinder.find_spec('whatever', [path])
self.assertEqual(got, success_finder.spec)
def test_deleted_cwd(self):
# Issue #22834
old_dir = os.getcwd()
self.addCleanup(os.chdir, old_dir)
new_dir = tempfile.mkdtemp()
try:
os.chdir(new_dir)
try:
os.rmdir(new_dir)
except OSError:
# EINVAL on Solaris, EBUSY on AIX, ENOTEMPTY on Windows
self.skipTest("platform does not allow "
"the deletion of the cwd")
except:
os.chdir(old_dir)
os.rmdir(new_dir)
raise
with util.import_state(path=['']):
# Do not want FileNotFoundError raised.
self.assertIsNone(self.machinery.PathFinder.find_spec('whatever'))
def test_invalidate_caches_finders(self):
# Finders with an invalidate_caches() method have it called.
class FakeFinder:
def __init__(self):
self.called = False
def invalidate_caches(self):
self.called = True
key = os.path.abspath('finder_to_invalidate')
cache = {'leave_alone': object(), key: FakeFinder()}
with util.import_state(path_importer_cache=cache):
self.machinery.PathFinder.invalidate_caches()
self.assertTrue(cache[key].called)
def test_invalidate_caches_clear_out_None(self):
# Clear out None in sys.path_importer_cache() when invalidating caches.
cache = {'clear_out': None}
with util.import_state(path_importer_cache=cache):
self.machinery.PathFinder.invalidate_caches()
self.assertEqual(len(cache), 0)
def test_invalidate_caches_clear_out_relative_path(self):
class FakeFinder:
def invalidate_caches(self):
pass
cache = {'relative_path': FakeFinder()}
with util.import_state(path_importer_cache=cache):
self.machinery.PathFinder.invalidate_caches()
self.assertEqual(cache, {})
class FindModuleTests(FinderTests):
def find(self, *args, **kwargs):
spec = self.machinery.PathFinder.find_spec(*args, **kwargs)
return None if spec is None else spec.loader
def check_found(self, found, importer):
self.assertIs(found, importer)
(Frozen_FindModuleTests,
Source_FindModuleTests
) = util.test_both(FindModuleTests, importlib=importlib, machinery=machinery)
class FindSpecTests(FinderTests):
def find(self, *args, **kwargs):
return self.machinery.PathFinder.find_spec(*args, **kwargs)
def check_found(self, found, importer):
self.assertIs(found.loader, importer)
(Frozen_FindSpecTests,
Source_FindSpecTests
) = util.test_both(FindSpecTests, importlib=importlib, machinery=machinery)
class PathEntryFinderTests:
def test_finder_with_failing_find_spec(self):
class Finder:
path_location = 'test_finder_with_find_spec'
def __init__(self, path):
if path != self.path_location:
raise ImportError
@staticmethod
def find_spec(fullname, target=None):
return None
with util.import_state(path=[Finder.path_location]+sys.path[:],
path_hooks=[Finder]):
with warnings.catch_warnings():
warnings.simplefilter("ignore", ImportWarning)
self.machinery.PathFinder.find_spec('importlib')
(Frozen_PEFTests,
Source_PEFTests
) = util.test_both(PathEntryFinderTests, machinery=machinery)
if __name__ == '__main__':
unittest.main()
|