Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9fa47eb

Browse files
committed
merge heads
2 parents 1138944 + e0d88a1 commit 9fa47eb

15 files changed

Lines changed: 3075 additions & 3195 deletions

Lib/importlib/_bootstrap.py

Lines changed: 19 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -752,15 +752,15 @@ class PathFinder:
752752
"""Meta path finder for sys.(path|path_hooks|path_importer_cache)."""
753753

754754
@classmethod
755-
def _path_hooks(cls, path, hooks=None):
755+
def _path_hooks(cls, path):
756756
"""Search sequence of hooks for a finder for 'path'.
757757
758758
If 'hooks' is false then use sys.path_hooks.
759759
760760
"""
761-
if hooks is None:
762-
hooks = sys.path_hooks
763-
for hook in hooks:
761+
if not sys.path_hooks:
762+
_warnings.warn('sys.path_hooks is empty', ImportWarning)
763+
for hook in sys.path_hooks:
764764
try:
765765
return hook(path)
766766
except ImportError:
@@ -770,14 +770,11 @@ def _path_hooks(cls, path, hooks=None):
770770
path=path)
771771

772772
@classmethod
773-
def _path_importer_cache(cls, path, default=None):
773+
def _path_importer_cache(cls, path):
774774
"""Get the finder for the path from sys.path_importer_cache.
775775
776776
If the path is not in the cache, find the appropriate finder and cache
777-
it. If None is cached, get the default finder and cache that
778-
(if applicable).
779-
780-
Because of NullImporter, some finder should be returned. The only
777+
it. Because of NullImporter, some finder should be returned. The only
781778
explicit fail case is if None is cached but the path cannot be used for
782779
the default hook, for which ImportError is raised.
783780
@@ -790,9 +787,13 @@ def _path_importer_cache(cls, path, default=None):
790787
finder = cls._path_hooks(path)
791788
sys.path_importer_cache[path] = finder
792789
else:
793-
if finder is None and default:
794-
# Raises ImportError on failure.
795-
finder = default(path)
790+
if finder is None:
791+
msg = ("'None' in sys.path_importer_cache[{!r}], so retrying "
792+
"finder search; in future versions of Python 'None' "
793+
"will represent no finder".format(path))
794+
_warnings.warn(msg, ImportWarning)
795+
del sys.path_importer_cache[path]
796+
finder = cls._path_hooks(path)
796797
sys.path_importer_cache[path] = finder
797798
return finder
798799

@@ -931,29 +932,6 @@ def path_hook_for_FileFinder(path):
931932

932933
# Import itself ###############################################################
933934

934-
_DEFAULT_PATH_HOOK = None # Set in _setup()
935-
936-
class _DefaultPathFinder(PathFinder):
937-
938-
"""Subclass of PathFinder that implements implicit semantics for
939-
__import__."""
940-
941-
@classmethod
942-
def _path_hooks(cls, path):
943-
"""Search sys.path_hooks as well as implicit path hooks."""
944-
try:
945-
return super()._path_hooks(path)
946-
except ImportError:
947-
implicit_hooks = [_DEFAULT_PATH_HOOK, _imp.NullImporter]
948-
return super()._path_hooks(path, implicit_hooks)
949-
950-
@classmethod
951-
def _path_importer_cache(cls, path):
952-
"""Use the default path hook when None is stored in
953-
sys.path_importer_cache."""
954-
return super()._path_importer_cache(path, _DEFAULT_PATH_HOOK)
955-
956-
957935
class _ImportLockContext:
958936

959937
"""Context manager for the import lock."""
@@ -1008,7 +986,7 @@ def _sanity_check(name, package, level):
1008986
raise ValueError("Empty module name")
1009987

1010988

1011-
_IMPLICIT_META_PATH = [BuiltinImporter, FrozenImporter, _DefaultPathFinder]
989+
_IMPLICIT_META_PATH = [BuiltinImporter, FrozenImporter, PathFinder]
1012990

1013991
_ERR_MSG = 'No module named {!r}'
1014992

@@ -1203,12 +1181,6 @@ def _setup(sys_module, _imp_module):
12031181
if builtin_os == 'nt':
12041182
SOURCE_SUFFIXES.append('.pyw')
12051183

1206-
supported_loaders = [(ExtensionFileLoader, _suffix_list(3), False),
1207-
(SourceFileLoader, _suffix_list(1), True),
1208-
(SourcelessFileLoader, _suffix_list(2), True)]
1209-
setattr(self_module, '_DEFAULT_PATH_HOOK',
1210-
FileFinder.path_hook(*supported_loaders))
1211-
12121184

12131185
def _install(sys_module, _imp_module):
12141186
"""Install importlib as the implementation of import.
@@ -1218,6 +1190,8 @@ def _install(sys_module, _imp_module):
12181190
12191191
"""
12201192
_setup(sys_module, _imp_module)
1221-
orig_import = builtins.__import__
1222-
builtins.__import__ = __import__
1223-
builtins.__original_import__ = orig_import
1193+
supported_loaders = [(ExtensionFileLoader, _suffix_list(3), False),
1194+
(SourceFileLoader, _suffix_list(1), True),
1195+
(SourcelessFileLoader, _suffix_list(2), True)]
1196+
sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders),
1197+
_imp.NullImporter])

Lib/importlib/test/import_/test_fromlist.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Test that the semantics relating to the 'fromlist' argument are correct."""
22
from .. import util
33
from . import util as import_util
4+
import imp
45
import unittest
56

67
class ReturnValue(unittest.TestCase):
@@ -73,7 +74,8 @@ def test_module_from_package(self):
7374
def test_no_module_from_package(self):
7475
# [no module]
7576
with util.mock_modules('pkg.__init__') as importer:
76-
with util.import_state(meta_path=[importer]):
77+
with util.import_state(meta_path=[importer],
78+
path_hooks=[imp.NullImporter]):
7779
module = import_util.import_('pkg', fromlist='non_existent')
7880
self.assertEqual(module.__name__, 'pkg')
7981
self.assertTrue(not hasattr(module, 'non_existent'))

Lib/importlib/test/import_/test_path.py

Lines changed: 24 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from test import support
1010
from types import MethodType
1111
import unittest
12+
import warnings
1213

1314

1415
class FinderTests(unittest.TestCase):
@@ -64,12 +65,18 @@ def test_path_hooks(self):
6465
self.assertTrue(path in sys.path_importer_cache)
6566
self.assertTrue(sys.path_importer_cache[path] is importer)
6667

67-
def test_path_importer_cache_has_None(self):
68-
# Test that if sys.path_importer_cache has None that None is returned.
69-
clear_cache = {path: None for path in sys.path}
70-
with util.import_state(path_importer_cache=clear_cache):
71-
for name in ('asynchat', 'sys', '<test module>'):
72-
self.assertTrue(machinery.PathFinder.find_module(name) is None)
68+
def test_empty_path_hooks(self):
69+
# Test that if sys.path_hooks is empty a warning is raised and
70+
# PathFinder returns None.
71+
# tried again (with a warning).
72+
with util.import_state(path_importer_cache={}, path_hooks=[],
73+
path=['bogus_path']):
74+
with warnings.catch_warnings(record=True) as w:
75+
warnings.simplefilter('always')
76+
self.assertIsNone(machinery.PathFinder.find_module('os'))
77+
self.assertNotIn('os', sys.path_importer_cache)
78+
self.assertEqual(len(w), 1)
79+
self.assertTrue(issubclass(w[-1].category, ImportWarning))
7380

7481
def test_path_importer_cache_has_None_continues(self):
7582
# Test that having None in sys.path_importer_cache causes the search to
@@ -78,9 +85,16 @@ def test_path_importer_cache_has_None_continues(self):
7885
module = '<test module>'
7986
importer = util.mock_modules(module)
8087
with util.import_state(path=['1', '2'],
81-
path_importer_cache={'1': None, '2': importer}):
82-
loader = machinery.PathFinder.find_module(module)
83-
self.assertTrue(loader is importer)
88+
path_importer_cache={'1': None, '2': importer},
89+
path_hooks=[imp.NullImporter]):
90+
with warnings.catch_warnings(record=True) as w:
91+
warnings.simplefilter('always')
92+
loader = machinery.PathFinder.find_module(module)
93+
self.assertTrue(loader is importer)
94+
self.assertEqual(len(w), 1)
95+
warned = w[0]
96+
self.assertTrue(issubclass(warned.category, ImportWarning))
97+
self.assertIn(repr(None), str(warned.message))
8498

8599
def test_path_importer_cache_empty_string(self):
86100
# The empty string should create a finder using the cwd.
@@ -94,57 +108,9 @@ def test_path_importer_cache_empty_string(self):
94108
self.assertIn(os.curdir, sys.path_importer_cache)
95109

96110

97-
class DefaultPathFinderTests(unittest.TestCase):
98-
99-
"""Test _bootstrap._DefaultPathFinder."""
100-
101-
def test_implicit_hooks(self):
102-
# Test that the implicit path hooks are used.
103-
bad_path = '<path>'
104-
module = '<module>'
105-
assert not os.path.exists(bad_path)
106-
existing_path = tempfile.mkdtemp()
107-
try:
108-
with util.import_state():
109-
nothing = _bootstrap._DefaultPathFinder.find_module(module,
110-
path=[existing_path])
111-
self.assertTrue(nothing is None)
112-
self.assertTrue(existing_path in sys.path_importer_cache)
113-
result = isinstance(sys.path_importer_cache[existing_path],
114-
imp.NullImporter)
115-
self.assertFalse(result)
116-
nothing = _bootstrap._DefaultPathFinder.find_module(module,
117-
path=[bad_path])
118-
self.assertTrue(nothing is None)
119-
self.assertTrue(bad_path in sys.path_importer_cache)
120-
self.assertTrue(isinstance(sys.path_importer_cache[bad_path],
121-
imp.NullImporter))
122-
finally:
123-
os.rmdir(existing_path)
124-
125-
126-
def test_path_importer_cache_has_None(self):
127-
# Test that the default hook is used when sys.path_importer_cache
128-
# contains None for a path.
129-
module = '<test module>'
130-
importer = util.mock_modules(module)
131-
path = '<test path>'
132-
# XXX Not blackbox.
133-
original_hook = _bootstrap._DEFAULT_PATH_HOOK
134-
mock_hook = import_util.mock_path_hook(path, importer=importer)
135-
_bootstrap._DEFAULT_PATH_HOOK = mock_hook
136-
try:
137-
with util.import_state(path_importer_cache={path: None}):
138-
loader = _bootstrap._DefaultPathFinder.find_module(module,
139-
path=[path])
140-
self.assertTrue(loader is importer)
141-
finally:
142-
_bootstrap._DEFAULT_PATH_HOOK = original_hook
143-
144-
145111
def test_main():
146112
from test.support import run_unittest
147-
run_unittest(FinderTests, DefaultPathFinderTests)
113+
run_unittest(FinderTests)
148114

149115
if __name__ == '__main__':
150116
test_main()

Lib/pkgutil.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -379,18 +379,15 @@ def get_importer(path_item):
379379
for path_hook in sys.path_hooks:
380380
try:
381381
importer = path_hook(path_item)
382+
sys.path_importer_cache.setdefault(path_item, importer)
382383
break
383384
except ImportError:
384385
pass
385386
else:
386-
importer = None
387-
sys.path_importer_cache.setdefault(path_item, importer)
388-
389-
if importer is None:
390-
try:
391-
importer = ImpImporter(path_item)
392-
except ImportError:
393-
importer = None
387+
try:
388+
importer = ImpImporter(path_item)
389+
except ImportError:
390+
importer = None
394391
return importer
395392

396393

Lib/runpy.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
# Written by Nick Coghlan <ncoghlan at gmail.com>
1010
# to implement PEP 338 (Executing Modules as Scripts)
1111

12+
import os
1213
import sys
1314
import imp
1415
from pkgutil import read_code
@@ -94,7 +95,7 @@ def _get_filename(loader, mod_name):
9495
for attr in ("get_filename", "_get_filename"):
9596
meth = getattr(loader, attr, None)
9697
if meth is not None:
97-
return meth(mod_name)
98+
return os.path.abspath(meth(mod_name))
9899
return None
99100

