Skip to content

Commit b3a8ee6

Browse files
committed
pythongh-97850: Remove deprecated functions from importlib.utils
1 parent b44372e commit b3a8ee6

File tree

6 files changed

+5
-373
lines changed

6 files changed

+5
-373
lines changed

Doc/library/importlib.rst

+1-53
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ ABC hierarchy::
443443
from the import. If the loader inserted a module and the load fails, it
444444
must be removed by the loader from :data:`sys.modules`; modules already
445445
in :data:`sys.modules` before the loader began execution should be left
446-
alone (see :func:`importlib.util.module_for_loader`).
446+
alone.
447447

448448
The loader should set several attributes on the module
449449
(note that some of these attributes can change when a module is
@@ -1326,58 +1326,6 @@ an :term:`importer`.
13261326

13271327
.. versionadded:: 3.5
13281328

1329-
.. decorator:: module_for_loader
1330-
1331-
A :term:`decorator` for :meth:`importlib.abc.Loader.load_module`
1332-
to handle selecting the proper
1333-
module object to load with. The decorated method is expected to have a call
1334-
signature taking two positional arguments
1335-
(e.g. ``load_module(self, module)``) for which the second argument
1336-
will be the module **object** to be used by the loader.
1337-
Note that the decorator will not work on static methods because of the
1338-
assumption of two arguments.
1339-
1340-
The decorated method will take in the **name** of the module to be loaded
1341-
as expected for a :term:`loader`. If the module is not found in
1342-
:data:`sys.modules` then a new one is constructed. Regardless of where the
1343-
module came from, :attr:`__loader__` set to **self** and :attr:`__package__`
1344-
is set based on what :meth:`importlib.abc.InspectLoader.is_package` returns
1345-
(if available). These attributes are set unconditionally to support
1346-
reloading.
1347-
1348-
If an exception is raised by the decorated method and a module was added to
1349-
:data:`sys.modules`, then the module will be removed to prevent a partially
1350-
initialized module from being in left in :data:`sys.modules`. If the module
1351-
was already in :data:`sys.modules` then it is left alone.
1352-
1353-
.. versionchanged:: 3.3
1354-
:attr:`__loader__` and :attr:`__package__` are automatically set
1355-
(when possible).
1356-
1357-
.. versionchanged:: 3.4
1358-
Set :attr:`__name__`, :attr:`__loader__` :attr:`__package__`
1359-
unconditionally to support reloading.
1360-
1361-
.. deprecated:: 3.4
1362-
The import machinery now directly performs all the functionality
1363-
provided by this function.
1364-
1365-
.. decorator:: set_loader
1366-
1367-
A :term:`decorator` for :meth:`importlib.abc.Loader.load_module`
1368-
to set the :attr:`__loader__`
1369-
attribute on the returned module. If the attribute is already set the
1370-
decorator does nothing. It is assumed that the first positional argument to
1371-
the wrapped method (i.e. ``self``) is what :attr:`__loader__` should be set
1372-
to.
1373-
1374-
.. versionchanged:: 3.4
1375-
Set ``__loader__`` if set to ``None``, as if the attribute does not
1376-
exist.
1377-
1378-
.. deprecated:: 3.4
1379-
The import machinery takes care of this automatically.
1380-
13811329
.. function:: spec_from_loader(name, loader, *, origin=None, is_package=None)
13821330

13831331
A factory function for creating a :class:`~importlib.machinery.ModuleSpec`

Lib/importlib/util.py

-87
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,9 @@
1111
from ._bootstrap_external import source_from_cache
1212
from ._bootstrap_external import spec_from_file_location
1313

14-
from contextlib import contextmanager
1514
import _imp
16-
import functools
1715
import sys
1816
import types
19-
import warnings
2017

2118

2219
def source_hash(source_bytes):
@@ -115,90 +112,6 @@ def find_spec(name, package=None):
115112
return spec
116113

117114

118-
@contextmanager
119-
def _module_to_load(name):
120-
is_reload = name in sys.modules
121-
122-
module = sys.modules.get(name)
123-
if not is_reload:
124-
# This must be done before open() is called as the 'io' module
125-
# implicitly imports 'locale' and would otherwise trigger an
126-
# infinite loop.
127-
module = type(sys)(name)
128-
# This must be done before putting the module in sys.modules
129-
# (otherwise an optimization shortcut in import.c becomes wrong)
130-
module.__initializing__ = True
131-
sys.modules[name] = module
132-
try:
133-
yield module
134-
except Exception:
135-
if not is_reload:
136-
try:
137-
del sys.modules[name]
138-
except KeyError:
139-
pass
140-
finally:
141-
module.__initializing__ = False
142-
143-
144-
def set_loader(fxn):
145-
"""Set __loader__ on the returned module.
146-
147-
This function is deprecated.
148-
149-
"""
150-
@functools.wraps(fxn)
151-
def set_loader_wrapper(self, *args, **kwargs):
152-
warnings.warn('The import system now takes care of this automatically; '
153-
'this decorator is slated for removal in Python 3.12',
154-
DeprecationWarning, stacklevel=2)
155-
module = fxn(self, *args, **kwargs)
156-
if getattr(module, '__loader__', None) is None:
157-
module.__loader__ = self
158-
return module
159-
return set_loader_wrapper
160-
161-
162-
def module_for_loader(fxn):
163-
"""Decorator to handle selecting the proper module for loaders.
164-
165-
The decorated function is passed the module to use instead of the module
166-
name. The module passed in to the function is either from sys.modules if
167-
it already exists or is a new module. If the module is new, then __name__
168-
is set the first argument to the method, __loader__ is set to self, and
169-
__package__ is set accordingly (if self.is_package() is defined) will be set
170-
before it is passed to the decorated function (if self.is_package() does
171-
not work for the module it will be set post-load).
172-
173-
If an exception is raised and the decorator created the module it is
174-
subsequently removed from sys.modules.
175-
176-
The decorator assumes that the decorated function takes the module name as
177-
the second argument.
178-
179-
"""
180-
warnings.warn('The import system now takes care of this automatically; '
181-
'this decorator is slated for removal in Python 3.12',
182-
DeprecationWarning, stacklevel=2)
183-
@functools.wraps(fxn)
184-
def module_for_loader_wrapper(self, fullname, *args, **kwargs):
185-
with _module_to_load(fullname) as module:
186-
module.__loader__ = self
187-
try:
188-
is_package = self.is_package(fullname)
189-
except (ImportError, AttributeError):
190-
pass
191-
else:
192-
if is_package:
193-
module.__package__ = fullname
194-
else:
195-
module.__package__ = fullname.rpartition('.')[0]
196-
# If __package__ was not set above, __import__() will do it later.
197-
return fxn(self, module, *args, **kwargs)
198-
199-
return module_for_loader_wrapper
200-
201-
202115
class _LazyModule(types.ModuleType):
203116

204117
"""A subclass of the module type which triggers loading upon attribute access."""

Lib/test/test_importlib/test_abc.py

+1-7
Original file line numberDiff line numberDiff line change
@@ -771,13 +771,7 @@ def verify_code(self, code_object):
771771

772772

773773
class SourceOnlyLoaderTests(SourceLoaderTestHarness):
774-
775-
"""Test importlib.abc.SourceLoader for source-only loading.
776-
777-
Reload testing is subsumed by the tests for
778-
importlib.util.module_for_loader.
779-
780-
"""
774+
"""Test importlib.abc.SourceLoader for source-only loading."""
781775

782776
def test_get_source(self):
783777
# Verify the source code is returned as a string.

Lib/test/test_importlib/test_spec.py

-48
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,6 @@ def exec_module(self, module):
4747
module.eggs = self.EGGS
4848

4949

50-
class LegacyLoader(TestLoader):
51-
52-
HAM = -1
53-
54-
with warnings.catch_warnings():
55-
warnings.simplefilter("ignore", DeprecationWarning)
56-
57-
frozen_util = util['Frozen']
58-
59-
@frozen_util.module_for_loader
60-
def load_module(self, module):
61-
module.ham = self.HAM
62-
return module
63-
64-
6550
class ModuleSpecTests:
6651

6752
def setUp(self):
@@ -302,26 +287,6 @@ def exec_module(self, module):
302287
loaded = self.bootstrap._load(self.spec)
303288
self.assertNotIn(self.spec.name, sys.modules)
304289

305-
def test_load_legacy(self):
306-
with warnings.catch_warnings():
307-
warnings.simplefilter("ignore", ImportWarning)
308-
self.spec.loader = LegacyLoader()
309-
with CleanImport(self.spec.name):
310-
loaded = self.bootstrap._load(self.spec)
311-
312-
self.assertEqual(loaded.ham, -1)
313-
314-
def test_load_legacy_attributes(self):
315-
with warnings.catch_warnings():
316-
warnings.simplefilter("ignore", ImportWarning)
317-
self.spec.loader = LegacyLoader()
318-
with CleanImport(self.spec.name):
319-
loaded = self.bootstrap._load(self.spec)
320-
321-
self.assertIs(loaded.__loader__, self.spec.loader)
322-
self.assertEqual(loaded.__package__, self.spec.parent)
323-
self.assertIs(loaded.__spec__, self.spec)
324-
325290
def test_load_legacy_attributes_immutable(self):
326291
module = object()
327292
with warnings.catch_warnings():
@@ -387,19 +352,6 @@ def test_reload_init_module_attrs(self):
387352
self.assertFalse(hasattr(loaded, '__file__'))
388353
self.assertFalse(hasattr(loaded, '__cached__'))
389354

390-
def test_reload_legacy(self):
391-
with warnings.catch_warnings():
392-
warnings.simplefilter("ignore", ImportWarning)
393-
self.spec.loader = LegacyLoader()
394-
with CleanImport(self.spec.name):
395-
loaded = self.bootstrap._load(self.spec)
396-
reloaded = self.bootstrap._exec(self.spec, loaded)
397-
installed = sys.modules[self.spec.name]
398-
399-
self.assertEqual(loaded.ham, -1)
400-
self.assertIs(reloaded, loaded)
401-
self.assertIs(installed, loaded)
402-
403355

404356
(Frozen_ModuleSpecMethodsTests,
405357
Source_ModuleSpecMethodsTests

0 commit comments

Comments
 (0)