mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
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:
parent
9e66ac683c
commit
aa93642a35
7 changed files with 1096 additions and 1172 deletions
|
@ -766,17 +766,14 @@ class PathFinder:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
raise ImportError("no path hook found for {0}".format(path),
|
return None
|
||||||
path=path)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _path_importer_cache(cls, path):
|
def _path_importer_cache(cls, path):
|
||||||
"""Get the finder for the path from sys.path_importer_cache.
|
"""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
|
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
|
it. If no finder is available, store None.
|
||||||
explicit fail case is if None is cached but the path cannot be used for
|
|
||||||
the default hook, for which ImportError is raised.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if path == '':
|
if path == '':
|
||||||
|
@ -786,15 +783,6 @@ class PathFinder:
|
||||||
except KeyError:
|
except KeyError:
|
||||||
finder = cls._path_hooks(path)
|
finder = cls._path_hooks(path)
|
||||||
sys.path_importer_cache[path] = finder
|
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
|
return finder
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -804,11 +792,8 @@ class PathFinder:
|
||||||
if path is None:
|
if path is None:
|
||||||
path = sys.path
|
path = sys.path
|
||||||
for entry in path:
|
for entry in path:
|
||||||
try:
|
finder = cls._path_importer_cache(entry)
|
||||||
finder = cls._path_importer_cache(entry)
|
if finder is not None:
|
||||||
except ImportError:
|
|
||||||
continue
|
|
||||||
if finder:
|
|
||||||
loader = finder.find_module(fullname)
|
loader = finder.find_module(fullname)
|
||||||
if loader:
|
if loader:
|
||||||
return loader
|
return loader
|
||||||
|
@ -1192,6 +1177,5 @@ def _install(sys_module, _imp_module):
|
||||||
supported_loaders = [(ExtensionFileLoader, _suffix_list(3), False),
|
supported_loaders = [(ExtensionFileLoader, _suffix_list(3), False),
|
||||||
(SourceFileLoader, _suffix_list(1), True),
|
(SourceFileLoader, _suffix_list(1), True),
|
||||||
(SourcelessFileLoader, _suffix_list(2), True)]
|
(SourcelessFileLoader, _suffix_list(2), True)]
|
||||||
sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders),
|
sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)])
|
||||||
_imp.NullImporter])
|
|
||||||
sys.meta_path.extend([BuiltinImporter, FrozenImporter, PathFinder])
|
sys.meta_path.extend([BuiltinImporter, FrozenImporter, PathFinder])
|
||||||
|
|
|
@ -66,36 +66,18 @@ class FinderTests(unittest.TestCase):
|
||||||
self.assertTrue(sys.path_importer_cache[path] is importer)
|
self.assertTrue(sys.path_importer_cache[path] is importer)
|
||||||
|
|
||||||
def test_empty_path_hooks(self):
|
def test_empty_path_hooks(self):
|
||||||
# Test that if sys.path_hooks is empty a warning is raised and
|
# Test that if sys.path_hooks is empty a warning is raised,
|
||||||
# PathFinder returns None.
|
# sys.path_importer_cache gets None set, and PathFinder returns None.
|
||||||
# tried again (with a warning).
|
path_entry = 'bogus_path'
|
||||||
with util.import_state(path_importer_cache={}, path_hooks=[],
|
with util.import_state(path_importer_cache={}, path_hooks=[],
|
||||||
path=['bogus_path']):
|
path=[path_entry]):
|
||||||
with warnings.catch_warnings(record=True) as w:
|
with warnings.catch_warnings(record=True) as w:
|
||||||
warnings.simplefilter('always')
|
warnings.simplefilter('always')
|
||||||
self.assertIsNone(machinery.PathFinder.find_module('os'))
|
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.assertEqual(len(w), 1)
|
||||||
self.assertTrue(issubclass(w[-1].category, ImportWarning))
|
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):
|
def test_path_importer_cache_empty_string(self):
|
||||||
# The empty string should create a finder using the cwd.
|
# The empty string should create a finder using the cwd.
|
||||||
path = ''
|
path = ''
|
||||||
|
|
|
@ -9,6 +9,7 @@ importers when locating support scripts as well as when importing modules.
|
||||||
# Written by Nick Coghlan <ncoghlan at gmail.com>
|
# Written by Nick Coghlan <ncoghlan at gmail.com>
|
||||||
# to implement PEP 338 (Executing Modules as Scripts)
|
# to implement PEP 338 (Executing Modules as Scripts)
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import imp
|
import imp
|
||||||
|
@ -206,11 +207,7 @@ def _get_importer(path_name):
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
# The following check looks a bit odd. The trick is that
|
importer = None
|
||||||
# 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)
|
|
||||||
cache[path_name] = importer
|
cache[path_name] = importer
|
||||||
return importer
|
return importer
|
||||||
|
|
||||||
|
@ -237,7 +234,7 @@ def run_path(path_name, init_globals=None, run_name=None):
|
||||||
if run_name is None:
|
if run_name is None:
|
||||||
run_name = "<run_path>"
|
run_name = "<run_path>"
|
||||||
importer = _get_importer(path_name)
|
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
|
# Not a valid sys.path entry, so run the code directly
|
||||||
# execfile() doesn't help as we want to allow compiled files
|
# execfile() doesn't help as we want to allow compiled files
|
||||||
code = _get_code_from_file(path_name)
|
code = _get_code_from_file(path_name)
|
||||||
|
|
|
@ -14,9 +14,9 @@ Core and Builtins
|
||||||
sys.meta_path is found to be empty, raise ImportWarning.
|
sys.meta_path is found to be empty, raise ImportWarning.
|
||||||
|
|
||||||
- Issue #14605: No longer have implicit entries in sys.path_hooks. If
|
- 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
|
sys.path_hooks is found to be empty, a warning will be raised. None is now
|
||||||
found in sys.path_importer_cache, a warning is raised and a search on
|
inserted into sys.path_importer_cache if no finder was discovered. This also
|
||||||
sys.path_hooks is attempted.
|
means imp.NullImporter is no longer implicitly used.
|
||||||
|
|
||||||
- Issue #13903: Implement PEP 412. Individual dictionary instances can now share
|
- Issue #13903: Implement PEP 412. Individual dictionary instances can now share
|
||||||
their keys with other dictionaries. Classes take advantage of this to share
|
their keys with other dictionaries. Classes take advantage of this to share
|
||||||
|
|
|
@ -224,7 +224,7 @@ RunMainFromImporter(wchar_t *filename)
|
||||||
if (importer == NULL)
|
if (importer == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (importer->ob_type == &PyNullImporter_Type) {
|
if (importer == Py_None) {
|
||||||
Py_DECREF(argv0);
|
Py_DECREF(argv0);
|
||||||
Py_DECREF(importer);
|
Py_DECREF(importer);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -1186,15 +1186,7 @@ get_path_importer(PyObject *path_importer_cache, PyObject *path_hooks,
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
}
|
}
|
||||||
if (importer == NULL) {
|
if (importer == NULL) {
|
||||||
importer = PyObject_CallFunctionObjArgs(
|
return Py_None;
|
||||||
(PyObject *)&PyNullImporter_Type, p, NULL
|
|
||||||
);
|
|
||||||
if (importer == NULL) {
|
|
||||||
if (PyErr_ExceptionMatches(PyExc_ImportError)) {
|
|
||||||
PyErr_Clear();
|
|
||||||
return Py_None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (importer != NULL) {
|
if (importer != NULL) {
|
||||||
int err = PyDict_SetItem(path_importer_cache, p, importer);
|
int err = PyDict_SetItem(path_importer_cache, p, importer);
|
||||||
|
|
2187
Python/importlib.h
2187
Python/importlib.h
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue