freeze_support.py
Overview
`freeze_support.py` provides utility functions designed to assist freezing tools (such as cx_Freeze) in identifying all internal modules used by the `pytest` testing framework. Freezing tools bundle Python applications into standalone executables by including all necessary modules and dependencies. This file specifically helps ensure that all relevant `pytest` submodules are detected and included during the freezing process.
The primary functionality centers around recursively enumerating all modules within the `_pytest` package, returning a comprehensive list of module names that freezing tools can then incorporate.
Detailed Documentation
Function: freeze_includes() -> list[str]
Returns a list of fully qualified module names used by `pytest` that should be included by the freezing tool cx_Freeze.
Purpose:
To provide a single entry point that returns allpytestinternal modules for freezing.Parameters:
NoneReturns:
list[str]: A list of strings representing module names. Each string is a fully qualified module path (e.g.,_pytest._code.code).Usage Example:
from freeze_support import freeze_includes modules_to_include = freeze_includes() print(modules_to_include) # Output might include: ['_pytest._argcomplete', '_pytest._code.code', ...]Implementation Detail:
It imports the internal_pytestpackage and calls the helper function_iter_all_modulesto recursively gather all submodules.
Function: _iter_all_modules(package: str | types.ModuleType, prefix: str = "") -> Iterator[str]
Recursively iterates over the names of all modules within a given package, yielding their fully qualified names.
Purpose:
To traverse the package directory structure and yield module names for all contained Python modules and subpackages.Parameters:
Parameter
Type
Description
`package`
`str` or `types.ModuleType`
The package to scan. Can be a string path or a module object.
`prefix`
`str` (default `""`)
The prefix used for module names, typically the parent package name.
Returns:
Iterator[str]: An iterator over fully qualified module names as strings.Usage Example:
import _pytest from freeze_support import _iter_all_modules all_modules = list(_iter_all_modules(_pytest)) print(all_modules) # Output: ['_pytest._argcomplete', '_pytest._code.code', ...]Implementation Details:
If
packageis a string, it treats it as a path.If
packageis a module, it retrieves the filesystem path from the module's__path__attribute.Uses
pkgutil.iter_modules()to list modules and packages under the specified path.If a submodule is a package, recursively calls itself to iterate inside it, appending the subpackage name as a prefix.
Yields fully qualified module names by combining the prefix with the module name.
Algorithmic Notes:
The recursion ensures deep traversal into nested subpackages.
Uses dynamic import path analysis rather than hardcoding module names.
Supports both string paths and module objects for flexibility.
Important Implementation Details
The file uses
pkgutil.iter_modules()to discover modules on the filesystem without importing them (except for the initial import of_pytest).Recursion is leveraged to handle arbitrarily deep package hierarchies.
The prefix parameter is crucial to build fully qualified module names corresponding to Python import paths.
The module distinguishes between packages and modules via the
is_packageflag frompkgutil.
Interaction with Other System Components
Interaction with
pytest:
The file imports the private_pytestpackage (the internal namespace ofpytest) to find all its submodules. These modules constitute the internals of pytest's implementation.Integration with Freezing Tools:
The output list fromfreeze_includes()can be used by cx_Freeze or similar freezing tools to explicitly specify modules that need to be bundled. This is important because freezing tools may miss dynamically imported modules or modules discovered only at runtime.No External Dependencies:
Apart from standard library modules (pkgutil,os,types) and the_pytestpackage, the file is self-contained.
Visual Diagram
The following Mermaid flowchart illustrates the workflow and relationships between the main functions in this file:
flowchart TD
A[freeze_includes()] --> B[_iter_all_modules(package=_pytest)]
B --> C{Is item a package?}
C -- Yes --> B
C -- No --> D[Yield fully qualified module name]
D --> E[Collect all module names into list]
E --> F[Return list of module names]
freeze_includescalls_iter_all_modulesstarting at_pytest._iter_all_modulesrecursively checks each item.For packages, it recurses deeper.
For regular modules, it yields the module name.
All yielded names are collected and returned as a list.
Summary
`freeze_support.py` is a small but essential utility to facilitate the freezing of the `pytest` package by programmatically enumerating all internal modules. It ensures that freezing tools can gather the complete set of modules required for a standalone executable, avoiding missing dependencies that could cause runtime errors. The recursive discovery implemented via `_iter_all_modules` is a robust solution for dynamic module inclusion, adaptable to changes in `pytest` internals without manual updates.