Issue #17177: The imp module is pending deprecation.

To make sure there is no issue with code that is both Python 2 and 3
compatible, there are no plans to remove the module any sooner than
Python 4 (unless the community moves to Python 3 solidly before then).
This commit is contained in:
Brett Cannon 2013-06-16 13:13:40 -04:00
parent 39295e7a55
commit e4f41deccf
15 changed files with 103 additions and 85 deletions

View File

@ -2,7 +2,7 @@
================================================================
.. deprecated:: 3.4
The :mod:`imp` package has been deprecated in favor of :mod:`importlib`.
The :mod:`imp` package is pending deprecation in favor of :mod:`importlib`.
.. module:: imp
:synopsis: Access the implementation of the import statement.
@ -232,7 +232,7 @@ file paths.
Return the :pep:`3147` magic tag string matching this version of Python's
magic number, as returned by :func:`get_magic`.
.. note::
.. deprecated:: 3.4
You may use :attr:`sys.implementation.cache_tag` directly starting
in Python 3.3.
@ -355,6 +355,9 @@ to indicate the search result of :func:`find_module`.
``None`` is inserted into ``sys.path_importer_cache`` instead of an
instance of :class:`NullImporter`.
.. deprecated:: 3.4
Insert ``None`` into ``sys.path_importer_cache`` instead.
.. _examples-imp:

View File

@ -230,6 +230,9 @@ Deprecated Python modules, functions and methods
:meth:`importlib.abc.Loader.init_module_attrs` allows subclasses of a loader
to more easily customize module loading.
* The :mod:`imp` module is pending deprecation. To keep compatibility with
Python 2/3 code bases, the module's removal is currently not scheduled.
Deprecated functions and types of the C API
-------------------------------------------

View File

