Skip to content

Commit 0607fdd

Browse files
authored
[3.13] gh-123085: Fix issue in inferred caller when resource package has no source (GH-123102) (#124024)
1 parent 2c614a8 commit 0607fdd

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

Lib/importlib/resources/_common.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,13 @@ def _infer_caller():
9393
"""
9494

9595
def is_this_file(frame_info):
96-
return frame_info.filename == __file__
96+
return frame_info.filename == stack[0].filename
9797

9898
def is_wrapper(frame_info):
9999
return frame_info.function == 'wrapper'
100100

101-
not_this_file = itertools.filterfalse(is_this_file, inspect.stack())
101+
stack = inspect.stack()
102+
not_this_file = itertools.filterfalse(is_this_file, stack)
102103
# also exclude 'wrapper' due to singledispatch in the call stack
103104
callers = itertools.filterfalse(is_wrapper, not_this_file)
104105
return next(callers).frame

Lib/test/test_importlib/resources/test_files.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import os
2+
import pathlib
3+
import py_compile
4+
import shutil
15
import textwrap
26
import unittest
37
import warnings
@@ -7,6 +11,7 @@
711
from importlib import resources
812
from importlib.resources.abc import Traversable
913
from . import util
14+
from test.support import os_helper, import_helper
1015

1116

1217
@contextlib.contextmanager
@@ -117,8 +122,8 @@ class ModuleFilesZipTests(DirectSpec, util.ZipSetup, ModulesFiles, unittest.Test
117122

118123
class ImplicitContextFiles:
119124
set_val = textwrap.dedent(
120-
"""
121-
import importlib.resources as res
125+
f"""
126+
import {resources.__name__} as res
122127
val = res.files().joinpath('res.txt').read_text(encoding='utf-8')
123128
"""
124129
)
@@ -128,6 +133,10 @@ class ImplicitContextFiles:
128133
'submod.py': set_val,
129134
'res.txt': 'resources are the best',
130135
},
136+
'frozenpkg': {
137+
'__init__.py': set_val.replace(resources.__name__, 'c_resources'),
138+
'res.txt': 'resources are the best',
139+
},
131140
}
132141

133142
def test_implicit_files_package(self):
@@ -142,6 +151,32 @@ def test_implicit_files_submodule(self):
142151
"""
143152
assert importlib.import_module('somepkg.submod').val == 'resources are the best'
144153

154+
def _compile_importlib(self):
155+
"""
156+
Make a compiled-only copy of the importlib resources package.
157+
"""
158+
bin_site = self.fixtures.enter_context(os_helper.temp_dir())
159+
c_resources = pathlib.Path(bin_site, 'c_resources')
160+
sources = pathlib.Path(resources.__file__).parent
161+
shutil.copytree(sources, c_resources, ignore=lambda *_: ['__pycache__'])
162+
163+
for dirpath, _, filenames in os.walk(c_resources):
164+
for filename in filenames:
165+
source_path = pathlib.Path(dirpath) / filename
166+
cfile = source_path.with_suffix('.pyc')
167+
py_compile.compile(source_path, cfile)
168+
pathlib.Path.unlink(source_path)
169+
self.fixtures.enter_context(import_helper.DirsOnSysPath(bin_site))
170+
171+
def test_implicit_files_with_compiled_importlib(self):
172+
"""
173+
Caller detection works for compiled-only resources module.
174+
175+
python/cpython#123085
176+
"""
177+
self._compile_importlib()
178+
assert importlib.import_module('frozenpkg').val == 'resources are the best'
179+
145180

146181
class ImplicitContextFilesDiskTests(
147182
DirectSpec, util.DiskSetup, ImplicitContextFiles, unittest.TestCase
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
In a bare call to :func:`importlib.resources.files`, ensure the caller's
2+
frame is properly detected when ``importlib.resources`` is itself available
3+
as a compiled module only (no source).

0 commit comments

Comments
 (0)