Skip to content

Commit

Permalink
[3.13] pythongh-123085: Fix issue in inferred caller when resource pa…
Browse files Browse the repository at this point in the history
…ckage has no source (pythonGH-123102)
  • Loading branch information
jaraco committed Sep 12, 2024
1 parent 92f9a53 commit 50c8d2d
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 4 deletions.
5 changes: 3 additions & 2 deletions Lib/importlib/resources/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,13 @@ def _infer_caller():
"""

def is_this_file(frame_info):
return frame_info.filename == __file__
return frame_info.filename == stack[0].filename

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

not_this_file = itertools.filterfalse(is_this_file, inspect.stack())
stack = inspect.stack()
not_this_file = itertools.filterfalse(is_this_file, stack)
# also exclude 'wrapper' due to singledispatch in the call stack
callers = itertools.filterfalse(is_wrapper, not_this_file)
return next(callers).frame
Expand Down
39 changes: 37 additions & 2 deletions Lib/test/test_importlib/resources/test_files.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import os
import pathlib
import py_compile
import shutil
import textwrap
import unittest
import warnings
Expand All @@ -7,6 +11,7 @@
from importlib import resources
from importlib.resources.abc import Traversable
from . import util
from test.support import os_helper, import_helper


@contextlib.contextmanager
Expand Down Expand Up @@ -97,8 +102,8 @@ class ModuleFilesZipTests(DirectSpec, util.ZipSetup, ModulesFiles, unittest.Test

class ImplicitContextFiles:
set_val = textwrap.dedent(
"""
import importlib.resources as res
f"""
import {resources.__name__} as res
val = res.files().joinpath('res.txt').read_text(encoding='utf-8')
"""
)
Expand All @@ -108,6 +113,10 @@ class ImplicitContextFiles:
'submod.py': set_val,
'res.txt': 'resources are the best',
},
'frozenpkg': {
'__init__.py': set_val.replace(resources.__name__, 'c_resources'),
'res.txt': 'resources are the best',
},
}

def test_implicit_files_package(self):
Expand All @@ -122,6 +131,32 @@ def test_implicit_files_submodule(self):
"""
assert importlib.import_module('somepkg.submod').val == 'resources are the best'

def _compile_importlib(self):
"""
Make a compiled-only copy of the importlib resources package.
"""
bin_site = self.fixtures.enter_context(os_helper.temp_dir())
c_resources = pathlib.Path(bin_site, 'c_resources')
sources = pathlib.Path(resources.__file__).parent
shutil.copytree(sources, c_resources, ignore=lambda *_: ['__pycache__'])

for dirpath, _, filenames in os.walk(c_resources):
for filename in filenames:
source_path = pathlib.Path(dirpath) / filename
cfile = source_path.with_suffix('.pyc')
py_compile.compile(source_path, cfile)
pathlib.Path.unlink(source_path)
self.fixtures.enter_context(import_helper.DirsOnSysPath(bin_site))

def test_implicit_files_with_compiled_importlib(self):
"""
Caller detection works for compiled-only resources module.
python/cpython#123085
"""
self._compile_importlib()
assert importlib.import_module('frozenpkg').val == 'resources are the best'


class ImplicitContextFilesDiskTests(
DirectSpec, util.DiskSetup, ImplicitContextFiles, unittest.TestCase
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
In a bare call to :func:`importlib.resources.files`, ensure the caller's
frame is properly detected when ``importlib.resources`` is itself available
as a compiled module only (no source).

0 comments on commit 50c8d2d

Please sign in to comment.