summaryrefslogtreecommitdiff
path: root/Lib/importlib
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2016-05-27 12:56:41 -0600
committerEric Snow <ericsnowcurrently@gmail.com>2016-05-27 12:56:41 -0600
commit1f1268c0bc93629b7abc16d8af9cf997c32a947b (patch)
tree39ee4dfe533b80ba355fc850ca5de5bc85c09ec0 /Lib/importlib
parentf9990315cdea1d35808ed89f11a4fe388944553e (diff)
parent3bd347c543f3849bc5c70f7c07aa02bb204d3060 (diff)
downloadcpython-1f1268c0bc93629b7abc16d8af9cf997c32a947b.tar.gz
Issue #27138: Fix the doc comment for FileFinder.find_spec().
Diffstat (limited to 'Lib/importlib')
-rw-r--r--Lib/importlib/_bootstrap.py28
-rw-r--r--Lib/importlib/_bootstrap_external.py59
-rw-r--r--Lib/importlib/util.py4
3 files changed, 58 insertions, 33 deletions
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
index 9eecbfe967..afc31ee5e8 100644
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -878,13 +878,20 @@ def _find_spec_legacy(finder, name, path):
def _find_spec(name, path, target=None):
"""Find a module's loader."""
- if sys.meta_path is not None and not sys.meta_path:
+ meta_path = sys.meta_path
+ if meta_path is None:
+ # PyImport_Cleanup() is running or has been called.
+ raise ImportError("sys.meta_path is None, Python is likely "
+ "shutting down")
+
+ if not meta_path:
_warnings.warn('sys.meta_path is empty', ImportWarning)
+
# We check sys.modules here for the reload case. While a passed-in
# target will usually indicate a reload there is no guarantee, whereas
# sys.modules provides one.
is_reload = name in sys.modules
- for finder in sys.meta_path:
+ for finder in meta_path:
with _ImportLockContext():
try:
find_spec = finder.find_spec
@@ -925,6 +932,9 @@ def _sanity_check(name, package, level):
if level > 0:
if not isinstance(package, str):
raise TypeError('__package__ not set to a string')
+ elif not package:
+ raise ImportError('attempted relative import with no known parent '
+ 'package')
elif package not in sys.modules:
msg = ('Parent module {!r} not loaded, cannot perform relative '
'import')
@@ -1033,7 +1043,19 @@ def _calc___package__(globals):
"""
package = globals.get('__package__')
- if package is None:
+ spec = globals.get('__spec__')
+ if package is not None:
+ if spec is not None and package != spec.parent:
+ _warnings.warn("__package__ != __spec__.parent "
+ f"({package!r} != {spec.parent!r})",
+ ImportWarning, stacklevel=3)
+ return package
+ elif spec is not None:
+ return spec.parent
+ else:
+ _warnings.warn("can't resolve package from __spec__ or __package__, "
+ "falling back on __name__ and __path__",
+ ImportWarning, stacklevel=3)
package = globals['__name__']
if '__path__' not in globals:
package = package.rpartition('.')[0]
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index 9788828688..034b783990 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -223,6 +223,9 @@ _code_type = type(_write_atomic.__code__)
# Python 3.5b1 3330 (PEP 448: Additional Unpacking Generalizations)
# Python 3.5b2 3340 (fix dictionary display evaluation order #11205)
# Python 3.5b2 3350 (add GET_YIELD_FROM_ITER opcode #24400)
+# Python 3.6a0 3360 (add FORMAT_VALUE opcode #25483
+# Python 3.6a0 3361 (lineno delta of code.co_lnotab becomes signed)
+# Python 3.6a0 3370 (16 bit wordcode)
#
# MAGIC must change whenever the bytecode emitted by the compiler may no
# longer be understood by older implementations of the eval loop (usually
@@ -231,7 +234,7 @@ _code_type = type(_write_atomic.__code__)
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.
-MAGIC_NUMBER = (3350).to_bytes(2, 'little') + b'\r\n'
+MAGIC_NUMBER = (3370).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
_PYCACHE = '__pycache__'
@@ -363,14 +366,6 @@ def _calc_mode(path):
return mode
-def _verbose_message(message, *args, verbosity=1):
- """Print the message to stderr if -v/PYTHONVERBOSE is turned on."""
- if sys.flags.verbose >= verbosity:
- if not message.startswith(('#', 'import ')):
- message = '# ' + message
- print(message.format(*args), file=sys.stderr)
-
-
def _check_name(method):
"""Decorator to verify that the module being requested matches the one the
loader can handle.
@@ -440,15 +435,15 @@ def _validate_bytecode_header(data, source_stats=None, name=None, path=None):
raw_size = data[8:12]
if magic != MAGIC_NUMBER:
message = 'bad magic number in {!r}: {!r}'.format(name, magic)
- _verbose_message('{}', message)
+ _bootstrap._verbose_message('{}', message)
raise ImportError(message, **exc_details)
elif len(raw_timestamp) != 4:
message = 'reached EOF while reading timestamp in {!r}'.format(name)
- _verbose_message('{}', message)
+ _bootstrap._verbose_message('{}', message)
raise EOFError(message)
elif len(raw_size) != 4:
message = 'reached EOF while reading size of source in {!r}'.format(name)
- _verbose_message('{}', message)
+ _bootstrap._verbose_message('{}', message)
raise EOFError(message)
if source_stats is not None:
try:
@@ -458,7 +453,7 @@ def _validate_bytecode_header(data, source_stats=None, name=None, path=None):
else:
if _r_long(raw_timestamp) != source_mtime:
message = 'bytecode is stale for {!r}'.format(name)
- _verbose_message('{}', message)
+ _bootstrap._verbose_message('{}', message)
raise ImportError(message, **exc_details)
try:
source_size = source_stats['size'] & 0xFFFFFFFF
@@ -475,7 +470,7 @@ def _compile_bytecode(data, name=None, bytecode_path=None, source_path=None):
"""Compile bytecode as returned by _validate_bytecode_header()."""
code = marshal.loads(data)
if isinstance(code, _code_type):
- _verbose_message('code object from {!r}', bytecode_path)
+ _bootstrap._verbose_message('code object from {!r}', bytecode_path)
if source_path is not None:
_imp._fix_co_filename(code, source_path)
return code
@@ -602,7 +597,7 @@ class WindowsRegistryFinder:
else:
registry_key = cls.REGISTRY_KEY
key = registry_key.format(fullname=fullname,
- sys_version=sys.version[:3])
+ sys_version='%d.%d' % sys.version_info[:2])
try:
with cls._open_registry(key) as hkey:
filepath = _winreg.QueryValue(hkey, '')
@@ -665,6 +660,7 @@ class _LoaderBasics:
_bootstrap._call_with_frames_removed(exec, code, module.__dict__)
def load_module(self, fullname):
+ """This module is deprecated."""
return _bootstrap._load_module_shim(self, fullname)
@@ -758,21 +754,21 @@ class SourceLoader(_LoaderBasics):
except (ImportError, EOFError):
pass
else:
- _verbose_message('{} matches {}', bytecode_path,
- source_path)
+ _bootstrap._verbose_message('{} matches {}', bytecode_path,
+ source_path)
return _compile_bytecode(bytes_data, name=fullname,
bytecode_path=bytecode_path,
source_path=source_path)
source_bytes = self.get_data(source_path)
code_object = self.source_to_code(source_bytes, source_path)
- _verbose_message('code object from {}', source_path)
+ _bootstrap._verbose_message('code object from {}', source_path)
if (not sys.dont_write_bytecode and bytecode_path is not None and
source_mtime is not None):
data = _code_to_bytecode(code_object, source_mtime,
len(source_bytes))
try:
self._cache_bytecode(source_path, bytecode_path, data)
- _verbose_message('wrote {!r}', bytecode_path)
+ _bootstrap._verbose_message('wrote {!r}', bytecode_path)
except NotImplementedError:
pass
return code_object
@@ -852,14 +848,16 @@ class SourceFileLoader(FileLoader, SourceLoader):
except OSError as exc:
# Could be a permission error, read-only filesystem: just forget
# about writing the data.
- _verbose_message('could not create {!r}: {!r}', parent, exc)
+ _bootstrap._verbose_message('could not create {!r}: {!r}',
+ parent, exc)
return
try:
_write_atomic(path, data, _mode)
- _verbose_message('created {!r}', path)
+ _bootstrap._verbose_message('created {!r}', path)
except OSError as exc:
# Same as above: just don't write the bytecode.
- _verbose_message('could not create {!r}: {!r}', path, exc)
+ _bootstrap._verbose_message('could not create {!r}: {!r}', path,
+ exc)
class SourcelessFileLoader(FileLoader, _LoaderBasics):
@@ -904,14 +902,14 @@ class ExtensionFileLoader(FileLoader, _LoaderBasics):
"""Create an unitialized extension module"""
module = _bootstrap._call_with_frames_removed(
_imp.create_dynamic, spec)
- _verbose_message('extension module {!r} loaded from {!r}',
+ _bootstrap._verbose_message('extension module {!r} loaded from {!r}',
spec.name, self.path)
return module
def exec_module(self, module):
"""Initialize an extension module"""
_bootstrap._call_with_frames_removed(_imp.exec_dynamic, module)
- _verbose_message('extension module {!r} executed from {!r}',
+ _bootstrap._verbose_message('extension module {!r} executed from {!r}',
self.name, self.path)
def is_package(self, fullname):
@@ -977,6 +975,9 @@ class _NamespacePath:
def __iter__(self):
return iter(self._recalculate())
+ def __setitem__(self, index, path):
+ self._path[index] = path
+
def __len__(self):
return len(self._recalculate())
@@ -1026,7 +1027,8 @@ class _NamespaceLoader:
"""
# The import system never calls this method.
- _verbose_message('namespace module loaded with path {!r}', self._path)
+ _bootstrap._verbose_message('namespace module loaded with path {!r}',
+ self._path)
return _bootstrap._load_module_shim(self, fullname)
@@ -1246,12 +1248,13 @@ class FileFinder:
# Check for a file w/ a proper suffix exists.
for suffix, loader_class in self._loaders:
full_path = _path_join(self.path, tail_module + suffix)
- _verbose_message('trying {}'.format(full_path), verbosity=2)
+ _bootstrap._verbose_message('trying {}', full_path, verbosity=2)
if cache_module + suffix in cache:
if _path_isfile(full_path):
- return self._get_spec(loader_class, fullname, full_path, None, target)
+ return self._get_spec(loader_class, fullname, full_path,
+ None, target)
if is_namespace:
- _verbose_message('possible namespace for {}'.format(base_path))
+ _bootstrap._verbose_message('possible namespace for {}', base_path)
spec = _bootstrap.ModuleSpec(fullname, None)
spec.submodule_search_locations = [base_path]
return spec
diff --git a/Lib/importlib/util.py b/Lib/importlib/util.py
index 4525b3f78e..af781fd4cd 100644
--- a/Lib/importlib/util.py
+++ b/Lib/importlib/util.py
@@ -22,8 +22,8 @@ def resolve_name(name, package):
if not name.startswith('.'):
return name
elif not package:
- raise ValueError('{!r} is not a relative name '
- '(no leading dot)'.format(name))
+ raise ValueError(f'no package specified for {repr(name)} '
+ '(required for relative module names)')
level = 0
for character in name:
if character != '.':