Skip to content

Commit

Permalink
hooks: fix the message in distutils pre-module-find hook
Browse files Browse the repository at this point in the history
Fix the "retargetting to non-venv dir" message emitted from the
pre-module-find hook in distutils. Due to incorrect comparison
between parent path levels, the message was always emitted, even
when the distutils was found in stdlib directory. Fix that
comparison and handle the case when distutils is provided by
setuptools. Lastly, demote the message from INFO to DEBUG.
  • Loading branch information
rokm committed Sep 7, 2022
1 parent 3be4a49 commit f93dd3f
Showing 1 changed file with 22 additions and 14 deletions.
36 changes: 22 additions & 14 deletions PyInstaller/hooks/pre_find_module_path/hook-distutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@
"""
`distutils`-specific pre-find module path hook.
When run from within a venv (virtual environment), this hook changes the `__path__` of the `distutils` package to
that of the system-wide rather than venv-specific `distutils` package. While the former is suitable for freezing,
the latter is intended for use _only_ from within venvs.
When run from within a virtual environment, this hook changes the `__path__` of the `distutils` package to
that of the system-wide rather than virtual-environment-specific `distutils` package. While the former is suitable for
freezing, the latter is intended for use _only_ from within virtual environments.
NOTE: this behavior seems to be specific to virtual environments created by (an old?) version of `virtualenv`; it is not
applicable to virtual environments created by the `venv`.
"""

import distutils
import os
import pathlib

from PyInstaller.utils.hooks import logger
from PyInstaller.utils.hooks import logger, get_module_file_attribute


def pre_find_module_path(api):
Expand All @@ -28,11 +30,17 @@ def pre_find_module_path(api):
# opcode is not a virtualenv module, so we can use it to find the stdlib. Technique taken from virtualenv's
# "distutils" package detection at
# https://github.com/pypa/virtualenv/blob/16.3.0/virtualenv_embedded/distutils-init.py#L5
import opcode

system_module_path = os.path.normpath(os.path.dirname(opcode.__file__))
loaded_module_path = os.path.normpath(os.path.dirname(distutils.__file__))
if system_module_path != loaded_module_path:
# Find this package in its parent directory.
api.search_dirs = [system_module_path]
logger.info('distutils: retargeting to non-venv dir %r', system_module_path)
# As opcode is a module, stdlib path corresponds to the parent directory of its ``__file__`` attribute.
stdlib_path = pathlib.Path(get_module_file_attribute('opcode')).parent.resolve()
# As distutils is a package, we need to consider the grandparent directory of its ``__file__`` attribute.
distutils_path = pathlib.Path(get_module_file_attribute('distutils')).parent.parent.resolve()

if distutils_path.name == 'setuptools':
logger.debug("distutils: provided by setuptools")
elif distutils_path == stdlib_path:
logger.debug("distutils: provided by stdlib")
else:
# Find this package in stdlib.
stdlib_path = str(stdlib_path)
logger.debug("distutils: virtualenv shim - retargeting to stdlib dir %r", stdlib_path)
api.search_dirs = [stdlib_path]

0 comments on commit f93dd3f

Please sign in to comment.