feat(typing): achieve full strict typing compliance across OWNd (mypy --strict) - #36
Conversation
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
Passing on this one: a strict-typing migration across the parser and the connection is outside what I can judge, and the risk in a change this size isn't a wrong annotation, it's behaviour that shifts by accident. That needs someone who can run the conformance corpus and read the diff as code. @xtimmy86x or @fedem95 would be the right eyes here, or @mvalla if he's willing, since the golden vectors are partly his. I'll say the one thing I can: OWNd is what every installation runs, including the 0.7.x line my own house is on, so I'd want this to land on its own, after #35, rather than stacked under anything else. |
034c480 to
9c122ec
Compare
|
@Interstellar0verdrive — fair call, and the right one: the risk in a diff this size is behaviour that moves by accident, so let me put the evidence you'd want a reviewer to have in front of them, and then turn your request into something that runs on its own. 1. The diff is a third of what GitHub shows
Both read as intended with whitespace hidden: #35 2. What #36 changes, read as codeAnnotations, plus three kinds of guard on paths where the value could already not be
No control-flow change, no frame text change. 3. The conformance corpus, runAgainst the #35 + #36 stack, on a clean checkout of MyHOME
The full suite is what found the two real problems, neither of them in #36: the retry flap @xtimmy86x reported on #35 (fixed in 4. Your request, as CI#37 adds two jobs to OWNd's CI, each with the PR's checkout installed in place of the release MyHOME pins: the golden corpus and smoke gates (about a minute), and MyHOME's full suite (about four). From then on "someone who can run the conformance corpus" is every PR, before anyone reads it. 5. Landing order and release riskAgreed on both counts. #36 stays stacked on #35 only as GitHub sees it — #35 lands first and alone, #36 rebases and lands second, nothing else under either. On the 0.7.x line: MyHOME pins What would move this: @xtimmy86x, a second look at #35 with |
|
Thanks for the typing work. I checked commit There is one typing issue I would like addressed before approving: For example: await session.send(OWNLightingCommand.switch_on("11"))Mypy rejects this with: Could you update This is an annotation compatibility issue rather than a runtime failure, but it matters for consumers now that the library exposes its types through |
…pass Review of 9c122ec (OpenWebNet-HA#36, @xtimmy86x): OWNCommandSession.send(), _locked_send() and send_to_gateway() were annotated `message: str`, while the wire path is `str(message).encode()` and MyHOME passes OWNCommand builders and OWNMessage.parse() results. With py.typed shipped, that made a working call a type error for every consumer: Argument 1 to "send" has incompatible type "OWNLightingCommand"; expected "str" The three signatures now take `str | OWNMessage`. tests/typing/consumer_send.py is the consumer's side of the contract: the calls MyHOME really makes (raw frame, builder, parsed command, parsed message, one-shot helper), checked by `mypy --strict` in CI's quality job and by tests/test_typing_consumer.py under pytest. It fails five ways on the previous annotation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
@xtimmy86x — agreed, and thanks for checking with the corpus. Fixed in Signatures — Consumer typing check —
On the previous annotation it fails with exactly your message, five times; on Rebased nothing — this is one commit on top of |
xtimmy86x
left a comment
There was a problem hiding this comment.
Rechecked commit 0fe2938: my previous concern is resolved. The updated str | OWNMessage signatures correctly cover raw frames and command objects, and the consumer typing checks are now included in CI.
All six checks are green, including strict mypy validation of the library and consumer examples. The follow-up changes do not alter the runtime send logic.
No remaining blockers from my review. Approved, thanks for addressing this.
The merge-base changed after approval.
|
@GreenGrassBlueOcean I submitted the approval again, but GitHub still blocks the merge, marking it as stale because the merge base changed. The branch is currently 4 commits ahead and 1 behind My technical assessment remains positive; this is about resolving the review/merge-base state. |
The merge-base changed after approval.
e80dff3
into
OpenWebNet-HA:feat/session-is-open
…pass Review of 9c122ec (OpenWebNet-HA#36, @xtimmy86x): OWNCommandSession.send(), _locked_send() and send_to_gateway() were annotated `message: str`, while the wire path is `str(message).encode()` and MyHOME passes OWNCommand builders and OWNMessage.parse() results. With py.typed shipped, that made a working call a type error for every consumer: Argument 1 to "send" has incompatible type "OWNLightingCommand"; expected "str" The three signatures now take `str | OWNMessage`. tests/typing/consumer_send.py is the consumer's side of the contract: the calls MyHOME really makes (raw frame, builder, parsed command, parsed message, one-shot helper), checked by `mypy --strict` in CI's quality job and by tests/test_typing_consumer.py under pytest. It fails five ways on the previous annotation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e, test) master stored five files with CRLF - .gitignore, LICENSE, __main__.py, connection.py, message.py - next to an LF majority, and connection.py mixed the two within the file. Any edit from a differently configured editor then rewrote the whole file: OpenWebNet-HA#35 rendered as +248/-218 for a +38/-8 change, OpenWebNet-HA#36 as +691/-615 for +324/-248, and a reviewer passed on both for that reason. `* text=auto eol=lf`, `git add --renormalize .`, and tests/test_line_endings.py so a CR that bypasses the clean filter fails the suite instead of the next reviewer. That test found one such path straight away: validate_corpus.py rewrote tests/golden/corpus.json with the platform newline on every run, so any Windows checkout that ran the suite had a CRLF corpus.json waiting to be committed. It now writes LF. Every byte other than line endings is unchanged: `git diff --ignore-cr-at-eol` shows only the two new files and the one-line newline argument. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
For the record: this merged into |
feat(typing): strict typing across OWNd — re-land of #36 on master
…e, test) master stored five files with CRLF - .gitignore, LICENSE, __main__.py, connection.py, message.py - next to an LF majority, and connection.py mixed the two within the file. Any edit from a differently configured editor then rewrote the whole file: OpenWebNet-HA#35 rendered as +248/-218 for a +38/-8 change, OpenWebNet-HA#36 as +691/-615 for +324/-248, and a reviewer passed on both for that reason. `* text=auto eol=lf`, `git add --renormalize .`, and tests/test_line_endings.py so a CR that bypasses the clean filter fails the suite instead of the next reviewer. That test found one such path straight away: validate_corpus.py rewrote tests/golden/corpus.json with the platform newline on every run, so any Windows checkout that ran the suite had a CRLF corpus.json waiting to be committed. It now writes LF. Every byte other than line endings is unchanged: `git diff --ignore-cr-at-eol` shows only the two new files and the one-line newline argument. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Summary
This PR completes the full strict typing migration (
mypy --strict) across all modules ofOWNd, satisfying Home Assistant Platinum quality scale standards (strict-typing) and providing complete type safety for library consumers (includingMyHOME).Note
Stacked on #35. This PR's base is
feat/session-is-open(a mirror of #35's head,54f61e9, on the org repo), so the diff and commit list here are the typing work only. It lands after #35, on its own: when #35 merges and that mirror branch is deleted, GitHub retargets this PR tomasterautomatically. Nothing else is stacked on it.Key Changes
Strict Type Annotations Across All Modules:
OWNd/connection.py: Fully typedOWNSession,OWNEventSession,OWNDiscoverySession, andOWNGateway. Added type narrowing for HMAC/legacy authentication nonces, proper optionality handling on socket streams and callbacks, and precise return types.OWNd/discovery.py: Annotatedscan(), SSDP, and mDNS discovery packet parsing, interfaces, and dispatchers.OWNd/__main__.py: Annotated CLI entry points and argument parsers.OWNd/message.py:OWNScenarioEvent,OWNLightingEvent,OWNAutomationEvent,OWNHeatingEvent,OWNAlarmEvent,OWNAuxEvent,OWNGatewayEvent,OWNCENEvent,OWNSceneEvent,OWNEnergyEvent,OWNDryContactEvent,OWNCENPlusEvent,OWNSoundEvent).OWNStatusRequest,OWNLightingCommand,OWNAutomationCommand,OWNHeatingCommand,OWNAlarmCommand,OWNAVCommand,OWNGatewayCommand,OWNEnergyCommand,OWNSoundCommand,OWNDryContactCommand).where,what,dimension, and parameter dictionaries.Strict Mypy Configuration (
pyproject.toml):strict = trueandwarn_unused_configs = true.arg-type,assignment,index,operator,return,return-value,truthy-function,union-attr,var-annotated).implicit_optional = true.dateutil.*,defusedxml.*,serial_asyncio.*).Packaging & Verification:
OWNd/py.typedis present and packaged in wheel and sdist distributions.scripts/verify_library_standards.py.Validation
mypy OWNd: 0 errors across all 10 source files.mypy --strict OWNd: 0 errors across all 10 source files.pytest tests: 627 passed (100% pass rate).ruff check: All checks passed.