Skip to content

feat: add Timer, a small context-manager/manual elapsed-time timer - #23

Merged
thorwhalen merged 2 commits into
masterfrom
add-timer
Aug 26, 2026
Merged

feat: add Timer, a small context-manager/manual elapsed-time timer#23
thorwhalen merged 2 commits into
masterfrom
add-timer

Conversation

@thorwhalen

Copy link
Copy Markdown
Member

Summary

Adds Timer to stream2py.util (and exports it from the package root): a small
elapsed-time helper usable either as a context manager or started/stopped manually,
with an optional egress callable applied to the elapsed seconds.

  • Monotonic (time.perf_counter), so it is unaffected by system clock adjustments.
  • Reusable across context blocks.
  • elapsed() on a stopped timer raises a ValueError that says what to do, rather
    than failing obscurely.

Changes

  • stream2py/util.pyTimer, identity
  • stream2py/__init__.py — export Timer
  • stream2py/tests/test_util.py — tests

Branch had been sitting unlanded since 2026-08-10; renamed from claude/add-timer
to add-timer per the branch-naming policy.

Recovers work that had been stranded on the `audio_timestamp` branch since
2023 (that branch was merged once, via #19, then kept receiving commits that
were never landed). Re-derived against current master and finished off.

Changes from the stranded version:

- `elapsed()` no longer detects "not started" by catching TypeError from
  `time() - None`. That conflated two different failures: if `egress` itself
  raised TypeError, the except block's `if start_time is None` was False, so
  the function fell off the end and returned None -- silently swallowing the
  real error. It now checks `start_time` explicitly and raises ValueError with
  an actionable message.
- Uses `time.perf_counter` rather than `time.time`. Elapsed-time measurement
  wants a monotonic clock; wall-clock time can jump backwards under NTP
  adjustment and yield negative durations. Documented that this makes
  `start_time` a reference point, not a wall-clock timestamp.
- Doctest sleeps reduced from 1s to 0.01s. The displayed outputs are unchanged
  (they were either +SKIP'd or floor-divided to 0), so this costs nothing in
  illustrative value and takes ~2s off the suite.

Adds 9 unit tests, two of which are regression guards for the swallowed-error
bug described above.

Claude-Session: https://claude.ai/code/session_01EwmvrvgLNjzgE8weA4MMWU
@thorwhalen

Copy link
Copy Markdown
Member Author

CI cannot run on this repo — not a problem with this change.

.github/workflows/ci.yml on master still specifies runs-on: ubuntu-18.04, a
runner label GitHub retired. Both workflow runs for this branch sat queued for
20+ minutes and would never have been scheduled; I cancelled them rather than
leave them hanging.

So the branch cannot be gated on green CI, and I am not merging it on that basis.
The change itself is small and self-contained (a Timer context manager in
stream2py/util.py plus tests) and was reviewed by reading the diff.

Unblocking this needs the wads uv-CI migration for stream2py — which is
already half-written and sitting uncommitted in the local working tree of this
repo. Once the CI is migrated and green on master, this PR can be re-run and
merged.

thorwhalen added a commit that referenced this pull request Aug 26, 2026
* Migrate to pyproject.toml + the wads uv-CI stub

The repo was still on setup.cfg/setup.py with a `runs-on: ubuntu-18.04`
workflow — a runner label GitHub retired, so jobs queued forever and never ran.
CI has effectively been dead here, which is why #23 could not be gated.

- pyproject.toml (hatchling), version carried over at 1.0.42 to match PyPI;
  requires-python >=3.10 (3.8 is EOL and was the only version the old CI tested)
- .github/workflows/ci.yml is now the 5-line reusable-workflow stub; all config
  lives in [tool.wads.ci.*]
- testpaths points at the package, not a top-level tests/ — this repo's tests
  live in stream2py/tests/ and there are doctests in the modules
- setup.cfg and setup.py removed
- stream2py/utility/__init__.py gains the module docstring D100 wants

42 tests pass locally under the collection CI uses.

* Use the named secrets transport in the stub

The JSON transport (WADS_CI_SECRETS_JSON) is what ci-to-stub emits by default,
but no repo in the fleet is on it yet and the run came back 'action_required'
with zero jobs before anything executed. The named transport is what every
already-migrated i2mint repo runs, so use the proven one here rather than debug
a wads-side transport question inside a CI-revival PR.

stream2py declares no env vars in [tool.wads.ci.env], so PYPI_PASSWORD (an
i2mint org secret) is the only one that needs passing.
@thorwhalen
thorwhalen merged commit 2134b04 into master Aug 26, 2026
12 checks passed
@thorwhalen
thorwhalen deleted the add-timer branch August 26, 2026 08:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant