Skip to content

feat(translation): list known keys in TranslationMap KeyError#768

Merged
bokelley merged 3 commits into
mainfrom
bokelley/issue-453-translation-map-typed-credentials
May 21, 2026
Merged

feat(translation): list known keys in TranslationMap KeyError#768
bokelley merged 3 commits into
mainfrom
bokelley/issue-453-translation-map-typed-credentials

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

Summary

When TranslationMap.to_upstream / to_adcp miss, include the full set of known keys in the KeyError message so adopters debugging a typo or stale mapping see the fix without instrumenting the call site.

Before:

KeyError: "unknown AdCP key: 'activ'"

After:

KeyError: "unknown AdCP key 'activ'; known keys: ['active', 'archived', 'paused']"

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 (existing KeyError-raise tests tightened to assert the known-keys list)
  • ruff check src/ clean
  • mypy src/adcp/decisioning/translation.py clean
  • Pre-commit hooks (black, ruff, mypy, bandit) green

Closes #453.

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>
aao-ipr-bot[bot]
aao-ipr-bot Bot previously approved these changes May 21, 2026
Copy link
Copy Markdown

@aao-ipr-bot aao-ipr-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-98sorted(self._forward.keys(), key=repr) is the right defensive sort for Generic[A, U] where keys may not be mutually comparable. !r formatting clean.
  • Exception type unchanged. KeyError still 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_unknown cases now assert the bad key plus every known key appears in the message. Existing pytest.raises(KeyError) retained.
  • Grepped repo for "unknown AdCP key:" / "unknown upstream key:" — no stale callers depend on the old wording.
  • TranslationMap is exported from adcp.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 (pytest 34/34, ruff, mypy, pre-commit).

Follow-ups (non-blocking — file as issues)

  • code-reviewer noted KeyError.__str__ wraps args[0] in another repr(), so adopters see double-quoted output. Pre-existing behavior — worth a future custom-exception subclass or a multi-arg KeyError if anyone touches this file again.

LGTM. Closes #453.

bokelley and others added 2 commits May 21, 2026 08:35
`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>
Copy link
Copy Markdown

@aao-ipr-bot aao-ipr-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,97sorted(..., key=repr) is the right defensive choice. sorted() on heterogeneous keys (mixed str / int / Enum) raises TypeError; sorting on repr sidesteps that and gives a deterministic message order. Happy path and KeyError type 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:124 regex ^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.py clean. Pre-commit checks all green.

Minor nits (non-blocking)

  1. Sorted-keys could be cached at construction. TranslationMap is 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 that known reflects exactly the dict snapshot at miss time. Not worth changing.

Approving. Clean close for #453 — the rest of that triage is already in #464.

@bokelley bokelley merged commit 7545424 into main May 21, 2026
17 checks passed
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.

feat(server): createUpstreamHttpClient + createTranslationMap (translator pattern helpers)

1 participant