Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

building: force the runtime hook execution order based on filenames #7012

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 28 additions & 23 deletions PyInstaller/depend/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,31 +594,36 @@ def analyze_runtime_hooks(self, custom_runhooks):

:return : list of Graph nodes.
"""
rthooks_nodes = []
logger.info('Analyzing run-time hooks ...')
# Process custom runtime hooks (from --runtime-hook options). The runtime hooks are order dependent. First hooks
# in the list are executed first. Put their graph nodes at the head of the priority_scripts list Pyinstaller
# defined rthooks and thus they are executed first.
if custom_runhooks:
for hook_file in custom_runhooks:
logger.info("Including custom run-time hook %r", hook_file)
hook_file = os.path.abspath(hook_file)
# Not using "try" here because the path is supposed to exist, if it does not, the raised error will
# explain.
rthooks_nodes.append(self.add_script(hook_file))

# Find runtime hooks that are implied by packages already imported. Get a temporary TOC listing all the scripts
# and packages graphed so far. Assuming that runtime hooks apply only to modules and packages.

# Process custom runtime hooks (from --runtime-hook options). These hooks are executed first, in the same order
# that they are specified.
rthook_nodes_custom = []
for hook_file in custom_runhooks:
logger.info("Including custom run-time hook %r", hook_file)
hook_file = os.path.abspath(hook_file)
# Not using "try" here because the path is supposed to exist; if not, the error will be self-explanatory.
rthook_nodes_custom.append(self.add_script(hook_file))

# Find runtime hooks that are implied by the imported packages/modules. Obtain a temporary TOC listing all
# imported modules. Under current mechanism, the runtime hooks are tied only to modules/packages.
included_rthooks = []
temp_toc = self._make_toc(VALID_MODULE_TYPES)
for (mod_name, path, typecode) in temp_toc:
# Look if there is any run-time hook for given module.
if mod_name in self._available_rthooks:
# There could be several run-time hooks for a module.
for abs_path in self._available_rthooks[mod_name]:
logger.info("Including run-time hook %r", abs_path)
rthooks_nodes.append(self.add_script(abs_path))

return rthooks_nodes
for mod_name, path, typecode in temp_toc:
# Process hook(s) for the given module.
for hook_file in self._available_rthooks.get(mod_name, []):
hook_basename = os.path.basename(hook_file) # used for sorting
included_rthooks.append((hook_basename, self.add_script(hook_file)))

# Sort the included runtime hooks by their basename. This allows predictable ordering, and also allows us to
# influence the order via hook filenames.
included_rthooks = sorted(included_rthooks, key=lambda e: e[0])
rthook_nodes_regular = []
for _, hook_node in included_rthooks:
logger.info("Including run-time hook %r", hook_node.filename)
rthook_nodes_regular.append(hook_node)

return rthook_nodes_custom + rthook_nodes_regular

def add_hiddenimports(self, module_list):
"""
Expand Down
4 changes: 4 additions & 0 deletions news/7012.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Make runtime hook execution order deterministic, based on the runtime
hook filenames. This change affects only the runtime hooks tied to
the imported modules; the custom runtime hooks are still executed
first and in the order that they are specified.