]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-98040: Remove just the `imp` module (#98573)
authorBarry Warsaw <barry@python.org>
Fri, 28 Apr 2023 23:17:58 +0000 (16:17 -0700)
committerGitHub <noreply@github.com>
Fri, 28 Apr 2023 23:17:58 +0000 (16:17 -0700)
24 files changed:
Doc/c-api/import.rst
Doc/library/functions.rst
Doc/library/imp.rst [deleted file]
Doc/library/superseded.rst
Doc/library/sys.rst
Doc/reference/import.rst
Doc/tools/.nitignore
Doc/whatsnew/3.12.rst
Lib/imp.py [deleted file]
Lib/pkgutil.py
Lib/pydoc.py
Lib/runpy.py
Lib/test/test_imp.py [deleted file]
Lib/test/test_importlib/util.py
Lib/test/test_pkgutil.py
Misc/NEWS.d/next/Library/2022-10-21-17-20-57.gh-issue-98040.3btbmA.rst [new file with mode: 0644]
Modules/_testmultiphase.c
Python/import.c
Python/makeopcodetargets.py
Python/pylifecycle.c
Python/stdlib_module_names.h
Tools/build/generate_stdlib_module_names.py
Tools/c-analyzer/TODO
Tools/importbench/importbench.py

index a51619db6d3d97c7fc935ef45c6d0c639827775c..474a64800044d08ba2fe07d1a436f68cdd53299e 100644 (file)
@@ -188,6 +188,8 @@ Importing Modules
    .. versionchanged:: 3.3
       Uses :func:`imp.source_from_cache()` in calculating the source path if
       only the bytecode path is provided.
+   .. versionchanged:: 3.12
+      No longer uses the removed ``imp`` module.
 
 
 .. c:function:: long PyImport_GetMagicNumber()
index 7792e598c1155cdf9e8306161faf5a1801d3f660..a5e86ef0f9eb59f96e097a85470dbc7082f79b31 100644 (file)
@@ -1987,7 +1987,6 @@ are always available.  They are listed here in alphabetical order.
 
    .. index::
       statement: import
-      module: imp
 
    .. note::
 
diff --git a/Doc/library/imp.rst b/Doc/library/imp.rst
deleted file mode 100644 (file)
index 000793a..0000000
+++ /dev/null
@@ -1,411 +0,0 @@
-:mod:`imp` --- Access the :ref:`import <importsystem>` internals
-================================================================
-
-.. module:: imp
-   :synopsis: Access the implementation of the import statement.
-   :deprecated:
-
-**Source code:** :source:`Lib/imp.py`
-
-.. deprecated-removed:: 3.4 3.12
-   The :mod:`imp` module is deprecated in favor of :mod:`importlib`.
-
-.. index:: statement: import
-
---------------
-
-This module provides an interface to the mechanisms used to implement the
-:keyword:`import` statement.  It defines the following constants and functions:
-
-
-.. function:: get_magic()
-
-   .. index:: pair: file; byte-code
-
-   Return the magic string value used to recognize byte-compiled code files
-   (:file:`.pyc` files).  (This value may be different for each Python version.)
-
-   .. deprecated:: 3.4
-       Use :attr:`importlib.util.MAGIC_NUMBER` instead.
-
-
-.. function:: get_suffixes()
-
-   Return a list of 3-element tuples, each describing a particular type of
-   module. Each triple has the form ``(suffix, mode, type)``, where *suffix* is
-   a string to be appended to the module name to form the filename to search
-   for, *mode* is the mode string to pass to the built-in :func:`open` function
-   to open the file (this can be ``'r'`` for text files or ``'rb'`` for binary
-   files), and *type* is the file type, which has one of the values
-   :const:`PY_SOURCE`, :const:`PY_COMPILED`, or :const:`C_EXTENSION`, described
-   below.
-
-   .. deprecated:: 3.3
-      Use the constants defined on :mod:`importlib.machinery` instead.
-
-
-.. function:: find_module(name[, path])
-
-   Try to find the module *name*.  If *path* is omitted or ``None``, the list of
-   directory names given by ``sys.path`` is searched, but first a few special
-   places are searched: the function tries to find a built-in module with the
-   given name (:const:`C_BUILTIN`), then a frozen module (:const:`PY_FROZEN`),
-   and on some systems some other places are looked in as well (on Windows, it
-   looks in the registry which may point to a specific file).
-
-   Otherwise, *path* must be a list of directory names; each directory is
-   searched for files with any of the suffixes returned by :func:`get_suffixes`
-   above.  Invalid names in the list are silently ignored (but all list items
-   must be strings).
-
-   If search is successful, the return value is a 3-element tuple ``(file,
-   pathname, description)``:
-
-   *file* is an open :term:`file object` positioned at the beginning, *pathname*
-   is the pathname of the file found, and *description* is a 3-element tuple as
-   contained in the list returned by :func:`get_suffixes` describing the kind of
-   module found.
-
-   If the module is built-in or frozen then *file* and *pathname* are both ``None``
-   and the *description* tuple contains empty strings for its suffix and mode;
-   the module type is indicated as given in parentheses above.  If the search
-   is unsuccessful, :exc:`ImportError` is raised.  Other exceptions indicate
-   problems with the arguments or environment.
-
-   If the module is a package, *file* is ``None``, *pathname* is the package
-   path and the last item in the *description* tuple is :const:`PKG_DIRECTORY`.
-
-   This function does not handle hierarchical module names (names containing
-   dots).  In order to find *P.M*, that is, submodule *M* of package *P*, use
-   :func:`find_module` and :func:`load_module` to find and load package *P*, and
-   then use :func:`find_module` with the *path* argument set to ``P.__path__``.
-   When *P* itself has a dotted name, apply this recipe recursively.
-
-   .. deprecated:: 3.3
-      Use :func:`importlib.util.find_spec` instead unless Python 3.3
-      compatibility is required, in which case use
-      :func:`importlib.find_loader`. For example usage of the former case,
-      see the :ref:`importlib-examples` section of the :mod:`importlib`
-      documentation.
-
-
-.. function:: load_module(name, file, pathname, description)
-
-   Load a module that was previously found by :func:`find_module` (or by an
-   otherwise conducted search yielding compatible results).  This function does
-   more than importing the module: if the module was already imported, it will
-   reload the module!  The *name* argument indicates the full
-   module name (including the package name, if this is a submodule of a
-   package).  The *file* argument is an open file, and *pathname* is the
-   corresponding file name; these can be ``None`` and ``''``, respectively, when
-   the module is a package or not being loaded from a file.  The *description*
-   argument is a tuple, as would be returned by :func:`get_suffixes`, describing
-   what kind of module must be loaded.
-
-   If the load is successful, the return value is the module object; otherwise,
-   an exception (usually :exc:`ImportError`) is raised.
-
-   **Important:** the caller is responsible for closing the *file* argument, if
-   it was not ``None``, even when an exception is raised.  This is best done
-   using a :keyword:`try` ... :keyword:`finally` statement.
-
-   .. deprecated:: 3.3
-      If previously used in conjunction with :func:`imp.find_module` then
-      consider using :func:`importlib.import_module`, otherwise use the loader
-      returned by the replacement you chose for :func:`imp.find_module`. If you
-      called :func:`imp.load_module` and related functions directly with file
-      path arguments then use a combination of
-      :func:`importlib.util.spec_from_file_location` and
-      :func:`importlib.util.module_from_spec`. See the :ref:`importlib-examples`
-      section of the :mod:`importlib` documentation for details of the various
-      approaches.
-
-
-.. function:: new_module(name)
-
-   Return a new empty module object called *name*.  This object is *not* inserted
-   in ``sys.modules``.
-
-   .. deprecated:: 3.4
-      Use :func:`importlib.util.module_from_spec` instead.
-
-
-.. function:: reload(module)
-
-   Reload a previously imported *module*.  The argument must be a module object, so
-   it must have been successfully imported before.  This is useful if you have
-   edited the module source file using an external editor and want to try out the
-   new version without leaving the Python interpreter.  The return value is the
-   module object (the same as the *module* argument).
-
-   When ``reload(module)`` is executed:
-
-   * Python modules' code is recompiled and the module-level code reexecuted,
-     defining a new set of objects which are bound to names in the module's
-     dictionary.  The ``init`` function of extension modules is not called a second
-     time.
-
-   * As with all other objects in Python the old objects are only reclaimed after
-     their reference counts drop to zero.
-
-   * The names in the module namespace are updated to point to any new or changed
-     objects.
-
-   * Other references to the old objects (such as names external to the module) are
-     not rebound to refer to the new objects and must be updated in each namespace
-     where they occur if that is desired.
-
-   There are a number of other caveats:
-
-   When a module is reloaded, its dictionary (containing the module's global
-   variables) is retained.  Redefinitions of names will override the old
-   definitions, so this is generally not a problem.  If the new version of a module
-   does not define a name that was defined by the old version, the old definition
-   remains.  This feature can be used to the module's advantage if it maintains a
-   global table or cache of objects --- with a :keyword:`try` statement it can test
-   for the table's presence and skip its initialization if desired::
-
-      try:
-          cache
-      except NameError:
-          cache = {}
-
-   It is legal though generally not very useful to reload built-in or dynamically
-   loaded modules, except for :mod:`sys`, :mod:`__main__` and :mod:`builtins`.
-   In many cases, however, extension modules are not designed to be initialized
-   more than once, and may fail in arbitrary ways when reloaded.
-
-   If a module imports objects from another module using :keyword:`from` ...
-   :keyword:`import` ..., calling :func:`reload` for the other module does not
-   redefine the objects imported from it --- one way around this is to re-execute
-   the :keyword:`!from` statement, another is to use :keyword:`!import` and qualified
-   names (*module*.*name*) instead.
-
-   If a module instantiates instances of a class, reloading the module that defines
-   the class does not affect the method definitions of the instances --- they
-   continue to use the old class definition.  The same is true for derived classes.
-
-   .. versionchanged:: 3.3
-      Relies on both ``__name__`` and ``__loader__`` being defined on the module
-      being reloaded instead of just ``__name__``.
-
-   .. deprecated:: 3.4
-      Use :func:`importlib.reload` instead.
-
-
-The following functions are conveniences for handling :pep:`3147` byte-compiled
-file paths.
-
-.. versionadded:: 3.2
-
-.. function:: cache_from_source(path, debug_override=None)
-
-   Return the :pep:`3147` path to the byte-compiled file associated with the
-   source *path*.  For example, if *path* is ``/foo/bar/baz.py`` the return
-   value would be ``/foo/bar/__pycache__/baz.cpython-32.pyc`` for Python 3.2.
-   The ``cpython-32`` string comes from the current magic tag (see
-   :func:`get_tag`; if :attr:`sys.implementation.cache_tag` is not defined then
-   :exc:`NotImplementedError` will be raised). By passing in ``True`` or
-   ``False`` for *debug_override* you can override the system's value for
-   ``__debug__``, leading to optimized bytecode.
-
-   *path* need not exist.
-
-   .. versionchanged:: 3.3
-      If :attr:`sys.implementation.cache_tag` is ``None``, then
-      :exc:`NotImplementedError` is raised.
-
-   .. deprecated:: 3.4
-      Use :func:`importlib.util.cache_from_source` instead.
-
-   .. versionchanged:: 3.5
-      The *debug_override* parameter no longer creates a ``.pyo`` file.
-
-
-.. function:: source_from_cache(path)
-
-   Given the *path* to a :pep:`3147` file name, return the associated source code
-   file path.  For example, if *path* is
-   ``/foo/bar/__pycache__/baz.cpython-32.pyc`` the returned path would be
-   ``/foo/bar/baz.py``.  *path* need not exist, however if it does not conform
-   to :pep:`3147` format, a :exc:`ValueError` is raised. If
-   :attr:`sys.implementation.cache_tag` is not defined,
-   :exc:`NotImplementedError` is raised.
-
-   .. versionchanged:: 3.3
-      Raise :exc:`NotImplementedError` when
-      :attr:`sys.implementation.cache_tag` is not defined.
-
-   .. deprecated:: 3.4
-      Use :func:`importlib.util.source_from_cache` instead.
-
-
-.. function:: get_tag()
-
-   Return the :pep:`3147` magic tag string matching this version of Python's
-   magic number, as returned by :func:`get_magic`.
-
-   .. deprecated:: 3.4
-      Use :attr:`sys.implementation.cache_tag` directly starting
-      in Python 3.3.
-
-
-The following functions help interact with the import system's internal
-locking mechanism.  Locking semantics of imports are an implementation
-detail which may vary from release to release.  However, Python ensures
-that circular imports work without any deadlocks.
-
-
-.. function:: lock_held()
-
-   Return ``True`` if the global import lock is currently held, else
-   ``False``. On platforms without threads, always return ``False``.
-
-   On platforms with threads, a thread executing an import first holds a
-   global import lock, then sets up a per-module lock for the rest of the
-   import.  This blocks other threads from importing the same module until
-   the original import completes, preventing other threads from seeing
-   incomplete module objects constructed by the original thread.  An
-   exception is made for circular imports, which by construction have to
-   expose an incomplete module object at some point.
-
-   .. versionchanged:: 3.3
-      The locking scheme has changed to per-module locks for
-      the most part.  A global import lock is kept for some critical tasks,
-      such as initializing the per-module locks.
-
-   .. deprecated:: 3.4
-
-
-.. function:: acquire_lock()
-
-   Acquire the interpreter's global import lock for the current thread.
-   This lock should be used by import hooks to ensure thread-safety when
-   importing modules.
-
-   Once a thread has acquired the import lock, the same thread may acquire it
-   again without blocking; the thread must release it once for each time it has
-   acquired it.
-
-   On platforms without threads, this function does nothing.
-
-   .. versionchanged:: 3.3
-      The locking scheme has changed to per-module locks for
-      the most part.  A global import lock is kept for some critical tasks,
-      such as initializing the per-module locks.
-
-   .. deprecated:: 3.4
-
-
-.. function:: release_lock()
-
-   Release the interpreter's global import lock. On platforms without
-   threads, this function does nothing.
-
-   .. versionchanged:: 3.3
-      The locking scheme has changed to per-module locks for
-      the most part.  A global import lock is kept for some critical tasks,
-      such as initializing the per-module locks.
-
-   .. deprecated:: 3.4
-
-
-The following constants with integer values, defined in this module, are used
-to indicate the search result of :func:`find_module`.
-
-
-.. data:: PY_SOURCE
-
-   The module was found as a source file.
-
-   .. deprecated:: 3.3
-
-
-.. data:: PY_COMPILED
-
-   The module was found as a compiled code object file.
-
-   .. deprecated:: 3.3
-
-
-.. data:: C_EXTENSION
-
-   The module was found as dynamically loadable shared library.
-
-   .. deprecated:: 3.3
-
-
-.. data:: PKG_DIRECTORY
-
-   The module was found as a package directory.
-
-   .. deprecated:: 3.3
-
-
-.. data:: C_BUILTIN
-
-   The module was found as a built-in module.
-
-   .. deprecated:: 3.3
-
-
-.. data:: PY_FROZEN
-
-   The module was found as a frozen module.
-
-   .. deprecated:: 3.3
-
-
-.. class:: NullImporter(path_string)
-
-   The :class:`NullImporter` type is a :pep:`302` import hook that handles
-   non-directory path strings by failing to find any modules.  Calling this type
-   with an existing directory or empty string raises :exc:`ImportError`.
-   Otherwise, a :class:`NullImporter` instance is returned.
-
-   Instances have only one method:
-
-   .. method:: NullImporter.find_module(fullname [, path])
-
-      This method always returns ``None``, indicating that the requested module could
-      not be found.
-
-   .. versionchanged:: 3.3
-      ``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:
-
-Examples
---------
-
-The following function emulates what was the standard import statement up to
-Python 1.4 (no hierarchical module names).  (This *implementation* wouldn't work
-in that version, since :func:`find_module` has been extended and
-:func:`load_module` has been added in 1.4.) ::
-
-   import imp
-   import sys
-
-   def __import__(name, globals=None, locals=None, fromlist=None):
-       # Fast path: see if the module has already been imported.
-       try:
-           return sys.modules[name]
-       except KeyError:
-           pass
-
-       # If any of the following calls raises an exception,
-       # there's a problem we can't handle -- let the caller handle it.
-
-       fp, pathname, description = imp.find_module(name)
-
-       try:
-           return imp.load_module(name, fp, pathname, description)
-       finally:
-           # Since we may exit via an exception, close fp explicitly.
-           if fp:
-               fp.close()
index 8786e227be918259f6d060134ee0c117692bd72b..aaf66ea121d39c85c02d11a562f3a98164af66b5 100644 (file)
@@ -17,7 +17,6 @@ backwards compatibility. They have been superseded by other modules.
    chunk.rst
    crypt.rst
    imghdr.rst
-   imp.rst
    mailcap.rst
    msilib.rst
    nis.rst
index 7324f3113e0a08feea09e8e124d4581b57256264..7c0e85142e7716a19796a54fd05ad26c30819cd4 100644 (file)
@@ -1253,10 +1253,6 @@ always available.
 
     Originally specified in :pep:`302`.
 
-    .. versionchanged:: 3.3
-       ``None`` is stored instead of :class:`imp.NullImporter` when no finder
-       is found.
-
 
 .. data:: platform
 
index b22b5251f1de469b4e3d1413af47192094a69a71..57eb5403243eef9484449e0755b8b09a81362df4 100644 (file)
@@ -1077,4 +1077,5 @@ methods to finders and loaders.
 .. [#fnpic] In legacy code, it is possible to find instances of
    :class:`imp.NullImporter` in the :data:`sys.path_importer_cache`.  It
    is recommended that code be changed to use ``None`` instead.  See
-   :ref:`portingpythoncode` for more details.
+   :ref:`portingpythoncode` for more details.  Note that the ``imp`` module
+   was removed in Python 3.12.
index f3350174f931aae32799fee0c7a859e64ab4ed21..1d3503bf06f085522c3ca780842f3a5b6e1c057d 100644 (file)
@@ -149,7 +149,6 @@ Doc/library/http.cookiejar.rst
 Doc/library/http.cookies.rst
 Doc/library/http.server.rst
 Doc/library/idle.rst
-Doc/library/imp.rst
 Doc/library/importlib.resources.abc.rst
 Doc/library/importlib.resources.rst
 Doc/library/importlib.rst
index 291500532493c65902565df04b3561c1e5912f76..a75e88c2615acaf1e452c803903991f742c69a79 100644 (file)
@@ -961,11 +961,14 @@ Removed
   completed:
 
   * References to, and support for ``module_repr()`` has been eradicated.
-
+    (Contributed by Barry Warsaw in :gh:`97850`.)
 
 * ``importlib.util.set_package`` has been removed.
   (Contributed by Brett Cannon in :gh:`65961`.)
 
+* The ``imp`` module has been removed.  (Contributed by Barry Warsaw in
+  :gh:`98040`.)
+
 * Removed the ``suspicious`` rule from the documentation Makefile, and
   removed ``Doc/tools/rstlint.py``, both in favor of `sphinx-lint
   <https://github.com/sphinx-contrib/sphinx-lint>`_.
diff --git a/Lib/imp.py b/Lib/imp.py
deleted file mode 100644 (file)
index fe850f6..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-"""This module provides the components needed to build your own __import__
-function.  Undocumented functions are obsolete.
-
-In most cases it is preferred you consider using the importlib module's
-functionality over this module.
-
-"""
-# (Probably) need to stay in _imp
-from _imp import (lock_held, acquire_lock, release_lock,
-                  get_frozen_object, is_frozen_package,
-                  init_frozen, is_builtin, is_frozen,
-                  _fix_co_filename, _frozen_module_names)
-try:
-    from _imp import create_dynamic
-except ImportError:
-    # Platform doesn't support dynamic loading.
-    create_dynamic = None
-
-from importlib._bootstrap import _ERR_MSG, _exec, _load, _builtin_from_name
-from importlib._bootstrap_external import SourcelessFileLoader
-
-from importlib import machinery
-from importlib import util
-import importlib
-import os
-import sys
-import tokenize
-import types
-import warnings
-
-warnings.warn("the imp module is deprecated in favour of importlib and slated "
-              "for removal in Python 3.12; "
-              "see the module's documentation for alternative uses",
-              DeprecationWarning, stacklevel=2)
-
-# DEPRECATED
-SEARCH_ERROR = 0
-PY_SOURCE = 1
-PY_COMPILED = 2
-C_EXTENSION = 3
-PY_RESOURCE = 4
-PKG_DIRECTORY = 5
-C_BUILTIN = 6
-PY_FROZEN = 7
-PY_CODERESOURCE = 8
-IMP_HOOK = 9
-
-
-def new_module(name):
-    """**DEPRECATED**
-
-    Create a new module.
-
-    The module is not entered into sys.modules.
-
-    """
-    return types.ModuleType(name)
-
-
-def get_magic():
-    """**DEPRECATED**
-
-    Return the magic number for .pyc files.
-    """
-    return util.MAGIC_NUMBER
-
-
-def get_tag():
-    """Return the magic tag for .pyc files."""
-    return sys.implementation.cache_tag
-
-
-def cache_from_source(path, debug_override=None):
-    """**DEPRECATED**
-
-    Given the path to a .py file, return the path to its .pyc file.
-
-    The .py file does not need to exist; this simply returns the path to the
-    .pyc file calculated as if the .py file were imported.
-
-    If debug_override is not None, then it must be a boolean and is used in
-    place of sys.flags.optimize.
-
-    If sys.implementation.cache_tag is None then NotImplementedError is raised.
-
-    """
-    with warnings.catch_warnings():
-        warnings.simplefilter('ignore')
-        return util.cache_from_source(path, debug_override)
-
-
-def source_from_cache(path):
-    """**DEPRECATED**
-
-    Given the path to a .pyc. file, return the path to its .py file.
-
-    The .pyc file does not need to exist; this simply returns the path to
-    the .py file calculated to correspond to the .pyc file.  If path does
-    not conform to PEP 3147 format, ValueError will be raised. If
-    sys.implementation.cache_tag is None then NotImplementedError is raised.
-
-    """
-    return util.source_from_cache(path)
-
-
-def get_suffixes():
-    """**DEPRECATED**"""
-    extensions = [(s, 'rb', C_EXTENSION) for s in machinery.EXTENSION_SUFFIXES]
-    source = [(s, 'r', PY_SOURCE) for s in machinery.SOURCE_SUFFIXES]
-    bytecode = [(s, 'rb', PY_COMPILED) for s in machinery.BYTECODE_SUFFIXES]
-
-    return extensions + source + bytecode
-
-
-class NullImporter:
-
-    """**DEPRECATED**
-
-    Null import object.
-
-    """
-
-    def __init__(self, path):
-        if path == '':
-            raise ImportError('empty pathname', path='')
-        elif os.path.isdir(path):
-            raise ImportError('existing directory', path=path)
-
-    def find_module(self, fullname):
-        """Always returns None."""
-        return None
-
-
-class _HackedGetData:
-
-    """Compatibility support for 'file' arguments of various load_*()
-    functions."""
-
-    def __init__(self, fullname, path, file=None):
-        super().__init__(fullname, path)
-        self.file = file
-
-    def get_data(self, path):
-        """Gross hack to contort loader to deal w/ load_*()'s bad API."""
-        if self.file and path == self.path:
-            # The contract of get_data() requires us to return bytes. Reopen the
-            # file in binary mode if needed.
-            if not self.file.closed:
-                file = self.file
-                if 'b' not in file.mode:
-                    file.close()
-            if self.file.closed:
-                self.file = file = open(self.path, 'rb')
-
-            with file:
-                return file.read()
-        else:
-            return super().get_data(path)
-
-
-class _LoadSourceCompatibility(_HackedGetData, machinery.SourceFileLoader):
-
-    """Compatibility support for implementing load_source()."""
-
-
-def load_source(name, pathname, file=None):
-    loader = _LoadSourceCompatibility(name, pathname, file)
-    spec = util.spec_from_file_location(name, pathname, loader=loader)
-    if name in sys.modules:
-        module = _exec(spec, sys.modules[name])
-    else:
-        module = _load(spec)
-    # To allow reloading to potentially work, use a non-hacked loader which
-    # won't rely on a now-closed file object.
-    module.__loader__ = machinery.SourceFileLoader(name, pathname)
-    module.__spec__.loader = module.__loader__
-    return module
-
-
-class _LoadCompiledCompatibility(_HackedGetData, SourcelessFileLoader):
-
-    """Compatibility support for implementing load_compiled()."""
-
-
-def load_compiled(name, pathname, file=None):
-    """**DEPRECATED**"""
-    loader = _LoadCompiledCompatibility(name, pathname, file)
-    spec = util.spec_from_file_location(name, pathname, loader=loader)
-    if name in sys.modules:
-        module = _exec(spec, sys.modules[name])
-    else:
-        module = _load(spec)
-    # To allow reloading to potentially work, use a non-hacked loader which
-    # won't rely on a now-closed file object.
-    module.__loader__ = SourcelessFileLoader(name, pathname)
-    module.__spec__.loader = module.__loader__
-    return module
-
-
-def load_package(name, path):
-    """**DEPRECATED**"""
-    if os.path.isdir(path):
-        extensions = (machinery.SOURCE_SUFFIXES[:] +
-                      machinery.BYTECODE_SUFFIXES[:])
-        for extension in extensions:
-            init_path = os.path.join(path, '__init__' + extension)
-            if os.path.exists(init_path):
-                path = init_path
-                break
-        else:
-            raise ValueError('{!r} is not a package'.format(path))
-    spec = util.spec_from_file_location(name, path,
-                                        submodule_search_locations=[])
-    if name in sys.modules:
-        return _exec(spec, sys.modules[name])
-    else:
-        return _load(spec)
-
-
-def load_module(name, file, filename, details):
-    """**DEPRECATED**
-
-    Load a module, given information returned by find_module().
-
-    The module name must include the full package name, if any.
-
-    """
-    suffix, mode, type_ = details
-    if mode and (not mode.startswith('r') 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)
-    else:
-        msg =  "Don't know how to import {} (type code {})".format(name, type_)
-        raise ImportError(msg, name=name)
-
-
-def find_module(name, path=None):
-    """**DEPRECATED**
-
-    Search for a module.
-
-    If path is omitted or None, search for a built-in, frozen or special
-    module and continue search in sys.path. The module name cannot
-    contain '.'; to search for a submodule of a package, pass the
-    submodule name and the package's __path__.
-
-    """
-    if not isinstance(name, str):
-        raise TypeError("'name' must be a str, not {}".format(type(name)))
-    elif not isinstance(path, (type(None), list)):
-        # Backwards-compatibility
-        raise RuntimeError("'path' must be None or a list, "
-                           "not {}".format(type(path)))
-
-    if path is None:
-        if is_builtin(name):
-            return None, None, ('', '', C_BUILTIN)
-        elif is_frozen(name):
-            return None, None, ('', '', PY_FROZEN)
-        else:
-            path = sys.path
-
-    for entry in path:
-        package_directory = os.path.join(entry, name)
-        for suffix in ['.py', machinery.BYTECODE_SUFFIXES[0]]:
-            package_file_name = '__init__' + suffix
-            file_path = os.path.join(package_directory, package_file_name)
-            if os.path.isfile(file_path):
-                return None, package_directory, ('', '', PKG_DIRECTORY)
-        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)
-
-    encoding = None
-    if 'b' not in mode:
-        with open(file_path, 'rb') as file:
-            encoding = tokenize.detect_encoding(file.readline)[0]
-    file = open(file_path, mode, encoding=encoding)
-    return file, file_path, (suffix, mode, type_)
-
-
-def reload(module):
-    """**DEPRECATED**
-
-    Reload the module and return it.
-
-    The module must have been successfully imported before.
-
-    """
-    return importlib.reload(module)
-
-
-def init_builtin(name):
-    """**DEPRECATED**
-
-    Load and return a built-in module by name, or None is such module doesn't
-    exist
-    """
-    try:
-        return _builtin_from_name(name)
-    except ImportError:
-        return None
-
-
-if create_dynamic:
-    def load_dynamic(name, path, file=None):
-        """**DEPRECATED**
-
-        Load an extension module.
-        """
-        import importlib.machinery
-        loader = importlib.machinery.ExtensionFileLoader(name, path)
-
-        # Issue #24748: Skip the sys.modules check in _load_module_shim;
-        # always load new extension
-        spec = importlib.util.spec_from_file_location(
-            name, path, loader=loader)
-        return _load(spec)
-
-else:
-    load_dynamic = None
index 56731de64af494f6170a1446909c8625985d9224..fb977eaaa05767f97901e412815e6de9187d56ee 100644 (file)
@@ -14,7 +14,7 @@ import warnings
 __all__ = [
     'get_importer', 'iter_importers', 'get_loader', 'find_loader',
     'walk_packages', 'iter_modules', 'get_data',
-    'ImpImporter', 'ImpLoader', 'read_code', 'extend_path',
+    'read_code', 'extend_path',
     'ModuleInfo',
 ]
 
@@ -185,187 +185,6 @@ iter_importer_modules.register(
     importlib.machinery.FileFinder, _iter_file_finder_modules)
 
 
-def _import_imp():
-    global imp
-    with warnings.catch_warnings():
-        warnings.simplefilter('ignore', DeprecationWarning)
-        imp = importlib.import_module('imp')
-
-class ImpImporter:
-    """PEP 302 Finder that wraps Python's "classic" import algorithm
-
-    ImpImporter(dirname) produces a PEP 302 finder that searches that
-    directory.  ImpImporter(None) produces a PEP 302 finder that searches
-    the current sys.path, plus any modules that are frozen or built-in.
-
-    Note that ImpImporter does not currently support being used by placement
-    on sys.meta_path.
-    """
-
-    def __init__(self, path=None):
-        global imp
-        warnings.warn("This emulation is deprecated and slated for removal "
-                      "in Python 3.12; use 'importlib' instead",
-             DeprecationWarning)
-        _import_imp()
-        self.path = path
-
-    def find_module(self, fullname, path=None):
-        # Note: we ignore 'path' argument since it is only used via meta_path
-        subname = fullname.split(".")[-1]
-        if subname != fullname and self.path is None:
-            return None
-        if self.path is None:
-            path = None
-        else:
-            path = [os.path.realpath(self.path)]
-        try:
-            file, filename, etc = imp.find_module(subname, path)
-        except ImportError:
-            return None
-        return ImpLoader(fullname, file, filename, etc)
-
-    def iter_modules(self, prefix=''):
-        if self.path is None or not os.path.isdir(self.path):
-            return
-
-        yielded = {}
-        import inspect
-        try:
-            filenames = os.listdir(self.path)
-        except OSError:
-            # ignore unreadable directories like import does
-            filenames = []
-        filenames.sort()  # handle packages before same-named modules
-
-        for fn in filenames:
-            modname = inspect.getmodulename(fn)
-            if modname=='__init__' or modname in yielded:
-                continue
-
-            path = os.path.join(self.path, fn)
-            ispkg = False
-
-            if not modname and os.path.isdir(path) and '.' not in fn:
-                modname = fn
-                try:
-                    dircontents = os.listdir(path)
-                except OSError:
-                    # ignore unreadable directories like import does
-                    dircontents = []
-                for fn in dircontents:
-                    subname = inspect.getmodulename(fn)
-                    if subname=='__init__':
-                        ispkg = True
-                        break
-                else:
-                    continue    # not a package
-
-            if modname and '.' not in modname:
-                yielded[modname] = 1
-                yield prefix + modname, ispkg
-
-
-class ImpLoader:
-    """PEP 302 Loader that wraps Python's "classic" import algorithm
-    """
-    code = source = None
-
-    def __init__(self, fullname, file, filename, etc):
-        warnings.warn("This emulation is deprecated and slated for removal in "
-                      "Python 3.12; use 'importlib' instead",
-                      DeprecationWarning)
-        _import_imp()
-        self.file = file
-        self.filename = filename
-        self.fullname = fullname
-        self.etc = etc
-
-    def load_module(self, fullname):
-        self._reopen()
-        try:
-            mod = imp.load_module(fullname, self.file, self.filename, self.etc)
-        finally:
-            if self.file:
-                self.file.close()
-        # Note: we don't set __loader__ because we want the module to look
-        # normal; i.e. this is just a wrapper for standard import machinery
-        return mod
-
-    def get_data(self, pathname):
-        with open(pathname, "rb") as file:
-            return file.read()
-
-    def _reopen(self):
-        if self.file and self.file.closed:
-            mod_type = self.etc[2]
-            if mod_type==imp.PY_SOURCE:
-                self.file = open(self.filename, 'r')
-            elif mod_type in (imp.PY_COMPILED, imp.C_EXTENSION):
-                self.file = open(self.filename, 'rb')
-
-    def _fix_name(self, fullname):
-        if fullname is None:
-            fullname = self.fullname
-        elif fullname != self.fullname:
-            raise ImportError("Loader for module %s cannot handle "
-                              "module %s" % (self.fullname, fullname))
-        return fullname
-
-    def is_package(self, fullname):
-        fullname = self._fix_name(fullname)
-        return self.etc[2]==imp.PKG_DIRECTORY
-
-    def get_code(self, fullname=None):
-        fullname = self._fix_name(fullname)
-        if self.code is None:
-            mod_type = self.etc[2]
-            if mod_type==imp.PY_SOURCE:
-                source = self.get_source(fullname)
-                self.code = compile(source, self.filename, 'exec')
-            elif mod_type==imp.PY_COMPILED:
-                self._reopen()
-                try:
-                    self.code = read_code(self.file)
-                finally:
-                    self.file.close()
-            elif mod_type==imp.PKG_DIRECTORY:
-                self.code = self._get_delegate().get_code()
-        return self.code
-
-    def get_source(self, fullname=None):
-        fullname = self._fix_name(fullname)
-        if self.source is None:
-            mod_type = self.etc[2]
-            if mod_type==imp.PY_SOURCE:
-                self._reopen()
-                try:
-                    self.source = self.file.read()
-                finally:
-                    self.file.close()
-            elif mod_type==imp.PY_COMPILED:
-                if os.path.exists(self.filename[:-1]):
-                    with open(self.filename[:-1], 'r') as f:
-                        self.source = f.read()
-            elif mod_type==imp.PKG_DIRECTORY:
-                self.source = self._get_delegate().get_source()
-        return self.source
-
-    def _get_delegate(self):
-        finder = ImpImporter(self.filename)
-        spec = _get_spec(finder, '__init__')
-        return spec.loader
-
-    def get_filename(self, fullname=None):
-        fullname = self._fix_name(fullname)
-        mod_type = self.etc[2]
-        if mod_type==imp.PKG_DIRECTORY:
-            return self._get_delegate().get_filename()
-        elif mod_type in (imp.PY_SOURCE, imp.PY_COMPILED, imp.C_EXTENSION):
-            return self.filename
-        return None
-
-
 try:
     import zipimport
     from zipimport import zipimporter
index 78d8fd5357f72aaa6f1a9bc8134cb1e84b08a379..1c3443fa8469f7bf2a1b0d0263e4a972edf8d339 100755 (executable)
@@ -512,7 +512,7 @@ class Doc:
 
         basedir = os.path.normcase(basedir)
         if (isinstance(object, type(os)) and
-            (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
+            (object.__name__ in ('errno', 'exceptions', 'gc',
                                  'marshal', 'posix', 'signal', 'sys',
                                  '_thread', 'zipimport') or
              (file.startswith(basedir) and
index 54fc136d4074f203b4eaccbb0a601009b90489b3..42f896c9cd509406726390e82fc42e4958b9bf5c 100644 (file)
@@ -279,12 +279,7 @@ def run_path(path_name, init_globals=None, run_name=None):
     pkg_name = run_name.rpartition(".")[0]
     from pkgutil import get_importer
     importer = get_importer(path_name)
-    # 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:
+    if isinstance(importer, type(None)):
         # Not a valid sys.path entry, so run the code directly
         # execfile() doesn't help as we want to allow compiled files
         code, fname = _get_code_from_file(run_name, path_name)
diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py
deleted file mode 100644 (file)
index 80abc72..0000000
+++ /dev/null
@@ -1,524 +0,0 @@
-import gc
-import importlib
-import importlib.util
-import os
-import os.path
-import py_compile
-import sys
-from test import support
-from test.support import import_helper
-from test.support import os_helper
-from test.support import script_helper
-from test.support import warnings_helper
-import unittest
-import warnings
-imp = warnings_helper.import_deprecated('imp')
-import _imp
-
-
-OS_PATH_NAME = os.path.__name__
-
-
-def requires_load_dynamic(meth):
-    """Decorator to skip a test if not running under CPython or lacking
-    imp.load_dynamic()."""
-    meth = support.cpython_only(meth)
-    return unittest.skipIf(getattr(imp, 'load_dynamic', None) is None,
-                           'imp.load_dynamic() required')(meth)
-
-
-class LockTests(unittest.TestCase):
-
-    """Very basic test of import lock functions."""
-
-    def verify_lock_state(self, expected):
-        self.assertEqual(imp.lock_held(), expected,
-                             "expected imp.lock_held() to be %r" % expected)
-    def testLock(self):
-        LOOPS = 50
-
-        # The import lock may already be held, e.g. if the test suite is run
-        # via "import test.autotest".
-        lock_held_at_start = imp.lock_held()
-        self.verify_lock_state(lock_held_at_start)
-
-        for i in range(LOOPS):
-            imp.acquire_lock()
-            self.verify_lock_state(True)
-
-        for i in range(LOOPS):
-            imp.release_lock()
-
-        # The original state should be restored now.
-        self.verify_lock_state(lock_held_at_start)
-
-        if not lock_held_at_start:
-            try:
-                imp.release_lock()
-            except RuntimeError:
-                pass
-            else:
-                self.fail("release_lock() without lock should raise "
-                            "RuntimeError")
-
-class ImportTests(unittest.TestCase):
-    def setUp(self):
-        mod = importlib.import_module('test.encoded_modules')
-        self.test_strings = mod.test_strings
-        self.test_path = mod.__path__
-
-    # test_import_encoded_module moved to test_source_encoding.py
-
-    def test_find_module_encoding(self):
-        for mod, encoding, _ in self.test_strings:
-            with imp.find_module('module_' + mod, self.test_path)[0] as fd:
-                self.assertEqual(fd.encoding, encoding)
-
-        path = [os.path.dirname(__file__)]
-        with self.assertRaises(SyntaxError):
-            imp.find_module('badsyntax_pep3120', path)
-
-    def test_issue1267(self):
-        for mod, encoding, _ in self.test_strings:
-            fp, filename, info  = imp.find_module('module_' + mod,
-                                                  self.test_path)
-            with fp:
-                self.assertNotEqual(fp, None)
-                self.assertEqual(fp.encoding, encoding)
-                self.assertEqual(fp.tell(), 0)
-                self.assertEqual(fp.readline(), '# test %s encoding\n'
-                                 % encoding)
-
-        fp, filename, info = imp.find_module("tokenize")
-        with fp:
-            self.assertNotEqual(fp, None)
-            self.assertEqual(fp.encoding, "utf-8")
-            self.assertEqual(fp.tell(), 0)
-            self.assertEqual(fp.readline(),
-                             '"""Tokenization help for Python programs.\n')
-
-    def test_issue3594(self):
-        temp_mod_name = 'test_imp_helper'
-        sys.path.insert(0, '.')
-        try:
-            with open(temp_mod_name + '.py', 'w', encoding="latin-1") as file:
-                file.write("# coding: cp1252\nu = 'test.test_imp'\n")
-            file, filename, info = imp.find_module(temp_mod_name)
-            file.close()
-            self.assertEqual(file.encoding, 'cp1252')
-        finally:
-            del sys.path[0]
-            os_helper.unlink(temp_mod_name + '.py')
-            os_helper.unlink(temp_mod_name + '.pyc')
-
-    def test_issue5604(self):
-        # Test cannot cover imp.load_compiled function.
-        # Martin von Loewis note what shared library cannot have non-ascii
-        # character because init_xxx function cannot be compiled
-        # and issue never happens for dynamic modules.
-        # But sources modified to follow generic way for processing paths.
-
-        # the return encoding could be uppercase or None
-        fs_encoding = sys.getfilesystemencoding()
-
-        # covers utf-8 and Windows ANSI code pages
-        # one non-space symbol from every page
-        # (http://en.wikipedia.org/wiki/Code_page)
-        known_locales = {
-            'utf-8' : b'\xc3\xa4',
-            'cp1250' : b'\x8C',
-            'cp1251' : b'\xc0',
-            'cp1252' : b'\xc0',
-            'cp1253' : b'\xc1',
-            'cp1254' : b'\xc0',
-            'cp1255' : b'\xe0',
-            'cp1256' : b'\xe0',
-            'cp1257' : b'\xc0',
-            'cp1258' : b'\xc0',
-            }
-
-        if sys.platform == 'darwin':
-            self.assertEqual(fs_encoding, 'utf-8')
-            # Mac OS X uses the Normal Form D decomposition
-            # http://developer.apple.com/mac/library/qa/qa2001/qa1173.html
-            special_char = b'a\xcc\x88'
-        else:
-            special_char = known_locales.get(fs_encoding)
-
-        if not special_char:
-            self.skipTest("can't run this test with %s as filesystem encoding"
-                          % fs_encoding)
-        decoded_char = special_char.decode(fs_encoding)
-        temp_mod_name = 'test_imp_helper_' + decoded_char
-        test_package_name = 'test_imp_helper_package_' + decoded_char
-        init_file_name = os.path.join(test_package_name, '__init__.py')
-        try:
-            # if the curdir is not in sys.path the test fails when run with
-            # ./python ./Lib/test/regrtest.py test_imp
-            sys.path.insert(0, os.curdir)
-            with open(temp_mod_name + '.py', 'w', encoding="utf-8") as file:
-                file.write('a = 1\n')
-            file, filename, info = imp.find_module(temp_mod_name)
-            with file:
-                self.assertIsNotNone(file)
-                self.assertTrue(filename[:-3].endswith(temp_mod_name))
-                self.assertEqual(info[0], '.py')
-                self.assertEqual(info[1], 'r')
-                self.assertEqual(info[2], imp.PY_SOURCE)
-
-                mod = imp.load_module(temp_mod_name, file, filename, info)
-                self.assertEqual(mod.a, 1)
-
-            with warnings.catch_warnings():
-                warnings.simplefilter('ignore')
-                mod = imp.load_source(temp_mod_name, temp_mod_name + '.py')
-            self.assertEqual(mod.a, 1)
-
-            with warnings.catch_warnings():
-                warnings.simplefilter('ignore')
-                if not sys.dont_write_bytecode:
-                    mod = imp.load_compiled(
-                        temp_mod_name,
-                        imp.cache_from_source(temp_mod_name + '.py'))
-            self.assertEqual(mod.a, 1)
-
-            if not os.path.exists(test_package_name):
-                os.mkdir(test_package_name)
-            with open(init_file_name, 'w', encoding="utf-8") as file:
-                file.write('b = 2\n')
-            with warnings.catch_warnings():
-                warnings.simplefilter('ignore')
-                package = imp.load_package(test_package_name, test_package_name)
-            self.assertEqual(package.b, 2)
-        finally:
-            del sys.path[0]
-            for ext in ('.py', '.pyc'):
-                os_helper.unlink(temp_mod_name + ext)
-                os_helper.unlink(init_file_name + ext)
-            os_helper.rmtree(test_package_name)
-            os_helper.rmtree('__pycache__')
-
-    def test_issue9319(self):
-        path = os.path.dirname(__file__)
-        self.assertRaises(SyntaxError,
-                          imp.find_module, "badsyntax_pep3120", [path])
-
-    def test_load_from_source(self):
-        # Verify that the imp module can correctly load and find .py files
-        # XXX (ncoghlan): It would be nice to use import_helper.CleanImport
-        # here, but that breaks because the os module registers some
-        # handlers in copy_reg on import. Since CleanImport doesn't
-        # revert that registration, the module is left in a broken
-        # state after reversion. Reinitialising the module contents
-        # and just reverting os.environ to its previous state is an OK
-        # workaround
-        with import_helper.CleanImport('os', 'os.path', OS_PATH_NAME):
-            import os
-            orig_path = os.path
-            orig_getenv = os.getenv
-            with os_helper.EnvironmentVarGuard():
-                x = imp.find_module("os")
-                self.addCleanup(x[0].close)
-                new_os = imp.load_module("os", *x)
-                self.assertIs(os, new_os)
-                self.assertIs(orig_path, new_os.path)
-                self.assertIsNot(orig_getenv, new_os.getenv)
-
-    @requires_load_dynamic
-    def test_issue15828_load_extensions(self):
-        # Issue 15828 picked up that the adapter between the old imp API
-        # and importlib couldn't handle C extensions
-        example = "_heapq"
-        x = imp.find_module(example)
-        file_ = x[0]
-        if file_ is not None:
-            self.addCleanup(file_.close)
-        mod = imp.load_module(example, *x)
-        self.assertEqual(mod.__name__, example)
-
-    @requires_load_dynamic
-    def test_issue16421_multiple_modules_in_one_dll(self):
-        # Issue 16421: loading several modules from the same compiled file fails
-        m = '_testimportmultiple'
-        fileobj, pathname, description = imp.find_module(m)
-        fileobj.close()
-        mod0 = imp.load_dynamic(m, pathname)
-        mod1 = imp.load_dynamic('_testimportmultiple_foo', pathname)
-        mod2 = imp.load_dynamic('_testimportmultiple_bar', pathname)
-        self.assertEqual(mod0.__name__, m)
-        self.assertEqual(mod1.__name__, '_testimportmultiple_foo')
-        self.assertEqual(mod2.__name__, '_testimportmultiple_bar')
-        with self.assertRaises(ImportError):
-            imp.load_dynamic('nonexistent', pathname)
-
-    @requires_load_dynamic
-    def test_load_dynamic_ImportError_path(self):
-        # Issue #1559549 added `name` and `path` attributes to ImportError
-        # in order to provide better detail. Issue #10854 implemented those
-        # attributes on import failures of extensions on Windows.
-        path = 'bogus file path'
-        name = 'extension'
-        with self.assertRaises(ImportError) as err:
-            imp.load_dynamic(name, path)
-        self.assertIn(path, err.exception.path)
-        self.assertEqual(name, err.exception.name)
-
-    @requires_load_dynamic
-    def test_load_module_extension_file_is_None(self):
-        # When loading an extension module and the file is None, open one
-        # on the behalf of imp.load_dynamic().
-        # Issue #15902
-        name = '_testimportmultiple'
-        found = imp.find_module(name)
-        if found[0] is not None:
-            found[0].close()
-        if found[2][2] != imp.C_EXTENSION:
-            self.skipTest("found module doesn't appear to be a C extension")
-        imp.load_module(name, None, *found[1:])
-
-    @requires_load_dynamic
-    def test_issue24748_load_module_skips_sys_modules_check(self):
-        name = 'test.imp_dummy'
-        try:
-            del sys.modules[name]
-        except KeyError:
-            pass
-        try:
-            module = importlib.import_module(name)
-            spec = importlib.util.find_spec('_testmultiphase')
-            module = imp.load_dynamic(name, spec.origin)
-            self.assertEqual(module.__name__, name)
-            self.assertEqual(module.__spec__.name, name)
-            self.assertEqual(module.__spec__.origin, spec.origin)
-            self.assertRaises(AttributeError, getattr, module, 'dummy_name')
-            self.assertEqual(module.int_const, 1969)
-            self.assertIs(sys.modules[name], module)
-        finally:
-            try:
-                del sys.modules[name]
-            except KeyError:
-                pass
-
-    @unittest.skipIf(sys.dont_write_bytecode,
-        "test meaningful only when writing bytecode")
-    def test_bug7732(self):
-        with os_helper.temp_cwd():
-            source = os_helper.TESTFN + '.py'
-            os.mkdir(source)
-            self.assertRaisesRegex(ImportError, '^No module',
-                imp.find_module, os_helper.TESTFN, ["."])
-
-    def test_multiple_calls_to_get_data(self):
-        # Issue #18755: make sure multiple calls to get_data() can succeed.
-        loader = imp._LoadSourceCompatibility('imp', imp.__file__,
-                                              open(imp.__file__, encoding="utf-8"))
-        loader.get_data(imp.__file__)  # File should be closed
-        loader.get_data(imp.__file__)  # Will need to create a newly opened file
-
-    def test_load_source(self):
-        # Create a temporary module since load_source(name) modifies
-        # sys.modules[name] attributes like __loader___
-        modname = f"tmp{__name__}"
-        mod = type(sys.modules[__name__])(modname)
-        with support.swap_item(sys.modules, modname, mod):
-            with self.assertRaisesRegex(ValueError, 'embedded null'):
-                imp.load_source(modname, __file__ + "\0")
-
-    @support.cpython_only
-    def test_issue31315(self):
-        # There shouldn't be an assertion failure in imp.create_dynamic(),
-        # when spec.name is not a string.
-        create_dynamic = support.get_attribute(imp, 'create_dynamic')
-        class BadSpec:
-            name = None
-            origin = 'foo'
-        with self.assertRaises(TypeError):
-            create_dynamic(BadSpec())
-
-    def test_issue_35321(self):
-        # Both _frozen_importlib and _frozen_importlib_external
-        # should have a spec origin of "frozen" and
-        # no need to clean up imports in this case.
-
-        import _frozen_importlib_external
-        self.assertEqual(_frozen_importlib_external.__spec__.origin, "frozen")
-
-        import _frozen_importlib
-        self.assertEqual(_frozen_importlib.__spec__.origin, "frozen")
-
-    def test_source_hash(self):
-        self.assertEqual(_imp.source_hash(42, b'hi'), b'\xfb\xd9G\x05\xaf$\x9b~')
-        self.assertEqual(_imp.source_hash(43, b'hi'), b'\xd0/\x87C\xccC\xff\xe2')
-
-    def test_pyc_invalidation_mode_from_cmdline(self):
-        cases = [
-            ([], "default"),
-            (["--check-hash-based-pycs", "default"], "default"),
-            (["--check-hash-based-pycs", "always"], "always"),
-            (["--check-hash-based-pycs", "never"], "never"),
-        ]
-        for interp_args, expected in cases:
-            args = interp_args + [
-                "-c",
-                "import _imp; print(_imp.check_hash_based_pycs)",
-            ]
-            res = script_helper.assert_python_ok(*args)
-            self.assertEqual(res.out.strip().decode('utf-8'), expected)
-
-    def test_find_and_load_checked_pyc(self):
-        # issue 34056
-        with os_helper.temp_cwd():
-            with open('mymod.py', 'wb') as fp:
-                fp.write(b'x = 42\n')
-            py_compile.compile(
-                'mymod.py',
-                doraise=True,
-                invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH,
-            )
-            file, path, description = imp.find_module('mymod', path=['.'])
-            mod = imp.load_module('mymod', file, path, description)
-        self.assertEqual(mod.x, 42)
-
-    def test_issue98354(self):
-        # _imp.create_builtin should raise TypeError
-        # if 'name' attribute of 'spec' argument is not a 'str' instance
-
-        create_builtin = support.get_attribute(_imp, "create_builtin")
-
-        class FakeSpec:
-            def __init__(self, name):
-                self.name = self
-        spec = FakeSpec("time")
-        with self.assertRaises(TypeError):
-            create_builtin(spec)
-
-        class FakeSpec2:
-            name = [1, 2, 3, 4]
-        spec = FakeSpec2()
-        with self.assertRaises(TypeError):
-            create_builtin(spec)
-
-        import builtins
-        class UnicodeSubclass(str):
-            pass
-        class GoodSpec:
-            name = UnicodeSubclass("builtins")
-        spec = GoodSpec()
-        bltin = create_builtin(spec)
-        self.assertEqual(bltin, builtins)
-
-        class UnicodeSubclassFakeSpec(str):
-            def __init__(self, name):
-                self.name = self
-        spec = UnicodeSubclassFakeSpec("builtins")
-        bltin = create_builtin(spec)
-        self.assertEqual(bltin, builtins)
-
-    @support.cpython_only
-    def test_create_builtin_subinterp(self):
-        # gh-99578: create_builtin() behavior changes after the creation of the
-        # first sub-interpreter. Test both code paths, before and after the
-        # creation of a sub-interpreter. Previously, create_builtin() had
-        # a reference leak after the creation of the first sub-interpreter.
-
-        import builtins
-        create_builtin = support.get_attribute(_imp, "create_builtin")
-        class Spec:
-            name = "builtins"
-        spec = Spec()
-
-        def check_get_builtins():
-            refcnt = sys.getrefcount(builtins)
-            mod = _imp.create_builtin(spec)
-            self.assertIs(mod, builtins)
-            self.assertEqual(sys.getrefcount(builtins), refcnt + 1)
-            # Check that a GC collection doesn't crash
-            gc.collect()
-
-        check_get_builtins()
-
-        ret = support.run_in_subinterp("import builtins")
-        self.assertEqual(ret, 0)
-
-        check_get_builtins()
-
-
-class ReloadTests(unittest.TestCase):
-
-    """Very basic tests to make sure that imp.reload() operates just like
-    reload()."""
-
-    def test_source(self):
-        # XXX (ncoghlan): It would be nice to use test.import_helper.CleanImport
-        # here, but that breaks because the os module registers some
-        # handlers in copy_reg on import. Since CleanImport doesn't
-        # revert that registration, the module is left in a broken
-        # state after reversion. Reinitialising the module contents
-        # and just reverting os.environ to its previous state is an OK
-        # workaround
-        with os_helper.EnvironmentVarGuard():
-            import os
-            imp.reload(os)
-
-    def test_extension(self):
-        with import_helper.CleanImport('time'):
-            import time
-            imp.reload(time)
-
-    def test_builtin(self):
-        with import_helper.CleanImport('marshal'):
-            import marshal
-            imp.reload(marshal)
-
-    def test_with_deleted_parent(self):
-        # see #18681
-        from html import parser
-        html = sys.modules.pop('html')
-        def cleanup():
-            sys.modules['html'] = html
-        self.addCleanup(cleanup)
-        with self.assertRaisesRegex(ImportError, 'html'):
-            imp.reload(parser)
-
-
-class PEP3147Tests(unittest.TestCase):
-    """Tests of PEP 3147."""
-
-    tag = imp.get_tag()
-
-    @unittest.skipUnless(sys.implementation.cache_tag is not None,
-                         'requires sys.implementation.cache_tag not be None')
-    def test_cache_from_source(self):
-        # Given the path to a .py file, return the path to its PEP 3147
-        # defined .pyc file (i.e. under __pycache__).
-        path = os.path.join('foo', 'bar', 'baz', 'qux.py')
-        expect = os.path.join('foo', 'bar', 'baz', '__pycache__',
-                              'qux.{}.pyc'.format(self.tag))
-        self.assertEqual(imp.cache_from_source(path, True), expect)
-
-    @unittest.skipUnless(sys.implementation.cache_tag is not None,
-                         'requires sys.implementation.cache_tag to not be '
-                         'None')
-    def test_source_from_cache(self):
-        # Given the path to a PEP 3147 defined .pyc file, return the path to
-        # its source.  This tests the good path.
-        path = os.path.join('foo', 'bar', 'baz', '__pycache__',
-                            'qux.{}.pyc'.format(self.tag))
-        expect = os.path.join('foo', 'bar', 'baz', 'qux.py')
-        self.assertEqual(imp.source_from_cache(path), expect)
-
-
-class NullImporterTests(unittest.TestCase):
-    @unittest.skipIf(os_helper.TESTFN_UNENCODABLE is None,
-                     "Need an undecodeable filename")
-    def test_unencodeable(self):
-        name = os_helper.TESTFN_UNENCODABLE
-        os.mkdir(name)
-        try:
-            self.assertRaises(ImportError, imp.NullImporter, name)
-        finally:
-            os.rmdir(name)
-
-
-if __name__ == "__main__":
-    unittest.main()
index 9032fd18d3f95bcf4d62ef24e5b6763654ef0fdb..e348733f6ce3c364bdb68266da83f74029284c79 100644 (file)
@@ -131,9 +131,8 @@ def uncache(*names):
 
     """
     for name in names:
-        if name in ('sys', 'marshal', 'imp'):
-            raise ValueError(
-                "cannot uncache {0}".format(name))
+        if name in ('sys', 'marshal'):
+            raise ValueError("cannot uncache {}".format(name))
         try:
             del sys.modules[name]
         except KeyError:
index 0cc99e0cc2276345212d6f1547e77b9dce268177..4d9f5db3c6b3cf393ce5b89565cfc0ef9efab4f0 100644 (file)
@@ -541,14 +541,6 @@ class ImportlibMigrationTests(unittest.TestCase):
              "Python 3.12; use 'importlib' instead",
              DeprecationWarning))
 
-    def test_importer_deprecated(self):
-        with self.check_deprecated():
-            pkgutil.ImpImporter("")
-
-    def test_loader_deprecated(self):
-        with self.check_deprecated():
-            pkgutil.ImpLoader("", "", "", "")
-
     def test_get_loader_avoids_emulation(self):
         with check_warnings() as w:
             self.assertIsNotNone(pkgutil.get_loader("sys"))
diff --git a/Misc/NEWS.d/next/Library/2022-10-21-17-20-57.gh-issue-98040.3btbmA.rst b/Misc/NEWS.d/next/Library/2022-10-21-17-20-57.gh-issue-98040.3btbmA.rst
new file mode 100644 (file)
index 0000000..f67bffc
--- /dev/null
@@ -0,0 +1 @@
+Remove the long-deprecated ``imp`` module.
index e34854f70257985bf558b8ef9c9daac8afb2d632..cf8990a2df0a9b26e5003a18426dd898f97f76f8 100644 (file)
@@ -884,15 +884,3 @@ PyInit__test_module_state_shared(void)
     }
     return module;
 }
-
-
-/*** Helper for imp test ***/
-
-static PyModuleDef imp_dummy_def = TEST_MODULE_DEF("imp_dummy", main_slots, testexport_methods);
-
-PyMODINIT_FUNC
-PyInit_imp_dummy(void)
-{
-    return PyModuleDef_Init(&imp_dummy_def);
-}
-
index daec64ea4adaadc81eab254c1d625811d6065e91..0bf107b28d3990a17259891ecc5fa51abd6c37e4 100644 (file)
@@ -594,11 +594,11 @@ _PyImport_ClearModulesByIndex(PyInterpreterState *interp)
 /*
     It may help to have a big picture view of what happens
     when an extension is loaded.  This includes when it is imported
-    for the first time or via imp.load_dynamic().
+    for the first time.
 
-    Here's a summary, using imp.load_dynamic() as the starting point:
+    Here's a summary, using importlib._boostrap._load() as a starting point.
 
-    1.  imp.load_dynamic() -> importlib._bootstrap._load()
+    1.  importlib._bootstrap._load()
     2.    _load():  acquire import lock
     3.    _load() -> importlib._bootstrap._load_unlocked()
     4.      _load_unlocked() -> importlib._bootstrap.module_from_spec()
@@ -3794,7 +3794,7 @@ _imp_source_hash_impl(PyObject *module, long key, Py_buffer *source)
 
 
 PyDoc_STRVAR(doc_imp,
-"(Extremely) low-level import machinery bits as used by importlib and imp.");
+"(Extremely) low-level import machinery bits as used by importlib.");
 
 static PyMethodDef imp_methods[] = {
     _IMP_EXTENSION_SUFFIXES_METHODDEF
index 5aa31803397ce402c72a190dec862ee7cc745e6f..2b402ae0b6a031d40ae395737c89a4923a91f006 100755 (executable)
@@ -7,24 +7,18 @@ import os
 import sys
 
 
-try:
-    from importlib.machinery import SourceFileLoader
-except ImportError:
-    import imp
-
-    def find_module(modname):
-        """Finds and returns a module in the local dist/checkout.
-        """
-        modpath = os.path.join(
-            os.path.dirname(os.path.dirname(__file__)), "Lib")
-        return imp.load_module(modname, *imp.find_module(modname, [modpath]))
-else:
-    def find_module(modname):
-        """Finds and returns a module in the local dist/checkout.
-        """
-        modpath = os.path.join(
-            os.path.dirname(os.path.dirname(__file__)), "Lib", modname + ".py")
-        return SourceFileLoader(modname, modpath).load_module()
+# 2023-04-27(warsaw): Pre-Python 3.12, this would catch ImportErrors and try to
+# import imp, and then use imp.load_module().  The imp module was removed in
+# Python 3.12 (and long deprecated before that), and it's unclear under what
+# conditions this import will now fail, so the fallback was simply removed.
+from importlib.machinery import SourceFileLoader
+
+def find_module(modname):
+    """Finds and returns a module in the local dist/checkout.
+    """
+    modpath = os.path.join(
+        os.path.dirname(os.path.dirname(__file__)), "Lib", modname + ".py")
+    return SourceFileLoader(modname, modpath).load_module()
 
 
 def write_contents(f):
index d525fb1075c4664ae6b96df0c90310d0be7bfe60..ba248d208e425a401661d55bc17eb0ef8832f908 100644 (file)
@@ -2173,10 +2173,9 @@ add_main_module(PyInterpreterState *interp)
         Py_DECREF(bimod);
     }
 
-    /* Main is a little special - imp.is_builtin("__main__") will return
-     * False, but BuiltinImporter is still the most appropriate initial
-     * setting for its __loader__ attribute. A more suitable value will
-     * be set if __main__ gets further initialized later in the startup
+    /* Main is a little special - BuiltinImporter is the most appropriate
+     * initial setting for its __loader__ attribute. A more suitable value
+     * will be set if __main__ gets further initialized later in the startup
      * process.
      */
     loader = _PyDict_GetItemStringWithError(d, "__loader__");
index e9f0061a59d3bafac41f5320a95814262e2e0598..27f42e5202e571cebb257c52e35aedf37c4c1e48 100644 (file)
@@ -164,7 +164,6 @@ static const char* _Py_stdlib_module_names[] = {
 "idlelib",
 "imaplib",
 "imghdr",
-"imp",
 "importlib",
 "inspect",
 "io",
index d15e5e2d5450d7c6fd509f5ed07c23f506258a0c..7e0e9602a107658bf6475181ff7fb8dcedf62669 100644 (file)
@@ -1,5 +1,5 @@
 # This script lists the names of standard library modules
-# to update Python/stdlib_mod_names.h
+# to update Python/stdlib_module_names.h
 import _imp
 import os.path
 import re
index 43760369b1980eb082885ed8f386e0da40765f02..27a535814ea52b5fe2a2753279d2150d9ba41b1b 100644 (file)
@@ -495,7 +495,6 @@ Python/import.c:PyImport_ImportModuleLevelObject():PyId___path__ _Py_IDENTIFIER(
 Python/import.c:PyImport_ImportModuleLevelObject():PyId___spec__ _Py_IDENTIFIER(__spec__)
 Python/import.c:PyImport_ImportModuleLevelObject():PyId__handle_fromlist _Py_IDENTIFIER(_handle_fromlist)
 Python/import.c:PyImport_ImportModuleLevelObject():PyId__lock_unlock_module _Py_IDENTIFIER(_lock_unlock_module)
-Python/import.c:PyImport_ReloadModule():PyId_imp                 _Py_IDENTIFIER(imp)
 Python/import.c:PyImport_ReloadModule():PyId_reload              _Py_IDENTIFIER(reload)
 Python/import.c:_PyImportZip_Init():PyId_zipimporter             _Py_IDENTIFIER(zipimporter)
 Python/import.c:import_find_and_load():PyId__find_and_load       _Py_IDENTIFIER(_find_and_load)
index 6c4a537ad86e6c0c5125055998be5fd69486fc83..619263b553c081519063b826ea500b9ac36d52a9 100644 (file)
@@ -6,7 +6,7 @@ thus has no external changes made to import-related attributes in sys.
 """
 from test.test_importlib import util
 import decimal
-import imp
+from importlib.util import cache_from_source
 import importlib
 import importlib.machinery
 import json
@@ -65,7 +65,7 @@ def source_wo_bytecode(seconds, repeat):
         name = '__importlib_test_benchmark__'
         # Clears out sys.modules and puts an entry at the front of sys.path.
         with util.create_modules(name) as mapping:
-            assert not os.path.exists(imp.cache_from_source(mapping[name]))
+            assert not os.path.exists(cache_from_source(mapping[name]))
             sys.meta_path.append(importlib.machinery.PathFinder)
             loader = (importlib.machinery.SourceFileLoader,
                       importlib.machinery.SOURCE_SUFFIXES)
@@ -80,7 +80,7 @@ def _wo_bytecode(module):
     name = module.__name__
     def benchmark_wo_bytecode(seconds, repeat):
         """Source w/o bytecode: {}"""
-        bytecode_path = imp.cache_from_source(module.__file__)
+        bytecode_path = cache_from_source(module.__file__)
         if os.path.exists(bytecode_path):
             os.unlink(bytecode_path)
         sys.dont_write_bytecode = True
@@ -108,9 +108,9 @@ def source_writing_bytecode(seconds, repeat):
         sys.path_hooks.append(importlib.machinery.FileFinder.path_hook(loader))
         def cleanup():
             sys.modules.pop(name)
-            os.unlink(imp.cache_from_source(mapping[name]))
+            os.unlink(cache_from_source(mapping[name]))
         for result in bench(name, cleanup, repeat=repeat, seconds=seconds):
-            assert not os.path.exists(imp.cache_from_source(mapping[name]))
+            assert not os.path.exists(cache_from_source(mapping[name]))
             yield result
 
 
@@ -121,7 +121,7 @@ def _writing_bytecode(module):
         assert not sys.dont_write_bytecode
         def cleanup():
             sys.modules.pop(name)
-            os.unlink(imp.cache_from_source(module.__file__))
+            os.unlink(cache_from_source(module.__file__))
         yield from bench(name, cleanup, repeat=repeat, seconds=seconds)
 
     writing_bytecode_benchmark.__doc__ = (
@@ -141,7 +141,7 @@ def source_using_bytecode(seconds, repeat):
                   importlib.machinery.SOURCE_SUFFIXES)
         sys.path_hooks.append(importlib.machinery.FileFinder.path_hook(loader))
         py_compile.compile(mapping[name])
-        assert os.path.exists(imp.cache_from_source(mapping[name]))
+        assert os.path.exists(cache_from_source(mapping[name]))
         yield from bench(name, lambda: sys.modules.pop(name), repeat=repeat,
                          seconds=seconds)