Commit aa93642a authored by Brett Cannon's avatar Brett Cannon

Issue #14605: Use None in sys.path_importer_cache to represent no

finder instead of using some (now non-existent) implicit finder.
parent 9e66ac68
......@@ -766,17 +766,14 @@ class PathFinder:
except ImportError:
continue
else:
raise ImportError("no path hook found for {0}".format(path),
path=path)
return None
@classmethod
def _path_importer_cache(cls, path):
"""Get the finder for the path from sys.path_importer_cache.
If the path is not in the cache, find the appropriate finder and cache
it. Because of NullImporter, some finder should be returned. The only
explicit fail case is if None is cached but the path cannot be used for
the default hook, for which ImportError is raised.
it. If no finder is available, store None.
"""
if path == '':
......@@ -786,15 +783,6 @@ class PathFinder:
except KeyError:
finder = cls._path_hooks(path)
sys.path_importer_cache[path] = finder
else:
if finder is None:
msg = ("'None' in sys.path_importer_cache[{!r}], so retrying "
"finder search; in future versions of Python 'None' "
"will represent no finder".format(path))
_warnings.warn(msg, ImportWarning)
del sys.path_importer_cache[path]
finder = cls._path_hooks(path)
sys.path_importer_cache[path] = finder
return finder
@classmethod
......@@ -804,11 +792,8 @@ class PathFinder:
if path is None:
path = sys.path
for entry in path:
try:
finder = cls._path_importer_cache(entry)
except ImportError:
continue
if finder:
if finder is not None:
loader = finder.find_module(fullname)
if loader:
return loader
......@@ -1192,6 +1177,5 @@ def _install(sys_module, _imp_module):
supported_loaders = [(ExtensionFileLoader, _suffix_list(3), False),
(SourceFileLoader, _suffix_list(1), True),
(SourcelessFileLoader, _suffix_list(2), True)]
sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders),
_imp.NullImporter])
sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)])
sys.meta_path.extend([BuiltinImporter, FrozenImporter, PathFinder])
......@@ -66,36 +66,18 @@ class FinderTests(unittest.TestCase):
self.assertTrue(sys.path_importer_cache[path] is importer)
def test_empty_path_hooks(self):
# Test that if sys.path_hooks is empty a warning is raised and
# PathFinder returns None.
# tried again (with a warning).
# 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=['bogus_path']):
path=[path_entry]):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
self.assertIsNone(machinery.PathFinder.find_module('os'))
self.assertNotIn('os', sys.path_importer_cache)
self.assertIsNone(sys.path_importer_cache[path_entry])
self.assertEqual(len(w), 1)
self.assertTrue(issubclass(w[-1].category, ImportWarning))
def test_path_importer_cache_has_None_continues(self):
# Test that having None in sys.path_importer_cache causes the search to
# continue.
path = '<test path>'
module = '<test module>'
importer = util.mock_modules(module)
with util.import_state(path=['1', '2'],
path_importer_cache={'1': None, '2': importer},
path_hooks=[imp.NullImporter]):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
loader = machinery.PathFinder.find_module(module)
self.assertTrue(loader is importer)
self.assertEqual(len(w), 1)
warned = w[0]
self.assertTrue(issubclass(warned.category, ImportWarning))
self.assertIn(repr(None), str(warned.message))
def test_path_importer_cache_empty_string(self):
# The empty string should create a finder using the cwd.
path = ''
......
......@@ -9,6 +9,7 @@ importers when locating support scripts as well as when importing modules.
# Written by Nick Coghlan <ncoghlan at gmail.com>
# to implement PEP 338 (Executing Modules as Scripts)
import os
import sys
import imp
......@@ -206,11 +207,7 @@ def _get_importer(path_name):
except ImportError:
pass
else:
# The following check looks a bit odd. The trick is that
# NullImporter throws ImportError if the supplied path is a
# *valid* directory entry (and hence able to be handled
# by the standard import machinery)
importer = imp.NullImporter(path_name)
importer = None
cache[path_name] = importer
return importer
......@@ -237,7 +234,7 @@ def run_path(path_name, init_globals=None, run_name=None):
if run_name is None:
run_name = "<run_path>"
importer = _get_importer(path_name)
if isinstance(importer, imp.NullImporter):
if isinstance(importer, (type(None), imp.NullImporter)):
# Not a valid sys.path entry, so run the code directly
# execfile() doesn't help as we want to allow compiled files
code = _get_code_from_file(path_name)
......
......@@ -14,9 +14,9 @@ Core and Builtins
sys.meta_path is found to be empty, raise ImportWarning.
- Issue #14605: No longer have implicit entries in sys.path_hooks. If
sys.path_hooks is found to be empty, a warning will be raised. If None is
found in sys.path_importer_cache, a warning is raised and a search on
sys.path_hooks is attempted.
sys.path_hooks is found to be empty, a warning will be raised. None is now
inserted into sys.path_importer_cache if no finder was discovered. This also
means imp.NullImporter is no longer implicitly used.
- Issue #13903: Implement PEP 412. Individual dictionary instances can now share
their keys with other dictionaries. Classes take advantage of this to share
......
......@@ -224,7 +224,7 @@ RunMainFromImporter(wchar_t *filename)
if (importer == NULL)
goto error;
if (importer->ob_type == &PyNullImporter_Type) {
if (importer == Py_None) {
Py_DECREF(argv0);
Py_DECREF(importer);
return -1;
......
......@@ -1186,16 +1186,8 @@ get_path_importer(PyObject *path_importer_cache, PyObject *path_hooks,
PyErr_Clear();
}
if (importer == NULL) {
importer = PyObject_CallFunctionObjArgs(
(PyObject *)&PyNullImporter_Type, p, NULL
);
if (importer == NULL) {
if (PyErr_ExceptionMatches(PyExc_ImportError)) {
PyErr_Clear();
return Py_None;
}
}
}
if (importer != NULL) {
int err = PyDict_SetItem(path_importer_cache, p, importer);
Py_DECREF(importer);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment