Plans (docs/plans/): - 2026-07-01-23-47-py-hxprobe-httpx.md — initial httpx probe design - 2026-07-02-09-32 through 14-05 — standalone project, toolchain, usage doc + Makefile, file input (-f), simplification pass, run-summary footer Summaries (docs/summaries/): one per completed feature, recording what was actually built, deviations from the plan, and verification steps Explanations (docs/explanations/): two deep-dives written during review — hxprobe concurrency model and worst-exit-code + render-loop analysis Usage (docs/usage/hxprobe.md): overview with pointer to hxprobe/USAGE.md for the full runnable reference Walkthrough (docs/py-latprobe-walkthrough.md): narrative tour of the latprobe Python package for interview / code-review context CHANGELOG.md: entries for all hxprobe features (toolchain, usage doc, file input, simplification, run-summary footer) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.2 KiB
hxprobe simplification — summary
Plan: docs/plans/2026-07-02-12-05-hxprobe-simplification.md (five targeted
removals of speculative scaffolding / redundant state / duplicated logic, no
behavior change). Trigger: a question about a dead file= parameter on
_Parser.print_help/print_usage in hxprobe/hxprobe/cli.py, which led to a
broader pass over the whole package for the same pattern.
What changed
-
hxprobe/hxprobe/cli.py— deleted the_Parsersubclass and_ArgExitexception (~32 lines). It re-implemented, by hand, behavior the standard library already provides:argparse.ArgumentParseralready writes help tosys.stdoutand usage/errors tosys.stderr, and already raisesSystemExitrather than hard-exiting.run()now builds a plainargparse.ArgumentParser, wraps the parse + validation calls incontextlib.redirect_stdout(stdout)/redirect_stderr(stderr), and catchesSystemExitat a single site:except SystemExit as exc: return EXIT_OK if not exc.code else EXIT_USAGEDeviation from the original plan sketch: the plan's snippet used
EXIT_OK if not exc.code else EXIT_USAGE, matching what was actually implemented (equivalent to, but slightly more defensive than, theexc.code == 0check first drafted, since argparse can in principle passNone). -
hxprobe/hxprobe/probe.py— trimmed_TimingStream.get_extra_infoto the single branch actually consumed on the request path (ssl_object). Verified by grepping the installedhttpcore/httpxpackages: theserver_addr/client_addrbranches were only ever queried byhttpx's own_main.py(thehttpxCLI command), never by anything hxprobe's request path touches. -
hxprobe/hxprobe/cli.py— simplified_load_urls: dropped theline.split()[0]"forward-compatible with futureurl key=valueannotations" scaffolding; a stripped line is used directly. Docstring updated to describe only what the function does today. -
hxprobe/hxprobe/probe.py— removed_dns_set/_connect_set/_tls_setfrom_Trace. These booleans duplicatedPhase.presentonself.dns/self.connect/self.tls(each starts asPhase(), i.e.present=False). Guards rewritten fromif not self._dns_set:toif not self.dns.present:(and analogously for connect/tls) — identical first-hop-wins semantics for redirects, one less piece of parallel state. -
hxprobe/hxprobe/cli.py— extracted_summarize_failures, a shared helper that dedupesfailed: list[Result]into[(phase, message, count), ...]in first-seen order._print_failure_summary(text rendering) and_build_json_entry(JSON rendering) previously each carried an identical ~12-line dedup loop; both now call the helper and only differ in how they format the tuple.
Not changed (considered, kept — per the plan)
- The custom httpcore backend (
_TimingBackend/_TimingStream/_TimingTransport) — this is the tool's actual reason to exist. ThreadPoolExecutorconcurrency — backs the shipped-c/--concurrencyand multi-URL/-ffeatures.- Explicit per-phase dataclass fields in
probe.py/aggregate.py. CertInfo.sans— unused in text output but real (emitted in JSON verbose output).
Verification
hxprobe/.venv/bin/python -m pytest tests/test_cli.py tests/test_probe.py -q→ 33 passed, no test file edits.hxprobe/.venv/bin/ruff check hxprobe/→ all checks passed.- Manual smoke tests (
python -m hxprobe -h, no-args, and a livehttps://example.com -vrequest):-h→ help text on stdout, exit0.- No args → usage +
no URLs givenerror on stderr only (confirmed via separate stdout/stderr redirection to files — stdout was empty), exit1. - Live verbose request → correct 6-phase timing, resolved IP, HTTP/2
protocol, TLS version/cipher, and certificate detail — confirms the
get_extra_infotrim didn't breakssl_objectretrieval and the_Tracerefactor didn't break phase/first-hop-wins tracking.
Net: cli.py and probe.py are shorter and carry less parallel/duplicated
state; no observable behavior changed.