Skip to content

Commit

Permalink
gh-121604: Make sure all deprecated items in importlib raise Deprecat…
Browse files Browse the repository at this point in the history
…ionWarning (#128007)

Co-authored-by: rashansmith <smith.rashan@gmail.com>
Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com>
Co-authored-by: Brett Cannon <brett@python.org>
  • Loading branch information
4 people authored Jan 15, 2025
1 parent b52de22 commit bd3baa8
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 5 deletions.
6 changes: 6 additions & 0 deletions Lib/importlib/_bootstrap_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,12 @@ def _search_registry(cls, fullname):

@classmethod
def find_spec(cls, fullname, path=None, target=None):
_warnings.warn('importlib.machinery.WindowsRegistryFinder is '
'deprecated; use site configuration instead. '
'Future versions of Python may not enable this '
'finder by default.',
DeprecationWarning, stacklevel=2)

filepath = cls._search_registry(fullname)
if filepath is None:
return None
Expand Down
13 changes: 13 additions & 0 deletions Lib/importlib/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ class ResourceLoader(Loader):
"""

def __init__(self):
import warnings
warnings.warn('importlib.abc.ResourceLoader is deprecated in '
'favour of supporting resource loading through '
'importlib.resources.abc.ResourceReader.',
DeprecationWarning, stacklevel=2)
super().__init__()


@abc.abstractmethod
def get_data(self, path):
"""Abstract method which when implemented should return the bytes for
Expand Down Expand Up @@ -199,6 +208,10 @@ class SourceLoader(_bootstrap_external.SourceLoader, ResourceLoader, ExecutionLo

def path_mtime(self, path):
"""Return the (int) modification time for the path (str)."""
import warnings
warnings.warn('SourceLoader.path_mtime is deprecated in favour of '
'SourceLoader.path_stats().',
DeprecationWarning, stacklevel=2)
if self.path_stats.__func__ is SourceLoader.path_stats:
raise OSError
return int(self.path_stats(path)['mtime'])
Expand Down
27 changes: 24 additions & 3 deletions Lib/importlib/machinery.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
from ._bootstrap import ModuleSpec
from ._bootstrap import BuiltinImporter
from ._bootstrap import FrozenImporter
from ._bootstrap_external import (SOURCE_SUFFIXES, DEBUG_BYTECODE_SUFFIXES,
OPTIMIZED_BYTECODE_SUFFIXES, BYTECODE_SUFFIXES,
EXTENSION_SUFFIXES)
from ._bootstrap_external import (
SOURCE_SUFFIXES, BYTECODE_SUFFIXES, EXTENSION_SUFFIXES,
DEBUG_BYTECODE_SUFFIXES as _DEBUG_BYTECODE_SUFFIXES,
OPTIMIZED_BYTECODE_SUFFIXES as _OPTIMIZED_BYTECODE_SUFFIXES
)
from ._bootstrap_external import WindowsRegistryFinder
from ._bootstrap_external import PathFinder
from ._bootstrap_external import FileFinder
Expand All @@ -27,3 +29,22 @@ def all_suffixes():
'NamespaceLoader', 'OPTIMIZED_BYTECODE_SUFFIXES', 'PathFinder',
'SOURCE_SUFFIXES', 'SourceFileLoader', 'SourcelessFileLoader',
'WindowsRegistryFinder', 'all_suffixes']


def __getattr__(name):
import warnings

if name == 'DEBUG_BYTECODE_SUFFIXES':
warnings.warn('importlib.machinery.DEBUG_BYTECODE_SUFFIXES is '
'deprecated; use importlib.machinery.BYTECODE_SUFFIXES '
'instead.',
DeprecationWarning, stacklevel=2)
return _DEBUG_BYTECODE_SUFFIXES
elif name == 'OPTIMIZED_BYTECODE_SUFFIXES':
warnings.warn('importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES is '
'deprecated; use importlib.machinery.BYTECODE_SUFFIXES '
'instead.',
DeprecationWarning, stacklevel=2)
return _OPTIMIZED_BYTECODE_SUFFIXES

raise AttributeError(f'module {__name__!r} has no attribute {name!r}')
3 changes: 1 addition & 2 deletions Lib/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -858,8 +858,7 @@ def getsourcefile(object):
Return None if no way can be identified to get the source.
"""
filename = getfile(object)
all_bytecode_suffixes = importlib.machinery.DEBUG_BYTECODE_SUFFIXES[:]
all_bytecode_suffixes += importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES[:]
all_bytecode_suffixes = importlib.machinery.BYTECODE_SUFFIXES[:]
if any(filename.endswith(s) for s in all_bytecode_suffixes):
filename = (os.path.splitext(filename)[0] +
importlib.machinery.SOURCE_SUFFIXES[0])
Expand Down
32 changes: 32 additions & 0 deletions Lib/test/test_importlib/test_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -913,5 +913,37 @@ def test_universal_newlines(self):
SourceOnlyLoaderMock=SPLIT_SOL)


class SourceLoaderDeprecationWarningsTests(unittest.TestCase):
"""Tests SourceLoader deprecation warnings."""

def test_deprecated_path_mtime(self):
from importlib.abc import SourceLoader
class DummySourceLoader(SourceLoader):
def get_data(self, path):
return b''

def get_filename(self, fullname):
return 'foo.py'

def path_stats(self, path):
return {'mtime': 1}

loader = DummySourceLoader()
with self.assertWarns(DeprecationWarning):
loader.path_mtime('foo.py')


class ResourceLoaderDeprecationWarningsTests(unittest.TestCase):
"""Tests ResourceLoader deprecation warnings."""

def test_deprecated_resource_loader(self):
from importlib.abc import ResourceLoader
class DummyLoader(ResourceLoader):
def get_data(self, path):
return b''

with self.assertWarns(DeprecationWarning):
DummyLoader()

if __name__ == '__main__':
unittest.main()
13 changes: 13 additions & 0 deletions Lib/test/test_importlib/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,5 +492,18 @@ def test_util(self):
support.check__all__(self, util['Source'], extra=extra)


class TestDeprecations(unittest.TestCase):
def test_machinery_deprecated_attributes(self):
from importlib import machinery
attributes = (
'DEBUG_BYTECODE_SUFFIXES',
'OPTIMIZED_BYTECODE_SUFFIXES',
)
for attr in attributes:
with self.subTest(attr=attr):
with self.assertWarns(DeprecationWarning):
getattr(machinery, attr)


if __name__ == '__main__':
unittest.main()
6 changes: 6 additions & 0 deletions Lib/test/test_importlib/test_windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ def test_module_not_found(self):
spec = self.machinery.WindowsRegistryFinder.find_spec(self.test_module)
self.assertIsNone(spec)

def test_raises_deprecation_warning(self):
# WindowsRegistryFinder is not meant to be instantiated, so the
# deprecation warning is raised in the 'find_spec' method instead.
with self.assertWarns(DeprecationWarning):
self.machinery.WindowsRegistryFinder.find_spec('spam')

(Frozen_WindowsRegistryFinderTests,
Source_WindowsRegistryFinderTests
) = test_util.test_both(WindowsRegistryFinderTests, machinery=machinery)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add missing Deprecation warnings for :attr:`importlib.machinery.DEBUG_BYTECODE_SUFFIXES`, :attr:`importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES`, :class:`importlib.machinery.WindowsRegistryFinder`, :class:`importlib.abc.ResourceLoader`, :meth:`importlib.abc.SourceLoader.path_mtime`.

0 comments on commit bd3baa8

Please sign in to comment.