Skip to content

fix(types): widen canceled Literal[True]=True to Literal[True]|None=None on request types#643

Merged
bokelley merged 2 commits intomainfrom
claude/issue-641-canceled-literal-default
May 10, 2026
Merged

fix(types): widen canceled Literal[True]=True to Literal[True]|None=None on request types#643
bokelley merged 2 commits intomainfrom
claude/issue-641-canceled-literal-default

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

Closes #641

canceled: Literal[True] = True on UpdateMediaBuyRequest and PackageUpdate was a datamodel-codegen misfire from "const": true boolean schema properties. Any buyer who omitted the field — e.g. a routine budget or pacing update — silently triggered irreversible media buy cancellation via the Pydantic default. This PR fixes all four request-type emissions by adding fix_canceled_literal_defaults() to scripts/post_generate_fixes.py, which rewrites the annotation to Literal[True] | None and the default to = None. Wire semantics are preserved: the field still only accepts true when present, and canceled=False remains a Pydantic ValidationError. Response-side canceled: bool | None = False status indicators are out of scope — their defaults are already non-destructive.

What's in the diff

File Change
scripts/post_generate_fixes.py New _CANCELED_FIELD_RE regex + fix_canceled_literal_defaults() wired into main(). Covers 3 target files (4 total emissions). Idempotent: `Literal[True]
src/adcp/types/generated_poc/media_buy/update_media_buy_request.py UpdateMediaBuyRequest.canceled: Literal[True] = True → `Literal[True]
src/adcp/types/generated_poc/media_buy/package_update.py PackageUpdate.canceled: same change
src/adcp/types/generated_poc/bundled/media_buy/update_media_buy_request.py Both inline classes: same change (2 occurrences)
tests/test_canceled_literal_default.py 11 behavioral tests: default-to-None, explicit True accepted, wire payload absent/present, False rejected, regex idempotency

What was tested

  • pytest tests/ -q: 4316 passed, 30 skipped (1 pre-existing network failure test_real_tls_handshake_still_validates_hostname also fails on main)
  • mypy src/adcp/types/generated_poc/media_buy/update_media_buy_request.py src/adcp/types/generated_poc/media_buy/package_update.py: Success, no issues
  • ruff check src/: All checks passed

Nits (not fixed — out of PR scope)

  • inject_literal_discriminator_defaults() already skips bool-valued Literal[True] (has if not isinstance(value, str): continue), so ordering against it is not load-bearing
  • _CANCELED_FIELD_RE hardcodes 4-space indentation — consistent with every other fix in this script; idempotency test catches silent no-ops
  • No bundled-type behavioral test — consistent with rest of test suite's approach to bundled types
  • dx-expert noted: field description could be updated to explicitly document the sentinel pattern ("Set to true to cancel; omit or None to leave unchanged") — considered a follow-up

Pre-PR review

  • code-reviewer: approved — regex matches exactly 4 emissions; idempotency holds; no blockers
  • dx-expert: approved — Literal[True] | None = None correct; if req.canceled: still falsy-safe for None; no migration doc needed; unused import re nit fixed before PR

Triage-managed PR. This bot does not currently iterate on
review comments or PR conversation threads (only on the source
issue). To unblock:

  • Push fixup commits directly: gh pr checkout <num>
    fix → push.
  • Or re-trigger: comment /triage execute on the source
    issue.

See adcp#3121
for context.

Session: https://claude.ai/code/cse_013iJiiNZi9aBGFawGKUNiGw


Generated by Claude Code

bokelley added 2 commits May 10, 2026 13:15
…one on request types (#641)

Omitting canceled from UpdateMediaBuyRequest or PackageUpdate previously
defaulted to True (datamodel-codegen const:true handling), silently canceling
the media buy on every routine update. Adds fix_canceled_literal_defaults()
to post_generate_fixes.py, widens 4 request-type emissions to
Literal[True] | None = None, and adds 11 behavioral tests.

https://claude.ai/code/session_013iJiiNZi9aBGFawGKUNiGw
@bokelley bokelley force-pushed the claude/issue-641-canceled-literal-default branch from e458dda to 06acaea Compare May 10, 2026 17:15
@bokelley bokelley marked this pull request as ready for review May 10, 2026 17:20
@bokelley bokelley merged commit 120ae3b into main May 10, 2026
16 checks passed
@bokelley bokelley deleted the claude/issue-641-canceled-literal-default branch May 10, 2026 17:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(types): Literal[True] = True default on canceled fields silently destroys media buys when buyer omits the field

1 participant