@ -27,6 +27,9 @@ import tokenize
import types
import warnings
warnings.warn("the imp module is deprecated in favour of importlib; "
"see the module's documentation for alternative uses",
PendingDeprecationWarning)
# DEPRECATED
SEARCH_ERROR = 0
@ -98,9 +101,7 @@ def source_from_cache(path):
def get_suffixes():
warnings.warn('imp.get_suffixes() is deprecated; use the constants '
'defined on importlib.machinery instead',
DeprecationWarning, 2)
"""**DEPRECATED**"""
extensions = [(s, 'rb', C_EXTENSION) for s in machinery.EXTENSION_SUFFIXES]
source = [(s, 'U', PY_SOURCE) for s in machinery.SOURCE_SUFFIXES]
bytecode = [(s, 'rb', PY_COMPILED) for s in machinery.BYTECODE_SUFFIXES]
@ -110,7 +111,11 @@ def get_suffixes():
class NullImporter:
"""Null import object."""
"""**DEPRECATED**
Null import object.
"""
def __init__(self, path):
if path == '':
@ -152,10 +157,6 @@ class _LoadSourceCompatibility(_HackedGetData, machinery.SourceFileLoader):
def load_source(name, pathname, file=None):
msg = ('imp.load_source() is deprecated; use '
'importlib.machinery.SourceFileLoader(name, pathname).load_module()'
' instead')
warnings.warn(msg, DeprecationWarning, 2)
_LoadSourceCompatibility(name, pathname, file).load_module(name)
module = sys.modules[name]
# To allow reloading to potentially work, use a non-hacked loader which
@ -170,10 +171,7 @@ class _LoadCompiledCompatibility(_HackedGetData, SourcelessFileLoader):
def load_compiled(name, pathname, file=None):
msg = ('imp.load_compiled() is deprecated; use '
'importlib.machinery.SourcelessFileLoader(name, pathname).'
'load_module() instead ')
warnings.warn(msg, DeprecationWarning, 2)
"""**DEPRECATED**"""
_LoadCompiledCompatibility(name, pathname, file).load_module(name)
module = sys.modules[name]
# To allow reloading to potentially work, use a non-hacked loader which
@ -183,10 +181,7 @@ def load_compiled(name, pathname, file=None):
def load_package(name, path):
msg = ('imp.load_package() is deprecated; use either '
'importlib.machinery.SourceFileLoader() or '
'importlib.machinery.SourcelessFileLoader() instead')
warnings.warn(msg, DeprecationWarning, 2)
"""**DEPRECATED**"""
if os.path.isdir(path):
extensions = (machinery.SOURCE_SUFFIXES[:] +
machinery.BYTECODE_SUFFIXES[:])
@ -208,32 +203,30 @@ def load_module(name, file, filename, details):
"""
suffix, mode, type_ = details
with warnings.catch_warnings():
warnings.simplefilter('ignore')
if mode and (not mode.startswith(('r', 'U')) or '+' in mode):
raise ValueError('invalid file open mode {!r}'.format(mode))
elif file is None and type_ in {PY_SOURCE, PY_COMPILED}:
msg = 'file object required for import (type code {})'.format(type_)
raise ValueError(msg)
elif type_ == PY_SOURCE:
return load_source(name, filename, file)
elif type_ == PY_COMPILED:
return load_compiled(name, filename, file)
elif type_ == C_EXTENSION and load_dynamic is not None:
if file is None:
with open(filename, 'rb') as opened_file:
return load_dynamic(name, filename, opened_file)
else:
return load_dynamic(name, filename, file)
elif type_ == PKG_DIRECTORY:
return load_package(name, filename)
elif type_ == C_BUILTIN:
return init_builtin(name)
elif type_ == PY_FROZEN:
return init_frozen(name)
if mode and (not mode.startswith(('r', 'U')) or '+' in mode):
raise ValueError('invalid file open mode {!r}'.format(mode))
elif file is None and type_ in {PY_SOURCE, PY_COMPILED}:
msg = 'file object required for import (type code {})'.format(type_)
raise ValueError(msg)
elif type_ == PY_SOURCE:
return load_source(name, filename, file)
elif type_ == PY_COMPILED:
return load_compiled(name, filename, file)
elif type_ == C_EXTENSION and load_dynamic is not None:
if file is None:
with open(filename, 'rb') as opened_file:
return load_dynamic(name, filename, opened_file)
else:
msg = "Don't know how to import {} (type code {})".format(name, type_)
raise ImportError(msg, name=name)
return load_dynamic(name, filename, file)
elif type_ == PKG_DIRECTORY:
return load_package(name, filename)
elif type_ == C_BUILTIN:
return init_builtin(name)
elif type_ == PY_FROZEN:
return init_frozen(name)
else:
msg = "Don't know how to import {} (type code {})".format(name, type_)
raise ImportError(msg, name=name)
def find_module(name, path=None):
@ -269,16 +262,14 @@ def find_module(name, path=None):
file_path = os.path.join(package_directory, package_file_name)
if os.path.isfile(file_path):
return None, package_directory, ('', '', PKG_DIRECTORY)
with warnings.catch_warnings():
warnings.simplefilter('ignore')
for suffix, mode, type_ in get_suffixes():
file_name = name + suffix
file_path = os.path.join(entry, file_name)
if os.path.isfile(file_path):
break
else:
continue
break # Break out of outer loop when breaking out of inner loop.
for suffix, mode, type_ in get_suffixes():
file_name = name + suffix
file_path = os.path.join(entry, file_name)
if os.path.isfile(file_path):
break
else:
continue
break # Break out of outer loop when breaking out of inner loop.
else:
raise ImportError(_ERR_MSG.format(name), name=name)

View File

@ -31,7 +31,6 @@ Here are some of the useful functions provided by this module:
__author__ = ('Ka-Ping Yee <ping@lfw.org>',
'Yury Selivanov <yselivanov@sprymix.com>')
import imp
import importlib.machinery
import itertools
import linecache
@ -440,6 +439,9 @@ def getmoduleinfo(path):
"""Get the module name, suffix, mode, and module type for a given file."""
warnings.warn('inspect.getmoduleinfo() is deprecated', DeprecationWarning,
2)
with warnings.catch_warnings():
warnings.simplefilter('ignore', PendingDeprecationWarning)
import imp
filename = os.path.basename(path)
suffixes = [(-len(suffix), suffix, mode, mtype)
for suffix, mode, mtype in imp.get_suffixes()]

View File

@ -1,13 +1,16 @@
"""Find modules used by a script, using introspection."""
import dis
import imp
import importlib.machinery
import marshal
import os
import sys
import types
import struct
import warnings
with warnings.catch_warnings():
warnings.simplefilter('ignore', PendingDeprecationWarning)
import imp
# XXX Clean up once str8's cstor matches bytes.
LOAD_CONST = bytes([dis.opname.index('LOAD_CONST')])

View File

@ -1,13 +1,13 @@
"""Utilities to support packages."""
from functools import singledispatch as simplegeneric
import imp
import importlib
import importlib.util
import os
import os.path
import sys
from types import ModuleType
from warnings import warn
import warnings
__all__ = [
'get_importer', 'iter_importers', 'get_loader', 'find_loader',
@ -21,7 +21,7 @@ def read_code(stream):
import marshal
magic = stream.read(4)
if magic != imp.get_magic():
if magic != importlib.util.MAGIC_NUMBER:
return None
stream.read(8) # Skip timestamp and size
@ -160,6 +160,13 @@ def _iter_file_finder_modules(importer, prefix=''):
iter_importer_modules.register(
importlib.machinery.FileFinder, _iter_file_finder_modules)
def _import_imp():
global imp
with warnings.catch_warnings():
warnings.simplefilter('ignore', PendingDeprecationWarning)
imp = importlib.import_module('imp')
class ImpImporter:
"""PEP 302 Importer that wraps Python's "classic" import algorithm
@ -172,8 +179,10 @@ class ImpImporter:
"""
def __init__(self, path=None):
warn("This emulation is deprecated, use 'importlib' instead",
global imp
warnings.warn("This emulation is deprecated, use 'importlib' instead",
DeprecationWarning)
_import_imp()
self.path = path
def find_module(self, fullname, path=None):
@ -238,8 +247,9 @@ class ImpLoader:
code = source = None
def __init__(self, fullname, file, filename, etc):
warn("This emulation is deprecated, use 'importlib' instead",
DeprecationWarning)
warnings.warn("This emulation is deprecated, use 'importlib' instead",
DeprecationWarning)
_import_imp()
self.file = file
self.filename = filename
self.fullname = fullname

View File

@ -13,7 +13,6 @@ importers when locating support scripts as well as when importing modules.
import os
import sys
import importlib.machinery # importlib first so we can test #15386 via -m
import imp
import types
from pkgutil import read_code, get_loader, get_importer
@ -224,7 +223,12 @@ def run_path(path_name, init_globals=None, run_name=None):
run_name = "<run_path>"
pkg_name = run_name.rpartition(".")[0]
importer = get_importer(path_name)
if isinstance(importer, (type(None), imp.NullImporter)):
# Trying to avoid importing imp so as to not consume the deprecation warning.
is_NullImporter = False
if type(importer).__module__ == 'imp':
if type(importer).__name__ == 'NullImporter':
is_NullImporter = True
if isinstance(importer, type(None)) or is_NullImporter:
# Not a valid sys.path entry, so run the code directly
# execfile() doesn't help as we want to allow compiled files
code, mod_loader = _get_code_from_file(run_name, path_name)

View File

@ -1,7 +1,7 @@
"""This test checks for correct fork() behavior.
"""
import imp
import _imp as imp
import os
import signal
import sys

View File

@ -2,7 +2,6 @@ try:
import _thread
except ImportError:
_thread = None
import imp
import importlib
import os
import os.path
@ -11,6 +10,9 @@ import sys
from test import support
import unittest
import warnings
with warnings.catch_warnings():
warnings.simplefilter('ignore', PendingDeprecationWarning)
import imp
def requires_load_dynamic(meth):

View File

@ -1,7 +1,7 @@
# We import importlib *ASAP* in order to test #15386
import importlib
import importlib.util
import builtins
import imp
from test.test_importlib.import_ import util as importlib_util
import marshal
import os
@ -221,7 +221,7 @@ class ImportTests(unittest.TestCase):
with open(source, "w") as f:
f.write("a = 10\nb=20//0\n")
self.assertRaises(ZeroDivisionError, imp.reload, mod)
self.assertRaises(ZeroDivisionError, importlib.reload, mod)
# But we still expect the module to be in sys.modules.
mod = sys.modules.get(TESTFN)
self.assertIsNot(mod, None, "expected module to be in sys.modules")
@ -287,7 +287,7 @@ class ImportTests(unittest.TestCase):
import sys
class C:
def __del__(self):
import imp
import importlib
sys.argv.insert(0, C())
"""))
script_helper.assert_python_ok(testfn)
@ -298,7 +298,7 @@ class ImportTests(unittest.TestCase):
sys.path.insert(0, os.curdir)
try:
source = TESTFN + ".py"
compiled = imp.cache_from_source(source)
compiled = importlib.util.cache_from_source(source)
with open(source, 'w') as f:
pass
try:
@ -339,7 +339,7 @@ class FilePermissionTests(unittest.TestCase):
def test_creation_mode(self):
mask = 0o022
with temp_umask(mask), _ready_to_import() as (name, path):
cached_path = imp.cache_from_source(path)
cached_path = importlib.util.cache_from_source(path)
module = __import__(name)
if not os.path.exists(cached_path):
self.fail("__import__ did not result in creation of "
@ -357,7 +357,7 @@ class FilePermissionTests(unittest.TestCase):
# permissions of .pyc should match those of .py, regardless of mask
mode = 0o600
with temp_umask(0o022), _ready_to_import() as (name, path):
cached_path = imp.cache_from_source(path)
cached_path = importlib.util.cache_from_source(path)
os.chmod(path, mode)
__import__(name)
if not os.path.exists(cached_path):
@ -372,7 +372,7 @@ class FilePermissionTests(unittest.TestCase):
def test_cached_readonly(self):
mode = 0o400
with temp_umask(0o022), _ready_to_import() as (name, path):
cached_path = imp.cache_from_source(path)
cached_path = importlib.util.cache_from_source(path)
os.chmod(path, mode)
__import__(name)
if not os.path.exists(cached_path):
@ -412,7 +412,7 @@ class FilePermissionTests(unittest.TestCase):
bytecode_only = path + "c"
else:
bytecode_only = path + "o"
os.rename(imp.cache_from_source(path), bytecode_only)
os.rename(importlib.util.cache_from_source(path), bytecode_only)
m = __import__(name)
self.assertEqual(m.x, 'rewritten')
@ -434,7 +434,7 @@ func_filename = func.__code__.co_filename
"""
dir_name = os.path.abspath(TESTFN)
file_name = os.path.join(dir_name, module_name) + os.extsep + "py"
compiled_name = imp.cache_from_source(file_name)
compiled_name = importlib.util.cache_from_source(file_name)
def setUp(self):
self.sys_path = sys.path[:]
@ -637,7 +637,7 @@ class OverridingImportBuiltinTests(unittest.TestCase):
class PycacheTests(unittest.TestCase):
# Test the various PEP 3147 related behaviors.
tag = imp.get_tag()
tag = sys.implementation.cache_tag
def _clean(self):
forget(TESTFN)
@ -685,7 +685,7 @@ class PycacheTests(unittest.TestCase):
# With PEP 3147 cache layout, removing the source but leaving the pyc
# file does not satisfy the import.
__import__(TESTFN)
pyc_file = imp.cache_from_source(self.source)
pyc_file = importlib.util.cache_from_source(self.source)
self.assertTrue(os.path.exists(pyc_file))
os.remove(self.source)
forget(TESTFN)
@ -710,7 +710,7 @@ class PycacheTests(unittest.TestCase):
def test___cached__(self):
# Modules now also have an __cached__ that points to the pyc file.
m = __import__(TESTFN)
pyc_file = imp.cache_from_source(TESTFN + '.py')
pyc_file = importlib.util.cache_from_source(TESTFN + '.py')
self.assertEqual(m.__cached__, os.path.join(os.curdir, pyc_file))
@skip_if_dont_write_bytecode
@ -745,10 +745,10 @@ class PycacheTests(unittest.TestCase):
pass
importlib.invalidate_caches()
m = __import__('pep3147.foo')
init_pyc = imp.cache_from_source(
init_pyc = importlib.util.cache_from_source(
os.path.join('pep3147', '__init__.py'))
self.assertEqual(m.__cached__, os.path.join(os.curdir, init_pyc))
foo_pyc = imp.cache_from_source(os.path.join('pep3147', 'foo.py'))
foo_pyc = importlib.util.cache_from_source(os.path.join('pep3147', 'foo.py'))
self.assertEqual(sys.modules['pep3147.foo'].__cached__,
os.path.join(os.curdir, foo_pyc))
@ -772,10 +772,10 @@ class PycacheTests(unittest.TestCase):
unload('pep3147')
importlib.invalidate_caches()
m = __import__('pep3147.foo')
init_pyc = imp.cache_from_source(
init_pyc = importlib.util.cache_from_source(
os.path.join('pep3147', '__init__.py'))
self.assertEqual(m.__cached__, os.path.join(os.curdir, init_pyc))
foo_pyc = imp.cache_from_source(os.path.join('pep3147', 'foo.py'))
foo_pyc = importlib.util.cache_from_source(os.path.join('pep3147', 'foo.py'))
self.assertEqual(sys.modules['pep3147.foo'].__cached__,
os.path.join(os.curdir, foo_pyc))

View File

@ -1,6 +1,5 @@
from .. import util as importlib_test_util
from . import util
import imp
import sys
import types
import unittest

View File

@ -7,7 +7,6 @@ from .. import util
from . import util as source_util
import errno
import imp
import marshal
import os
import py_compile

View File

@ -2,8 +2,8 @@
Test suite for socketserver.
"""
import _imp as imp
import contextlib
import imp
import os
import select
import signal

View File

@ -5,8 +5,8 @@
# complains several times about module random having no attribute
# randrange, and then Python hangs.
import _imp as imp
import os
import imp
import importlib
import sys
import time

View File

@ -123,6 +123,8 @@ Core and Builtins
Library
-------
- Issue #17177: The imp module is pending deprecation.
- subprocess: Prevent a possible double close of parent pipe fds when the
subprocess exec runs into an error. Prevent a regular multi-close of the
/dev/null fd when any of stdin, stdout and stderr was set to DEVNULL.