refactor(commands): split ads.py into modular components#611
Conversation
📋 Review summary — all cyclesReviewed locally (
Totals: 0 FIX, 2 SKIP, 0 UNVERIFIED. No blocking issues. CI green (test-and-report 3.9/3.11/3.13 + quality = SUCCESS). Byte-identical-payload invariance holds: single-item and Ready to merge. |
Breaks the 3 156-line direct_cli/commands/ads.py into a command package with type-specific modules, keeping the CLI surface byte-identical. Layout: - ads/_cli.py — thin Click router (group + get/add/update + lifecycle); - ads/objects.py — build_ad_object / build_ad_update_object (pure builders); - ads/batch.py — --from-file / --ads-json row normalization + chunked send; - ads/base.py — shared validation/parsing helpers; - ads/text.py, ads/responsive.py, ads/shopping.py, ads/mobile_app.py, ads/builder.py — per-subtype payload assembly; - ads/__init__.py — re-exports ads, build_ad_object, build_ad_update_object. No CLI surface changes (commands, flags, payloads unchanged). The create_client patchability contract is preserved: the package exposes create_client (re-exported from _cli) and scripts/build_api_coverage_report.py now patches the _cli submodule when a group is a package. Co-Authored-By: Claude <noreply@anthropic.com>
72ce6b5 to
952bd6e
Compare
📋 Review summary — all cyclesLocal review (cycle 1/3) — reviewed locally via PR #611: pure refactor splitting the 3156-line
Verification beyond the reviewers:
Totals: 0 FIX, 0 UNVERIFIED, 1 non-blocking observation (left as-is with rationale). Review complete. Review mode: local — no auto-merge. PR is mergeable/clean and CI is green; merge is yours to trigger. |
📋 Review summary — rebase verification (cycle 1/3, clean)Re-review after rebase + force-push to resolve the main conflict (rebased #611 onto current main incl. merged #609 + WSDL fix). Reviewed locally (
Totals: 0 FIX, 0 UNVERIFIED, 2 non-blocking SKIP. CI green on Byte-identical-payload invariance confirmed post-rebase by Codex smoke probes. Ready to merge. |
Summary
Splits the 3 156-line
direct_cli/commands/ads.py(79 functions/classes) into a command package with type-specific modules, mirroring the campaigns.py refactoring (#602). No CLI surface changes — every command, flag, and emitted payload is byte-identical.Closes #603
Layout
ads/__init__.pyads,build_ad_object,build_ad_update_object,create_clientads/_cli.pyget/add/updateoptions + lifecycle registrationads/objects.pybuild_ad_object/build_ad_update_object— pure item builders shared by single-item + batch pathsads/batch.py--from-file/--ads-jsonrow normalization + chunked sendads/base.pyads/text.pyads/responsive.pyads/shopping.pyads/mobile_app.pyads/builder.pyDesign notes
from direct_cli.commands.ads import ads, build_ad_object, build_ad_update_objectworks as before. The parity gate (COMMAND_WSDL_MAP,STRATEGY_TYPES, nillable handling) is untouched.create_clientpatchability preserved. The package re-exportscreate_client(aliased from_apiin_cli.py);scripts/build_api_coverage_report.pynow patches the_clisubmodule when a group is a package, so the wire-payload capture keeps intercepting the live path.batch.pyimportsadd/updatefrom_cliinside the param-type helpers (the CLI module importsbatchat top level), so no circular import at load time.Verification
pytest tests/test_wsdl_parity_gate.py tests/test_api_coverage.py tests/test_cli.py tests/test_comprehensive.py tests/test_ads_build_ad_object.py tests/test_ads_build_ad_update_object.py→ 371 passed, 6 skipped-m "not integration...", ignoring the pre-existing aiohttp/vcr cassette env breakage) → 2507 passedruff check .→ cleanmypy direct_cli/commands/ads→ no issuesscripts/build_api_coverage_report.py→strict_parity_ok,live_model_parity_ok,schema_parity_okalltrueNote:
tests/test_read_cassettes.py/test_integration_write.pyerror out in this worktree on an unrelatedaiohttp.streams/vcrversion mismatch — pre-existing, not introduced here (they touch noadscode).🤖 Generated with Claude Code