Skip to content

Commit

Permalink
loader: PyiFrozenImporter: work-around for importlib's LazyLoader
Browse files Browse the repository at this point in the history
When `importlib.util.LazyLoader` is used, the `module` passed to
the `PyiFrozenImporter.exec_module` contains modified spec, in
which the `loader_state` is a `dict` prepared by the `LazyLoader`
code.

This means that our original `loader_state` is lost, and we need
to determine the module name for look-up in the PYZ by other means.
Specifically, we convert the `origin` back to the module name, which
allows us to handle aliased modules as well.
  • Loading branch information
rokm committed May 24, 2023
1 parent 8dfb189 commit f53b7cb
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 0 deletions.
15 changes: 15 additions & 0 deletions PyInstaller/loader/pyimod02_importers.py
Expand Up @@ -347,10 +347,25 @@ def exec_module(self, module):
# `pkg_resources.extern.jaraco.text`, but the original name stored in `loader_state`, which we need
# to use for code look-up, is `pkg_resources._vendor.jaraco.text`.
module_name = spec.loader_state.pyz_entry_name
elif isinstance(spec.loader_state, dict):
# This seems to happen when `importlib.util.LazyLoader` is used, and our original `loader_state` is lost.
# We could use `spec.name`, and hope for the best, but that will likely fail with aliased modules (see
# the comment in the branch above for an example).
#
# So, try to reconstruct the original module name from the `origin` - which is essentially the reverse of
# the our `get_filename()` implementation.
assert spec.origin.startswith(SYS_PREFIX)
module_name = spec.origin[SYS_PREFIXLEN:].replace(os.sep, '.')
if module_name.endswith('.pyc'):
module_name = module_name[:-4]
if module_name.endswith('.__init__'):
module_name = module_name[:-9]
else:
raise RuntimeError(f"Module's spec contains loader_state of incompatible type: {type(spec.loader_state)}")

bytecode = self.get_code(module_name)
if bytecode is None:
raise RuntimeError(f"Failed to retrieve bytecode for {spec.name!r}!")

# Set by the import machinery
assert hasattr(module, '__file__')
Expand Down
2 changes: 2 additions & 0 deletions news/7657.bugfix.rst
@@ -0,0 +1,2 @@
Attempt to fix compatibility of PyInstaller's ``PyiFrozenImporter`` with
``importlib.util.LazyLoader``.

0 comments on commit f53b7cb

Please sign in to comment.