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

finder instead of using some (now non-existent) implicit finder.
This commit is contained in:
Brett Cannon 2012-04-27 15:30:58 -04:00
parent 9e66ac683c
commit aa93642a35
7 changed files with 1096 additions and 1172 deletions

View File

@ -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:
finder = cls._path_importer_cache(entry)
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])

View File

@ -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 = ''

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -1186,15 +1186,7 @@ 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;
}
}
return Py_None;
}
if (importer != NULL) {
int err = PyDict_SetItem(path_importer_cache, p, importer);

File diff suppressed because it is too large Load Diff