What Is the TrioProgress Instrument in Holehe and How Does It Show Progress?
The TrioProgress instrument is a lightweight trio instrumentation hook in holehe that bridges asynchronous task completion events to a visual tqdm progress bar.
Holehe is an OSINT tool that checks email addresses against hundreds of websites simultaneously. Because these checks run concurrently via trio, the project needs a non-blocking way to display progress to users. The TrioProgress class provides this by tapping into trio's low-level instrumentation API.
How TrioProgress Fits Into Holehe's Architecture
The instrument sits between trio's task scheduler and the user's terminal. Rather than modifying every site-checking module to report status, holehe registers a single global observer that watches for task lifecycle events.
In [holehe/instruments.py](https://github.com/megadose/holehe/blob/master/holehe/instruments.py), the class is defined as:
from tqdm import tqdm
class TrioProgress:
def __init__(self, total):
self.tqdm = tqdm(total=total)
def task_exited(self, task):
if task.name.split(".")[-1] == "launch_module":
self.tqdm.update(1)
The task_exited method is trio's standard instrumentation callback. TrioProgress filters these events by task name, looking specifically for "launch_module"—the coroutine that wraps each site's check.
Where TrioProgress Is Created and Registered
The instrument lifecycle is managed in [holehe/core.py](https://github.com/megadose/holehe/blob/master/holehe/core.py). Here's the exact integration:
# From holehe/core.py, lines 16-17
instrument = TrioProgress(len(websites))
trio.lowlevel.add_instrument(instrument)
This happens before any site checks begin. The len(websites) parameter tells tqdm how many total increments to expect.
How the Progress Bar Updates in Real Time
When trio schedules a launch_module task, it eventually exits—either successfully or with an exception. At that moment:
- Trio calls
instrument.task_exited(task)for every finished task - The instrument checks if
task.name.split(".")[-1] == "launch_module" - If matched,
self.tqdm.update(1)advances the bar by one unit
After all modules complete, holehe cleans up:
trio.lowlevel.remove_instrument(instrument)
This prevents memory leaks and ensures the progress bar finalizes properly.
Complete Working Example
This standalone script demonstrates the same pattern holehe uses internally:
import trio
from tqdm import tqdm
class TrioProgress:
def __init__(self, total):
self.tqdm = tqdm(total=total, desc="Checking sites")
def task_exited(self, task):
if task.name.split(".")[-1] == "launch_module":
self.tqdm.update(1)
def close(self):
self.tqdm.close()
async def launch_module(site_id):
"""Simulates a site check taking variable time."""
await trio.sleep(0.1 + site_id * 0.05)
async def main():
sites = ["twitter", "github", "gitlab", "instagram", "reddit"]
# Create and register the instrument
prog = TrioProgress(len(sites))
trio.lowlevel.add_instrument(prog)
try:
async with trio.open_nursery() as nursery:
for site in sites:
nursery.start_soon(launch_module, site)
finally:
# Always clean up the instrument
trio.lowlevel.remove_instrument(prog)
prog.close()
if __name__ == "__main__":
trio.run(main)
Running this displays a live tqdm bar that increments as each launch_module task exits, identical to holehe's behavior during email verification.
Key Design Decisions in TrioProgress
- Task name filtering: Uses string splitting on
task.namerather than identity checks, keeping the instrument decoupled from specific coroutine objects - Minimal API surface: Only implements
task_exited, ignoring other trio hooks liketask_scheduledorbefore_io_wait - External tqdm instance: Delegates all rendering to tqdm rather than custom terminal code, ensuring compatibility across platforms
Summary
- TrioProgress is a trio
Instrumentsubclass that converts task exit events into progress bar updates - Located in
holehe/instruments.py, it wraps atqdmbar and increments whenlaunch_moduletasks finish - Registered in
holehe/core.pybefore site checks begin and removed after completion - Enables real-time feedback without modifying individual checking modules or blocking the event loop
Frequently Asked Questions
What is a trio instrument?
A trio instrument is a class that implements specific callback methods to observe low-level task scheduling events. Trio calls these methods at key moments—task creation, execution, I/O operations, and exit—allowing external code to monitor or modify behavior without changing task code.
Why does TrioProgress check task.name instead of using a counter?
The task name check ensures the progress bar only increments for actual site checks, not for internal trio tasks or nursery management. In holehe, launch_module is the specific coroutine that performs each site's verification, so filtering by name provides accurate progress tracking.
Can TrioProgress work with other async libraries?
No—trio instruments are specific to trio's scheduling system. The trio.lowlevel.add_instrument API is proprietary to trio. For asyncio, you would need a different approach such as asyncio.Queue-based progress reporting or manual callback injection.
Does using TrioProgress slow down holehe's performance?
The overhead is negligible. The task_exited callback performs only a string split, equality check, and integer increment—operations measured in microseconds. The tqdm update batches terminal writes efficiently, so the instrument adds no perceptible latency to concurrent site checks.
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 →