fix(codegen): preserve regenerated response aliases#854
Merged
Conversation
There was a problem hiding this comment.
LGTM. Follow-ups noted below. Replaces the eager getattr(_g, "FooResponse1", _g.FooResponse) fallback with a lazy try/except helper — the right shape now that regenerated _generated.py carries concrete *Response1 arms instead of *Response1 = *Response shims.
Things I checked
- Lazy fallback semantics (
src/adcp/types/aliases.py:106-110):_generated_aliasevaluates the fallback only onAttributeError. Old form forced eager evaluation of_g.FooResponseregardless. New form is import-time safe even when the parent union goes away upstream. - Regression pin (
tests/test_code_generation.py:32-44): regexgetattr\(_g,\s*"[^"]+",\s*_g\.[A-Za-z_]+\s*\)matches only the attribute-fallback form, not the new string-fallback_generated_aliascalls. Sound guard. - Semantic alias resolution (
tests/test_code_generation.py:54-104): pinsActivateSignalSuccessResponse → ActivateSignalResponse1,AcquireRightsAcquiredResponse → AcquireRightsResponse1,CreateMediaBuySubmittedResponse → CreateMediaBuyResponse3, plus six more. This is the actual fix — the original bug was these collapsing silently to the parent union. - Wire-shape orderings (
ad-tech-protocol-expertverified against upstreamschemas/source/): AcquireRights oneOf is[Acquired, PendingApproval, Rejected, Error], matchingaliases.py:642-652(1→4). CreateMediaBuy[Success, Error, Submitted]matchesaliases.py:461-479. UpdateMediaBuy same ordering matchesaliases.py:607-614. ClaimTyperelocation (_generated.py:202-209): upstreamverify-brand-claim-request.jsondefinesclaim_typeas the singular task's discriminator, so the new import location is spec-correct. No external consumers of the old location insrc/,tests/, orexamples/.extract_exports_from_moduleAnnAssign extension (scripts/consolidate_exports.py:38-46): correctly picks upFoo: TypeAlias = Bardeclarations the post-generate fixer emits. Unit test attests/test_code_generation.py:46-52covers it._sync_protocol_envelope_import(scripts/post_generate_fixes.py:58-74): consolidates two prior call sites inrestore_response_variant_aliases. Insertion is gated on actualProtocolEnvelopereferences in the source, so the import doesn't get added speculatively. Regeneratedacquire_rights_response.py:5-9andcreate_media_buy_response.py:5-9confirm the placement.
Follow-ups (non-blocking — file as issues)
UpdateMediaBuyResponse1/2/3coercion parity. The PR adds_ergonomic.pypatches forCreateMediaBuyResponse1.packagesandmedia_buy_status. The three update_media_buy arms have the same two fields plusaffected_packages: Sequence[Package]and currently get no ergonomic coercion. Percode-reviewerthis is a pre-existing gap, not a regression — but the same shape, same call ergonomics, should land together.- Type erasure through
_generated_alias(src/adcp/types/aliases.py:106). ReturningAnymeansActivateSignalSuccessResponse: TypeAlias = ActivateSignalResponse1isAnyto mypy on the public surface. The file's# mypy: disable-error-code="valid-type"header masks the diagnostic but doesn't restore concrete typing. Consider anif TYPE_CHECKING:branch that binds the alias to the known fallback class statically while keeping runtime lazy. - Duplicate
ClaimTypeinverify_brand_claims_response.py:21. Perad-tech-protocol-expert: pydantic generates a separately-scopedClaimTypeenum inside the plural response module. Adopters doingisinstance(result.claim_type, ClaimType)against the public re-export from the singular request module will silently fail (same string values, different class objects). Codegen-level dedup, not in scope here. - Forward-compat on
VerifyBrandClaimResponse(generated_poc/brand/verify_brand_claim_response.py:59). The Success | Error union has noDiscriminator()callable and noUnknownStatusfallback arm. A new upstream oneOf arm will hitValidationErroron adopter deserialization. Same caveat applies toCreateMediaBuyResponse1.media_buy_status—coerce_to_enumreturns the raw string on miss, which strict pydantic rejects.
Minor nits (non-blocking)
_generated_aliasdocstring (src/adcp/types/aliases.py:106-110). The helper has no docstring explaining why the helper exists or thatfallback_nameis the parent-union case. Two lines lifted from the PR body would prevent future churn.- Branch (c) in
_sync_protocol_envelope_import(scripts/post_generate_fixes.py:74). The raw-prepend path fires only when neitherfrom __future__ import annotationsnorAdcpVersionEnvelopeexists in the source — whichpython-expertconfirmed never happens ongenerated_poc/files. Defensive but dead. Either drop or add a# pragma: no coverhint.
Approving on the strength of the four new regression tests plus the upstream-schema oneOf verification.
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.
Supersedes #824 using an in-repository branch so required CodeQL and Argus review checks can run with normal repository permissions.
Includes the original generated-alias fix from #824 plus follow-up fixes:
Validation run locally: