feat(translation): list known keys in TranslationMap KeyError#768
Merged
bokelley merged 3 commits intoMay 21, 2026
Merged
Conversation
When `to_upstream` / `to_adcp` miss, surface the full set of known keys in the exception so adopters debugging a typo or stale mapping see the fix without instrumenting the call site. dx-expert flagged this as the one outstanding nit from the #453 triage; the rest of that issue is resolved by #464. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
LGTM. Clean dx fix landing the last #453 follow-up — error messages get more useful, no API shape change, no perf concern on enum-sized maps.
Things I checked
src/adcp/decisioning/translation.py:84-85,97-98—sorted(self._forward.keys(), key=repr)is the right defensive sort forGeneric[A, U]where keys may not be mutually comparable.!rformatting clean.- Exception type unchanged.
KeyErrorstill raised on miss; default-passthrough behavior at L82-L83 / L95-L96 unchanged. Happy path is unchanged. tests/test_upstream_helpers.py:60-76— both_raises_on_unknowncases now assert the bad key plus every known key appears in the message. Existingpytest.raises(KeyError)retained.- Grepped repo for
"unknown AdCP key:"/"unknown upstream key:"— no stale callers depend on the old wording. TranslationMapis exported fromadcp.decisioning(__init__.py:225,416). Message-string change is not part of the API contract; exception type, args count, and raise conditions are all preserved.- Conventional commit
feat(translation):matches the dx-improvement framing; no!needed since no breaking change. - PR test plan: all four boxes checked (
pytest34/34,ruff,mypy, pre-commit).
Follow-ups (non-blocking — file as issues)
code-reviewernotedKeyError.__str__wrapsargs[0]in anotherrepr(), so adopters see double-quoted output. Pre-existing behavior — worth a future custom-exception subclass or a multi-argKeyErrorif anyone touches this file again.
LGTM. Closes #453.
…anslation-map-typed-credentials
`git merge origin/main` produces "Merge remote-tracking branch 'origin/main' …", which the conventional-commits skip regex didn't match — only `Merge branch '<name>'` was covered. Validator then flagged the merge commit as a malformed conventional commit and failed the check. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
LGTM. Right surface to fix: the message string, not the exception type — adopters' except KeyError: blocks keep working, only the human-readable text gets more useful.
Things I checked
translation.py:84,97—sorted(..., key=repr)is the right defensive choice.sorted()on heterogeneous keys (mixedstr/int/Enum) raisesTypeError; sorting onreprsidesteps that and gives a deterministic message order. Happy path andKeyErrortype are untouched.- Cost is on the miss path only. Translation maps in this SDK are tiny (channel names, delivery types — a dozen entries each), and the miss path exists to help adopters debug typos, not to be hot. No DoS surface here.
ci.yml:124regex^Merge ([0-9a-f]+ into [0-9a-f]+|(remote-tracking )?branch '[^']+')— anchored, structural-suffix-required, correctly skips the three shapes named in the comment and still rejects `Merge pull request …`, `Merge: add foo`, `Merging …`. Justified by the merge commit on this PR itself.test_upstream_helpers.py:60-76— assertions test membership of fixture keys in the message rather than full-string equality. Appropriately loose coupling to the fixture; won't bit-rot on cosmetic message tweaks.- PR description test plan: all four boxes checked, including
mypy src/adcp/decisioning/translation.pyclean. Pre-commit checks all green.
Minor nits (non-blocking)
- Sorted-keys could be cached at construction.
TranslationMapis immutable post-__init__, so the sorted key list could be computed once and stored — but the saving is negligible against the__slots__churn, and you'd lose the property thatknownreflects exactly the dict snapshot at miss time. Not worth changing.
Approving. Clean close for #453 — the rest of that triage is already in #464.
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.
Summary
When
TranslationMap.to_upstream/to_adcpmiss, include the full set of known keys in theKeyErrormessage so adopters debugging a typo or stale mapping see the fix without instrumenting the call site.Before:
After:
This is the one outstanding dx-expert nit from the #453 triage. The rest of that issue (typed dataclass auth variants, generic-class translation map, per-call
auth_context) is already resolved by #464 — closing #453 alongside this PR.Test plan
pytest tests/test_upstream_helpers.py -q— 34/34 pass (existingKeyError-raise tests tightened to assert the known-keys list)ruff check src/cleanmypy src/adcp/decisioning/translation.pycleanCloses #453.