importlib.resources.files() doesn't work correctly when importlib library is compiled
Bug report
Bug description:
If importlib library is compiled (in particular _common.py), then any package, that uses bare files() to get its resources, breaks, because _infer_caller returns wrong frame (as mentioned in #123037 (comment), __file__ in
| return frame_info.filename == __file__ |
is not valid)
Reproducer:
import importlib import os import pathlib import py_compile import shutil import sys import tempfile import textwrap def compile(tempdir): target_dir = pathlib.Path(tempdir) / 'cimportlib' souce_dir = pathlib.Path(importlib.__file__).parent shutil.copytree(souce_dir, target_dir, ignore=lambda *_: ['__pycache__']) for dirpath, _, filenames in os.walk(target_dir): for filename in filenames: if filename != "_common.py": continue source_path = pathlib.Path(dirpath) / filename cfile = source_path.with_suffix('.pyc') py_compile.compile(source_path, cfile) pathlib.Path.unlink(source_path) def create_package(tempdir): package_dir = pathlib.Path(tempdir) / 'somepkg' package_dir.mkdir() contents = { "__init__.py": textwrap.dedent( """ import cimportlib.resources as res val = res.files().joinpath('resource.txt').read_text(encoding='utf-8') """ ), "resource.txt": "data", } for file, content in contents.items(): path = pathlib.Path(package_dir) / file path.write_text(content) def main(): with tempfile.TemporaryDirectory() as tempdir: compile(tempdir) create_package(tempdir) sys.path.insert(0, str(tempdir)) print(importlib.import_module('somepkg').val) if __name__ == "__main__": raise SystemExit(main())
Expectation:
Actual outcome:
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmpngnuw441/cimportlib/resources/resource.txt'It may be important for frozen python applications, as they don't include source code
CPython versions tested on:
3.12, CPython main branch
Operating systems tested on:
Linux, Windows
Linked PRs
- gh-123085: Fix issue in inferred caller when resources package has no source #123102
- [3.12] gh-123085: Fix issue in inferred caller when resources package has no source (GH-123102) #124021
- [3.13] gh-123085: Fix issue in inferred caller when resource package has no source (GH-123102) #124024
- gh-123085: _compile_importlib: Avoid copying sources before compilation #124131
- [3.12] gh-123085: _compile_importlib: Avoid copying sources before compilation (GH-124131) #128581
- [3.12] gh-123085: Remove double 'import os' added by PR #124021 #128600
- [3.13] gh-123085: _compile_importlib: Avoid copying sources before compilation (GH-124131) #137914