How Holehe Dynamically Loads Modules: Runtime Discovery in megadose/holehe
Holehe dynamically loads modules by using pkgutil.walk_packages to discover Python files under holehe/modules, importlib to load them, and a custom filtering mechanism to extract the service-checking functions for async execution via trio.
The open-source OSINT tool megadose/holehe validates email address usage across hundreds of online services without hardcoded import statements for each platform. By implementing a runtime module discovery system in holehe/core.py, the tool achieves a plug-and-play architecture where adding new services requires only dropping a Python file into the correct directory structure.
The Three-Stage Dynamic Loading Pipeline
The dynamic loading mechanism operates through three coordinated phases that transform filesystem modules into executable coroutines.
Stage 1: Package Discovery via import_submodules
The import_submodules function (lines 36-46 in holehe/core.py) initiates the discovery process by traversing the package tree under holehe.modules. Using pkgutil.walk_packages, it iterates through every subdirectory and Python file, then calls importlib.import_module to load each discovered sub-module into memory. This approach eliminates the need for explicit import statements in the codebase, allowing the tool to recognize new services immediately upon file creation.
Stage 2: Function Extraction with get_functions
Once modules are loaded, the get_functions utility (lines 50-63 in holehe/core.py) filters the results to extract the actual checking functions. It receives the dictionary from import_submodules, iterates over fully-qualified module names (such as holehe.modules.social_media.twitter), and selects entries matching the expected directory depth. For qualifying modules, it retrieves the callable object that shares the module's final component name—the specific function that performs the email verification request.
Stage 3: Async Execution in maincore
The maincore function (lines 95-122 in holehe/core.py) orchestrates execution by invoking the previous two stages and spawning concurrent tasks. It passes the extracted functions to trio for asynchronous execution, enabling simultaneous checks against multiple services without blocking. Each callable runs as an independent task, aggregating results into a unified output format.
File Structure and Implementation Details
The dynamic loader relies on strict conventions within the repository structure. The holehe/modules/ directory contains subdirectories categorizing services (such as social_media, shopping, or productivity), with each Python file named after the service it checks. The loader expects each file to define a function matching its filename—creating a direct mapping between the filesystem and the executable code.
According to the megadose/holehe source code, the implementation uses standard library components rather than third-party dependency injection frameworks. The pkgutil.walk_packages call recursively inspects the holehe.modules namespace, while importlib.import_module handles the actual module instantiation. This design keeps dependencies minimal while maximizing extensibility.
Working with the Dynamic Loader
Developers can interact with Holehe's module system both programmatically and through the command line interface.
Manual Module Loading
To inspect or invoke the discovered functions directly:
from holehe.core import import_submodules, get_functions
# Discover and load every module under holehe.modules
mods = import_submodules("holehe.modules")
# Extract the service-checking functions (e.g., twitter, instagram)
functions = get_functions(mods)
# Execute or inspect the loaded functions
for fn in functions:
print(f"Loaded: {fn.__name__}")
CLI Execution
The command-line interface automates this process:
holehe victim@example.com
Behind the scenes, the CLI executes maincore, which performs the dynamic loading pipeline and runs each function concurrently using trio.
Summary
import_submodulesinholehe/core.pyusespkgutil.walk_packagesto discover all Python modules underholehe/moduleswithout explicit imports.get_functionsfilters the discovered modules by depth and extracts the checking functions that match their filenames.maincorecombines these utilities to load modules at runtime and execute them asynchronously viatrio.- The architecture enables a plug-and-play system where adding services requires only creating new files in
holehe/modules/subdirectories.
Frequently Asked Questions
How does Holehe discover new service modules without explicit imports?
Holehe uses pkgutil.walk_packages to recursively scan the holehe.modules package tree at runtime. When it encounters a new Python file in any subdirectory of holehe/modules/, it automatically loads the module using importlib.import_module, making the service available immediately without modifying any import statements in the core code.
What is the role of pkgutil.walk_packages in Holehe's architecture?
The pkgutil.walk_packages function serves as the discovery engine in holehe/core.py. It traverses the entire module hierarchy under holehe.modules, yielding information about every sub-package and module found. This allows Holehe to maintain a modular structure where services are organized by category (social media, shopping, etc.) while the loader treats them as a flat collection of callable functions.
How does Holehe execute multiple service checks concurrently?
After extracting the checking functions via get_functions, the maincore function passes them to trio to create an asynchronous task for each service. Each task runs the service-specific check independently, allowing hundreds of email verification requests to execute in parallel rather than sequentially, significantly reducing the total execution time for OSINT investigations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →