Skip to content

Commit

Permalink
Issue #17177: The imp module is pending deprecation.
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
brettcannon committed Jun 16, 2013
1 parent 39295e7 commit e4f41de
Show file tree
Hide file tree
Showing 15 changed files with 103 additions and 85 deletions.
7 changes: 5 additions & 2 deletions Doc/library/imp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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:

Expand Down
3 changes: 3 additions & 0 deletions Doc/whatsnew/3.4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
-------------------------------------------
Expand Down
93 changes: 42 additions & 51 deletions Lib/imp.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
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
Expand Down Expand Up @@ -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]
Expand All @@ -110,7 +111,11 @@ def get_suffixes():

class NullImporter:

"""Null import object."""
"""**DEPRECATED**
Null import object.
"""

def __init__(self, path):
if path == '':
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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[:])
Expand All @@ -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):
Expand Down Expand Up @@ -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)

Expand Down
4 changes: 3 additions & 1 deletion Lib/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
__author__ = ('Ka-Ping Yee <ping@lfw.org>',
'Yury Selivanov <yselivanov@sprymix.com>')

import imp
import importlib.machinery
import itertools
import linecache
Expand Down Expand Up @@ -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()]
Expand Down
5 changes: 4 additions & 1 deletion Lib/modulefinder.py
Original file line number Diff line number Diff line change
@@ -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')])
Expand Down
22 changes: 16 additions & 6 deletions Lib/pkgutil.py
Original file line number Diff line number Diff line change
@@ -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',
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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):
Expand Down Expand Up @@ -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
Expand Down
8 changes: 6 additions & 2 deletions Lib/runpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
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

Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_fork1.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""This test checks for correct fork() behavior.
"""

import imp
import _imp as imp
import os
import signal
import sys
Expand Down
4 changes: 3 additions & 1 deletion Lib/test/test_imp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import _thread
except ImportError:
_thread = None
import imp
import importlib
import os
import os.path
Expand All @@ -11,6 +10,9 @@
from test import support
import unittest
import warnings
with warnings.catch_warnings():
warnings.simplefilter('ignore', PendingDeprecationWarning)
import imp


def requires_load_dynamic(meth):
Expand Down
Loading

0 comments on commit e4f41de

Please sign in to comment.