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

Skip to content

Commit aa93642

Browse files
committed
Issue #14605: Use None in sys.path_importer_cache to represent no
finder instead of using some (now non-existent) implicit finder.
1 parent 9e66ac6 commit aa93642

7 files changed

Lines changed: 1083 additions & 1159 deletions

File tree

Lib/importlib/_bootstrap.py

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -766,17 +766,14 @@ def _path_hooks(cls, path):
766766
except ImportError:
767767
continue
768768
else:
769-
raise ImportError("no path hook found for {0}".format(path),
770-
path=path)
769+
return None
771770

772771
@classmethod
773772
def _path_importer_cache(cls, path):
774773
"""Get the finder for the path from sys.path_importer_cache.
775774
776775
If the path is not in the cache, find the appropriate finder and cache
777-
it. Because of NullImporter, some finder should be returned. The only
778-
explicit fail case is if None is cached but the path cannot be used for
779-
the default hook, for which ImportError is raised.
776+
it. If no finder is available, store None.
780777
781778
"""
782779
if path == '':
@@ -786,15 +783,6 @@ def _path_importer_cache(cls, path):
786783
except KeyError:
787784
finder = cls._path_hooks(path)
788785
sys.path_importer_cache[path] = finder
789-
else:
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)
797-
sys.path_importer_cache[path] = finder
798786
return finder
799787

800788
@classmethod
@@ -804,11 +792,8 @@ def find_module(cls, fullname, path=None):
804792
if path is None:
805793
path = sys.path
806794
for entry in path:
807-
try:
808-
finder = cls._path_importer_cache(entry)
809-
except ImportError:
810-
continue
811-
if finder:
795+
finder = cls._path_importer_cache(entry)
796+
if finder is not None:
812797
loader = finder.find_module(fullname)
813798
if loader:
814799
return loader
@@ -1192,6 +1177,5 @@ def _install(sys_module, _imp_module):
11921177
supported_loaders = [(ExtensionFileLoader, _suffix_list(3), False),
11931178
(SourceFileLoader, _suffix_list(1), True),
11941179
(SourcelessFileLoader, _suffix_list(2), True)]
1195-
sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders),
1196-
_imp.NullImporter])
1180+
sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)])
11971181
sys.meta_path.extend([BuiltinImporter, FrozenImporter, PathFinder])

Lib/importlib/test/import_/test_path.py

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -66,36 +66,18 @@ def test_path_hooks(self):
6666
self.assertTrue(sys.path_importer_cache[path] is importer)
6767

6868
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).
69+
# Test that if sys.path_hooks is empty a warning is raised,
70+
# sys.path_importer_cache gets None set, and PathFinder returns None.
71+
path_entry = 'bogus_path'
7272
with util.import_state(path_importer_cache={}, path_hooks=[],
73-
path=['bogus_path']):
73+
path=[path_entry]):
7474
with warnings.catch_warnings(record=True) as w:
7575
warnings.simplefilter('always')
7676
self.assertIsNone(machinery.PathFinder.find_module('os'))
77-
self.assertNotIn('os', sys.path_importer_cache)
77+
self.assertIsNone(sys.path_importer_cache[path_entry])
7878
self.assertEqual(len(w), 1)
7979
self.assertTrue(issubclass(w[-1].category, ImportWarning))
8080

81-
def test_path_importer_cache_has_None_continues(self):
82-
# Test that having None in sys.path_importer_cache causes the search to
83-
# continue.
84-
path = '<test path>'
85-
module = '<test module>'
86-
importer = util.mock_modules(module)
87-
with util.import_state(path=['1', '2'],
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))
98-
9981
def test_path_importer_cache_empty_string(self):
10082
# The empty string should create a finder using the cwd.
10183
path = ''

Lib/runpy.py

Lines changed: 3 additions & 6 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+
1213
import os
1314
import sys
1415
import imp
@@ -206,11 +207,7 @@ def _get_importer(path_name):
206207
except ImportError:
207208
pass
208209
else:
209-
# The following check looks a bit odd. The trick is that
210-
# NullImporter throws ImportError if the supplied path is a
211-
# *valid* directory entry (and hence able to be handled
212-
# by the standard import machinery)
213-
importer = imp.NullImporter(path_name)
210+
importer = None
214211
cache[path_name] = importer
215212
return importer
216213

@@ -237,7 +234,7 @@ def run_path(path_name, init_globals=None, run_name=None):
237234
if run_name is None:
238235
run_name = "<run_path>"
239236
importer = _get_importer(path_name)
240-
if isinstance(importer, imp.NullImporter):
237+
if isinstance(importer, (type(None), imp.NullImporter)):
241238
# Not a valid sys.path entry, so run the code directly
242239
# execfile() doesn't help as we want to allow compiled files
243240
code = _get_code_from_file(path_name)

Misc/NEWS

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ Core and Builtins
1414
sys.meta_path is found to be empty, raise ImportWarning.
1515

1616
- Issue #14605: No longer have implicit entries in sys.path_hooks. If
17-
sys.path_hooks is found to be empty, a warning will be raised. If None is
18-
found in sys.path_importer_cache, a warning is raised and a search on
19-
sys.path_hooks is attempted.
17+
sys.path_hooks is found to be empty, a warning will be raised. None is now
18+
inserted into sys.path_importer_cache if no finder was discovered. This also
19+
means imp.NullImporter is no longer implicitly used.
2020

2121
- Issue #13903: Implement PEP 412. Individual dictionary instances can now share
2222
their keys with other dictionaries. Classes take advantage of this to share

Modules/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ RunMainFromImporter(wchar_t *filename)
224224
if (importer == NULL)
225225
goto error;
226226

227-
if (importer->ob_type == &PyNullImporter_Type) {
227+
if (importer == Py_None) {
228228
Py_DECREF(argv0);
229229
Py_DECREF(importer);
230230
return -1;

Python/import.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,15 +1186,7 @@ get_path_importer(PyObject *path_importer_cache, PyObject *path_hooks,
11861186
PyErr_Clear();
11871187
}
11881188
if (importer == NULL) {
1189-
importer = PyObject_CallFunctionObjArgs(
1190-
(PyObject *)&PyNullImporter_Type, p, NULL
1191-
);
1192-
if (importer == NULL) {
1193-
if (PyErr_ExceptionMatches(PyExc_ImportError)) {
1194-
PyErr_Clear();
1195-
return Py_None;
1196-
}
1197-
}
1189+
return Py_None;
11981190
}
11991191
if (importer != NULL) {
12001192
int err = PyDict_SetItem(path_importer_cache, p, importer);

0 commit comments

Comments
 (0)