100101
# Helper to get the loader, code and filename for a module
@@ -198,10 +199,6 @@ def _get_importer(path_name):
198199
try:
199200
importer = cache[path_name]
200201
except KeyError:
201-
# Not yet cached. Flag as using the
202-
# standard machinery until we finish
203-
# checking the hooks
204-
cache[path_name] = None
205202
for hook in sys.path_hooks:
206203
try:
207204
importer = hook(path_name)
@@ -213,10 +210,7 @@ def _get_importer(path_name):
213210
# NullImporter throws ImportError if the supplied path is a
214211
# *valid* directory entry (and hence able to be handled
215212
# by the standard import machinery)
216-
try:
217-
importer = imp.NullImporter(path_name)
218-
except ImportError:
219-
return None
213+
importer = imp.NullImporter(path_name)
220214
cache[path_name] = importer
221215
return importer
222216

Lib/test/test_cgi.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import sys
55
import tempfile
66
import unittest
7+
import warnings
78
from io import StringIO, BytesIO
89

910
class HackedSysModule:
@@ -119,9 +120,13 @@ def gen_result(data, environ):
119120
class CgiTests(unittest.TestCase):
120121

121122
def test_escape(self):
122-
self.assertEqual("test &amp; string", cgi.escape("test & string"))
123-
self.assertEqual("&lt;test string&gt;", cgi.escape("<test string>"))
124-
self.assertEqual("&quot;test string&quot;", cgi.escape('"test string"', True))
123+
# cgi.escape() is deprecated.
124+
with warnings.catch_warnings():
125+
warnings.filterwarnings('ignore', 'cgi\.escape',
126+
DeprecationWarning)
127+
self.assertEqual("test &amp; string", cgi.escape("test & string"))
128+
self.assertEqual("&lt;test string&gt;", cgi.escape("<test string>"))
129+
self.assertEqual("&quot;test string&quot;", cgi.escape('"test string"', True))
125130

126131
def test_strict(self):
127132
for orig, expect in parse_strict_test_cases:

Lib/test/test_cmd_line_script.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# tests command line execution of scripts
22

3+
import importlib
34
import unittest
45
import sys
56
import os
@@ -49,12 +50,16 @@ def f():
4950
"""
5051

5152
def _make_test_script(script_dir, script_basename, source=test_source):
52-
return make_script(script_dir, script_basename, source)
53+
to_return = make_script(script_dir, script_basename, source)
54+
importlib.invalidate_caches()
55+
return to_return
5356

5457
def _make_test_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename,
5558
source=test_source, depth=1):
56-
return make_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename,
57-
source, depth)
59+
to_return = make_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename,
60+
source, depth)
61+
importlib.invalidate_caches()
62+
return to_return
5863

5964
# There's no easy way to pass the script directory in to get
6065
# -m to work (avoiding that is the whole point of making
@@ -72,7 +77,9 @@ def _make_launch_script(script_dir, script_basename, module_name, path=None):
7277
else:
7378
path = repr(path)
7479
source = launch_source % (path, module_name)
75-
return make_script(script_dir, script_basename, source)
80+
to_return = make_script(script_dir, script_basename, source)
81+
importlib.invalidate_caches()
82+
return to_return
7683

7784
class CmdLineTest(unittest.TestCase):
7885
def _check_output(self, script_name, exit_code, data,

Lib/test/test_importhooks.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def testMetaPath(self):
215215
self.doTestImports(i)
216216

217217
def testPathHook(self):
218-
sys.path_hooks.append(PathImporter)
218+
sys.path_hooks.insert(0, PathImporter)
219219
sys.path.append(test_path)
220220
self.doTestImports()
221221

@@ -228,7 +228,7 @@ def testBlocker(self):
228228
def testImpWrapper(self):
229229
i = ImpWrapper()
230230
sys.meta_path.append(i)
231-
sys.path_hooks.append(ImpWrapper)
231+
sys.path_hooks.insert(0, ImpWrapper)
232232
mnames = (
233233
"colorsys", "urllib.parse", "distutils.core", "sys",
234234
)

0 commit comments

Comments
 (0)