Third Python implementation in the latency-tool progression. Mirrors latprobe's feature set but replaces raw sockets with httpx, gaining HTTP/2 support and redirect following. Package layout (hxprobe/hxprobe/): - probe.py: asyncio + httpx.AsyncClient with a _TimingStream transport wrapper that captures DNS/connect/TLS/TTFB/transfer phase timings via httpx event hooks (get_connection_stats, request_started, etc.). VerboseDetail captures resolved IP, TLS version/cipher/bits, cert CN/ expiry/issuer (from httpx's SSLObject), and response headers. Options: timeout, verbose, follow_redirects, http2 - aggregate.py: summarize() → per-phase min/avg/max (same schema as latprobe) - cli.py: run(args,stdout,stderr)->int; argparse with redirect_stdout/ redirect_stderr + SystemExit catch; -n/--count, -c/--concurrency, --timeout, --fail, --json, -v/--verbose, --no-follow-redirects, --no-http2, -f/--file (URL list from file, mutually exclusive with args); multi-URL summary footer (tally + exit label) when len(urls) > 1; worst-exit-code logic mirrors Go/latprobe; JSON output is bare array - duration.py: same parse_duration() as latprobe - Exit codes: 0 ok, 1 usage, 2 dns, 3 connect, 4 timeout, 5 tls, 6 http≥400 Tests (hxprobe/tests/): - test_probe.py: 18 hermetic tests using anyio + in-process ASGI servers - test_cli.py: 36 hermetic tests (success, failures, JSON, verbose, -f flag, run-summary footer, worst-code accumulation) - test_integration.py: pytest-marked @integration (excluded from hx-test) Toolchain: uv + ruff + pytest; pyproject.toml with [dependency-groups]; hxprobe/Makefile standalone (help, deps, run, lint, fmt, test, test-integration, check, clean); .python-version pins 3.14 Configs: 8 fixture files mirroring python/configs/ (all-ok through mixed) USAGE.md: 16 runnable examples with real captured output Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
56 lines
2.0 KiB
Makefile
56 lines
2.0 KiB
Makefile
# hxprobe — standalone Makefile. Requires uv (https://docs.astral.sh/uv/).
|
|
#
|
|
# This project is fully self-contained (own pyproject.toml, own uv.lock) and
|
|
# this Makefile works the same whether run from inside a parent monorepo or
|
|
# after `cp -r`'ing hxprobe/ into its own repo. It does not depend on, and is
|
|
# not depended on by, the parent repo's root Makefile — the two are kept
|
|
# independent on purpose so a change to one can't break the other.
|
|
|
|
PYTHON ?= python3.14
|
|
ARGS ?=
|
|
|
|
.DEFAULT_GOAL := help
|
|
|
|
# ── help ──────────────────────────────────────────────────────────────────────
|
|
|
|
.PHONY: help
|
|
help: ## Show this help
|
|
@grep -E '^[a-zA-Z_-]+:.*##' $(MAKEFILE_LIST) \
|
|
| awk 'BEGIN {FS = ":.*##"}; {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}' \
|
|
| sort
|
|
|
|
# ── targets ───────────────────────────────────────────────────────────────────
|
|
|
|
.PHONY: deps
|
|
deps: ## sync the venv from uv.lock; idempotent
|
|
uv sync
|
|
|
|
.PHONY: run
|
|
run: deps ## run hxprobe (pass flags via ARGS="…")
|
|
uv run $(PYTHON) -m hxprobe $(ARGS)
|
|
|
|
.PHONY: lint
|
|
lint: deps ## lint with ruff
|
|
uv run ruff check .
|
|
|
|
.PHONY: fmt
|
|
fmt: deps ## format with ruff
|
|
uv run ruff format .
|
|
|
|
.PHONY: test
|
|
test: deps ## run hermetic unit tests
|
|
uv run pytest tests -m "not integration" -v $(ARGS)
|
|
|
|
.PHONY: test-integration
|
|
test-integration: deps ## run integration tests against live internet services (HTTP/2, redirects)
|
|
uv run pytest tests -m integration -v $(ARGS)
|
|
|
|
.PHONY: check
|
|
check: lint test ## run the full gate: lint + hermetic tests
|
|
|
|
.PHONY: clean
|
|
clean: ## remove bytecode, caches, and egg-info
|
|
@find . -type d -name '__pycache__' -exec rm -rf {} + 2>/dev/null; \
|
|
find . -name '*.pyc' -delete 2>/dev/null; \
|
|
rm -rf *.egg-info .pytest_cache .ruff_cache; true
|