Skip to content

Commit bd3baa8

Browse files
tomasr8rashansmithStanFromIrelandbrettcannon
authored
gh-121604: Make sure all deprecated items in importlib raise DeprecationWarning (#128007)
Co-authored-by: rashansmith <[email protected]> Co-authored-by: Stan Ulbrych <[email protected]> Co-authored-by: Brett Cannon <[email protected]>
1 parent b52de22 commit bd3baa8

File tree

8 files changed

+96
-5
lines changed

8 files changed

+96
-5
lines changed

Lib/importlib/_bootstrap_external.py

+6
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,12 @@ def _search_registry(cls, fullname):
716716

717717
@classmethod
718718
def find_spec(cls, fullname, path=None, target=None):
719+
_warnings.warn('importlib.machinery.WindowsRegistryFinder is '
720+
'deprecated; use site configuration instead. '
721+
'Future versions of Python may not enable this '
722+
'finder by default.',
723+
DeprecationWarning, stacklevel=2)
724+
719725
filepath = cls._search_registry(fullname)
720726
if filepath is None:
721727
return None

Lib/importlib/abc.py

+13
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ class ResourceLoader(Loader):
7070
7171
"""
7272

73+
def __init__(self):
74+
import warnings
75+
warnings.warn('importlib.abc.ResourceLoader is deprecated in '
76+
'favour of supporting resource loading through '
77+
'importlib.resources.abc.ResourceReader.',
78+
DeprecationWarning, stacklevel=2)
79+
super().__init__()
80+
81+
7382
@abc.abstractmethod
7483
def get_data(self, path):
7584
"""Abstract method which when implemented should return the bytes for
@@ -199,6 +208,10 @@ class SourceLoader(_bootstrap_external.SourceLoader, ResourceLoader, ExecutionLo
199208

200209
def path_mtime(self, path):
201210
"""Return the (int) modification time for the path (str)."""
211+
import warnings
212+
warnings.warn('SourceLoader.path_mtime is deprecated in favour of '
213+
'SourceLoader.path_stats().',
214+
DeprecationWarning, stacklevel=2)
202215
if self.path_stats.__func__ is SourceLoader.path_stats:
203216
raise OSError
204217
return int(self.path_stats(path)['mtime'])

Lib/importlib/machinery.py

+24-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
from ._bootstrap import ModuleSpec
44
from ._bootstrap import BuiltinImporter
55
from ._bootstrap import FrozenImporter
6-
from ._bootstrap_external import (SOURCE_SUFFIXES, DEBUG_BYTECODE_SUFFIXES,
7-
OPTIMIZED_BYTECODE_SUFFIXES, BYTECODE_SUFFIXES,
8-
EXTENSION_SUFFIXES)
6+
from ._bootstrap_external import (
7+
SOURCE_SUFFIXES, BYTECODE_SUFFIXES, EXTENSION_SUFFIXES,
8+
DEBUG_BYTECODE_SUFFIXES as _DEBUG_BYTECODE_SUFFIXES,
9+
OPTIMIZED_BYTECODE_SUFFIXES as _OPTIMIZED_BYTECODE_SUFFIXES
10+
)
911
from ._bootstrap_external import WindowsRegistryFinder
1012
from ._bootstrap_external import PathFinder
1113
from ._bootstrap_external import FileFinder
@@ -27,3 +29,22 @@ def all_suffixes():
2729
'NamespaceLoader', 'OPTIMIZED_BYTECODE_SUFFIXES', 'PathFinder',
2830
'SOURCE_SUFFIXES', 'SourceFileLoader', 'SourcelessFileLoader',
2931
'WindowsRegistryFinder', 'all_suffixes']
32+
33+
34+
def __getattr__(name):
35+
import warnings
36+
37+
if name == 'DEBUG_BYTECODE_SUFFIXES':
38+
warnings.warn('importlib.machinery.DEBUG_BYTECODE_SUFFIXES is '
39+
'deprecated; use importlib.machinery.BYTECODE_SUFFIXES '
40+
'instead.',
41+
DeprecationWarning, stacklevel=2)
42+
return _DEBUG_BYTECODE_SUFFIXES
43+
elif name == 'OPTIMIZED_BYTECODE_SUFFIXES':
44+
warnings.warn('importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES is '
45+
'deprecated; use importlib.machinery.BYTECODE_SUFFIXES '
46+
'instead.',
47+
DeprecationWarning, stacklevel=2)
48+
return _OPTIMIZED_BYTECODE_SUFFIXES
49+
50+
raise AttributeError(f'module {__name__!r} has no attribute {name!r}')

Lib/inspect.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -858,8 +858,7 @@ def getsourcefile(object):
858858
Return None if no way can be identified to get the source.
859859
"""
860860
filename = getfile(object)
861-
all_bytecode_suffixes = importlib.machinery.DEBUG_BYTECODE_SUFFIXES[:]
862-
all_bytecode_suffixes += importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES[:]
861+
all_bytecode_suffixes = importlib.machinery.BYTECODE_SUFFIXES[:]
863862
if any(filename.endswith(s) for s in all_bytecode_suffixes):
864863
filename = (os.path.splitext(filename)[0] +
865864
importlib.machinery.SOURCE_SUFFIXES[0])

Lib/test/test_importlib/test_abc.py

+32
Original file line numberDiff line numberDiff line change
@@ -913,5 +913,37 @@ def test_universal_newlines(self):
913913
SourceOnlyLoaderMock=SPLIT_SOL)
914914

915915

916+
class SourceLoaderDeprecationWarningsTests(unittest.TestCase):
917+
"""Tests SourceLoader deprecation warnings."""
918+
919+
def test_deprecated_path_mtime(self):
920+
from importlib.abc import SourceLoader
921+
class DummySourceLoader(SourceLoader):
922+
def get_data(self, path):
923+
return b''
924+
925+
def get_filename(self, fullname):
926+
return 'foo.py'
927+
928+
def path_stats(self, path):
929+
return {'mtime': 1}
930+
931+
loader = DummySourceLoader()
932+
with self.assertWarns(DeprecationWarning):
933+
loader.path_mtime('foo.py')
934+
935+
936+
class ResourceLoaderDeprecationWarningsTests(unittest.TestCase):
937+
"""Tests ResourceLoader deprecation warnings."""
938+
939+
def test_deprecated_resource_loader(self):
940+
from importlib.abc import ResourceLoader
941+
class DummyLoader(ResourceLoader):
942+
def get_data(self, path):
943+
return b''
944+
945+
with self.assertWarns(DeprecationWarning):
946+
DummyLoader()
947+
916948
if __name__ == '__main__':
917949
unittest.main()

Lib/test/test_importlib/test_api.py

+13
Original file line numberDiff line numberDiff line change
@@ -492,5 +492,18 @@ def test_util(self):
492492
support.check__all__(self, util['Source'], extra=extra)
493493

494494

495+
class TestDeprecations(unittest.TestCase):
496+
def test_machinery_deprecated_attributes(self):
497+
from importlib import machinery
498+
attributes = (
499+
'DEBUG_BYTECODE_SUFFIXES',
500+
'OPTIMIZED_BYTECODE_SUFFIXES',
501+
)
502+
for attr in attributes:
503+
with self.subTest(attr=attr):
504+
with self.assertWarns(DeprecationWarning):
505+
getattr(machinery, attr)
506+
507+
495508
if __name__ == '__main__':
496509
unittest.main()

Lib/test/test_importlib/test_windows.py

+6
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ def test_module_not_found(self):
104104
spec = self.machinery.WindowsRegistryFinder.find_spec(self.test_module)
105105
self.assertIsNone(spec)
106106

107+
def test_raises_deprecation_warning(self):
108+
# WindowsRegistryFinder is not meant to be instantiated, so the
109+
# deprecation warning is raised in the 'find_spec' method instead.
110+
with self.assertWarns(DeprecationWarning):
111+
self.machinery.WindowsRegistryFinder.find_spec('spam')
112+
107113
(Frozen_WindowsRegistryFinderTests,
108114
Source_WindowsRegistryFinderTests
109115
) = test_util.test_both(WindowsRegistryFinderTests, machinery=machinery)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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 commit comments

Comments
 (0)