Skip to main content
        .--:--.          c o d e c h u
       /  12   \           ╔═════════╗
      |9   ●---3|  meter   ║ 00:42.7 ║   ETA  03:18
       \   6   /           ╚═════════╝
        '-----'          ─── tick · tock · tick · tock ───

Stopwatch, rolling-rate, and ETA — time things without lying about them.

codechu-meter

Stdlib-only measurement primitives — stopwatch, rolling-window rate estimator, ETA predictor — extracted from the Disk Cleaner toolchain. Zero dependencies. Python 3.10+.

Install

pip install codechu-meter

API

Stopwatch

from codechu_meter import Stopwatch

with Stopwatch() as sw:
    do_work()
print(sw.elapsed)  # → float seconds

# Manual form
sw = Stopwatch().start()
do_work()
sw.stop()
print(sw.elapsed)

Formatting is up to you. If you want pretty output, pair with codechu-fmt:

from codechu_fmt import format_duration
print(format_duration(sw.elapsed))  # → '1m 30s'

RateEstimator

from codechu_meter import RateEstimator

re = RateEstimator(window_seconds=1.0, unit="bytes")
for chunk in stream:
    re.observe(len(chunk))
print(re.rate())   # float per-second

unit is just an attribute — it never affects the numeric rate(). Use it as a label when formatting:

from codechu_fmt import format_rate
print(format_rate(re.rate(), unit=re.unit))  # → '1.2 MB/s'

ETAEstimator

from codechu_meter import ETAEstimator

eta = ETAEstimator(total=1000, mode="ema", alpha=0.3)
for current in progress:
    eta.update(current)
    remaining = eta.eta()  # float seconds or None

mode='linear' (default) uses overall throughput since construction. mode='ema' blends an exponential moving average of recent throughput for smoother numbers on bursty workloads. The alpha parameter (default 0.3) controls EMA reactivity: higher values weight recent samples more heavily.

eta() returns None until at least two updates with measurable elapsed time and positive progress.

Counter (v0.3.0+)

Thread-safe int counter. inc / dec / reset / .value are all guarded by a threading.Lock.

from codechu_meter import Counter

inflight = Counter()
inflight.inc()
try:
    serve(req)
finally:
    inflight.dec()
print(inflight.value)

Histogram (v0.3.0+)

Bucketed distribution counter. Upper edges are inclusive; values above the largest edge fall into a math.inf overflow bucket. Thread-safe.

from codechu_meter import Histogram

hist = Histogram([0.01, 0.05, 0.1, 0.5, 1.0])
for r in requests:
    hist.observe(r.latency_seconds)
print(hist.counts, hist.total)

PercentileEstimator (v0.3.0+)

Streaming p50 / p95 / p99 via Vitter's reservoir sampling (max_samples capped). Pure stdlib — no numpy. Thread-safe.

from codechu_meter import PercentileEstimator

pe = PercentileEstimator(max_samples=5_000)
for r in requests:
    pe.observe(r.latency_seconds)
print(pe.p50, pe.p95, pe.p99)

Stopwatch named sections (v0.3.0+)

Stopwatch.section(name) accumulates sub-timings into Stopwatch.sections. Same name re-entered → values add. Not thread-safe; use one Stopwatch per thread.

sw = Stopwatch().start()
with sw.section("parse"):
    parse(buf)
with sw.section("emit"):
    emit(result)
sw.stop()
print(sw.sections)  # → {"parse": 0.012, "emit": 0.004}

Design

  • Zero dependencies. Stdlib only.
  • Monotonic clock. Wall-clock jumps don't break timing.
  • No formatting coupling. Numeric primitives only; pair with codechu-fmt (or roll your own) for display strings.
  • Defensive. Zero progress, zero elapsed, NaN, and negative rates never raise.

Migrating from 0.1.x

__str__ methods were removed in 0.2.0. Replace print(sw) / str(re) / str(eta) with explicit calls:

# Before (0.1.x)
print(sw)
print(re)
print(eta)

# After (0.2.x)
from codechu_fmt import format_duration, format_rate
print(format_duration(sw.elapsed))
print(format_rate(re.rate(), unit=re.unit))
v = eta.eta()
print(format_duration(v) if v is not None else "?")

Tests

pip install -e ".[dev]"
pytest -q

Coverage gate: ≥90 %. Tests drive time via monkeypatching time.monotonic for deterministic assertions.

Documentation

  • API reference — every public symbol, parameter, return value, and exception.
  • Migration guide — 0.1.x → 0.2.0 (breaking __str__ removal, new alpha parameter, dropped codechu-fmt dependency).
  • Recipes — patterns for timing blocks, tracking download speed, computing ETA, tuning EMA alpha, and pairing with codechu-fmt.

License

MIT — see LICENSE.

Metadata

Release files for codechu-meter 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for codechu-meter 0.3.0
File Size Uploaded
codechu_meter-0.3.0.tar.gz 15.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for codechu-meter 0.3.0
File Interpreter ABI Platform
codechu_meter-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 27.2 kB

Release files / codechu_meter-0.3.0.tar.gz

Download URL codechu_meter-0.3.0.tar.gz
Size 15.4 kB
Tags Source
SHA-256 checksum
How to use checksums
bfca71fb3b0d45f64a75f99e53672a5cb64651935f0a69ad8fb1e224ec7bcba5
BLAKE2b-256 checksum
How to use checksums
42f2b87abdd8f007fa99a5215f42181f91a6e49269ad520c6974270a7759537e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 20, 2026.

Transparency log

Release files / codechu_meter-0.3.0-py3-none-any.whl

Download URL codechu_meter-0.3.0-py3-none-any.whl
Size 11.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8ce94451b99fcf4aa3224aa6f3810c7c6cedbd52368e2efb7228ddef449a15e9
BLAKE2b-256 checksum
How to use checksums
76509447d1c1971672676f7ec4e254dd997f01449f0ddc23e461f644a9f5a0c6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 20, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page