Skip to content

chore(release): 5.4.0 - mock fidelity - #112

Merged
little-did-I-know merged 2 commits into
mainfrom
release/v5.4.0
Jul 26, 2026
Merged

chore(release): 5.4.0 - mock fidelity#112
little-did-I-know merged 2 commits into
mainfrom
release/v5.4.0

Conversation

@little-did-I-know

Copy link
Copy Markdown
Owner

Cuts 5.4.0 — the mock fidelity release. Version bump plus the changelog header rename; no code changes.

Why MINOR

[Unreleased] carried a single ### Added section and no ⚠️ Breaking Changes. Everything in it is additive: new SignalSpec fields appended at the end of the dataclass (so positional construction is unchanged), new keyword-only parameters with defaults on reject_if_invalid, and an empty error queue that returns '+0,"No error"' byte-identical to the stub it replaced.

What ships

The mock can now misbehave the way real hardware does — the point being that this project has no physical instruments, so the mock is the instrument, and a mock that can only succeed cannot test the code whose job is to notice failure.

  • A real SCPI error queue behind SYST:ERR?, cleared by *CLS and *RST. FunctionGenerator.get_error() and PowerSupply.get_error() go from timing out entirely to answering; DataLogger.get_error() can finally report something other than health.
  • Out-of-range parameters are rejected across the Siglent scope, PSU and AWG personalities plus the Tektronix and LeCroy dialects — accepted by the transport, ignored, and queued as -222, which is what an instrument actually does. Unimplemented commands still time out, so the wire-form conformance net is untouched.
  • SignalSpec gained baseline drift, glitches and edge ringing, all default-off, so measurement code can be exercised against imperfect signals instead of mathematically clean ones.

Verification

  • Both version sources read 5.4.0, enforced by tests/test_version_consistency.py.
  • docs/about/changelog.md regenerated and verified byte-identical to CHANGELOG.md.
  • PyPI summary 387/512 chars — the check that broke the v3.2.0 publish.
  • Changelog structure: exactly one ## [Unreleased], ## [5.4.0] - 2026-07-26 present, one Added section, no breaking-changes section, 5.3.0 untouched.
  • Full suite: 1774 passed, 19 skipped, 0 failed.
  • python -m build produces both artifacts at 5.4.0 with no deprecation warnings; twine check PASSED on the wheel and the sdist.
  • All four touched files confirmed BOM-free. Worth stating because the first bump attempt used PowerShell's Set-Content -Encoding utf8, which writes a BOM and corrupted pyproject.toml for TOML parsers; it was caught, reverted, and redone through Python with explicit encoding.

Known limitations carried into this release

Recorded in the feature PR rather than dropped, and none blocking:

  • A pre-existing float64 duty-threshold artifact in the square-wave generator misplaces a few level flips at frequencies landing exactly on a duty boundary — including 1 kHz at 100 kS/s, this project's most common test signal. Ringing then faithfully rings on each spurious edge, amplifying it. Verified independent of the feature work (it reproduces with ringing off, and divergence is zero at off-boundary frequencies). Not fixed here because changing the base generator alters synthesised output and would risk the default-off guarantee.
  • The error queue is unbounded, and in scope mode undrainable over the wire — real instruments cap at ~20 entries and push -350,"Queue overflow".
  • Malformed values still raise out of the transport (C1:VDIV abcValueError) rather than queueing -104,"Data type error".
  • No ringing_amplitude knob; magnitude is hardcoded at 50% of the step, giving ~90% first-sample overshoot at the tested parameters.
  • tests/test_server_ownership.py::test_watcher_released_on_abnormal_disconnect is flaky — it lost a race on the Python 3.10 runner during this branch's CI and passed on re-run, having passed on five other interpreter versions in the same run. Pre-existing and unrelated to this work, but worth de-flaking.

After merge

Publishing fires when the GitHub release is created (publish.yml on release: published, trusted publishing), tagged v5.4.0. Create it with gh release create --target <full-40-char-sha> — not by pushing the tag, since a tag push lets build-executables.yml create the release as github-actions[bot] and GitHub suppresses workflow triggers for bot-raised events, which is how v4.1.0 silently never reached PyPI. The full SHA is required; an abbreviated one is rejected with HTTP 422.

The test monkeypatched read_state with a raising stand-in, opened a websocket
and closed it immediately, then asserted the handler had reached read_state.
But the handler dispatches read_state onto the session worker thread via
session.submit() (stream.py:98), so it runs asynchronously relative to the
handshake -- closing right away raced that dispatch and the job could never run.

That race failed CI on whichever interpreter happened to lose it: Python 3.10 on
one run and 3.11 on the next, each time passing on every other version, and
passing on re-run. It blocked two consecutive runs including a release PR.

Wait for the stand-in to actually fire before closing the socket. The timeout
keeps a genuine regression from hanging the suite rather than failing it.
@little-did-I-know
little-did-I-know merged commit f3c05cb into main Jul 26, 2026
29 checks passed
@little-did-I-know
little-did-I-know deleted the release/v5.4.0 branch July 26, 2026 01:18
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