refactor: drop the runtime u8 = int shim; u8 is typing-only - #138
Merged
Merged
Conversation
#137 bound `u8 = int` in an `else` branch of the `TYPE_CHECKING` import, so the checkers saw `types_bits.u8` (`Literal[0..255]`) while the interpreter saw `int`: an invisible divergence. The branch existed only because two expressions evaluated `u8` at runtime: the `sequence: Iterator[u8] | None` annotation on `SMPClient.__init__` (evaluated eagerly on 3.10-3.13) and the first argument of `cast()` in `wrapping_sequence()`. With `from __future__ import annotations`, annotations are stored as strings and never evaluated. `cast()`'s first argument is an ordinary expression, not an annotation, so it is quoted. Nothing binds `u8` at runtime any more, so the `else` branch and its explanatory comment go together. Why not declare `types-bits[rt]` instead: smp itself declares `types-bits<0.3,>=0.2` without the `rt` extra, so the library that defines `u8` treats it as typing-only. The extra only pulls in `annotated-types` (one of pydantic's dependencies, which #136 evicted), and nothing in smpclient validates a `u8` at runtime: `cast()` is a no-op, and the annotation is never read. Verified: `camas check` and `camas matrix` (3.10-3.14) green. A clean `uv pip install .` into a fresh 3.10 venv (what the `transport-extras` CI job does) has no `annotated_types`; `import smpclient` succeeds and `wrapping_sequence()` wraps 255 -> 0, with `u8` unbound at runtime. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Warning
LLM Disclosure
This PR was authored by
claude-opus-5-5[1m]on behalf of @JPHutchins. They asked why #137 shimmedu8rather than declaringtypes-bits[rt], approved the cleaner fix below, and asked for it as its own small PR.Note
Targets
screaming-goblin, per the epic's rule (intercreate/smpmgr#103).#137's
if TYPE_CHECKING: from types_bits import u8/else: u8 = intmeant the checkers sawLiteral[0..255]while the interpreter sawint. This removes theelsebranch:u8now exists only for the type checkers.No new dependency, and no difference between what the checkers see and what runs.
Why this works, and why not
types-bits[rt]u8at runtime. One was theSMPClient.__init__annotation (evaluated eagerly on 3.10–3.13);from __future__ import annotationsnow stores it as a string. The other wascast()'s first argument, which is an ordinary expression, not an annotation, so it is quoted.types-bits<0.3,>=0.2withoutrt, so the library that definesu8treats it as typing-only. The extra would only pull inannotated-types(a pydantic dependency, evicted in refactor(mcuboot): replace pydantic dataclasses with stdlib dataclasses #136) to evaluate objects nothing reads:cast()is a no-op and the annotation is never inspected.Verification
camas check: ruff, pydoclint, mypy, pyright, and tests all green.camas matrix: green on 3.10, 3.11, 3.12, 3.13, 3.14.uv pip install .into a fresh 3.10 venv (what thetransport-extrasjob does) has noannotated_types.import smpclientsucceeds,wrapping_sequence()wraps 255 → 0, andu8is unbound at runtime.🤖 Generated with Claude Code