refactor(commands): make_get_command factory for the v5 get skeleton (#582) - #586
Conversation
…582) Dedup audit (#582, child of epic #584). Introduces direct_cli/commands/_get.py::make_get_command — the shared body for the repeated v5 ``get`` skeleton (resolve fields → build SelectionCriteria → common params → dry-run print or post + format), modeled on the lifecycle factory. Migrates the five simplest get-commands onto it: advideos, businesses, negativekeywordsharedsets, vcards, turbopages. The factory absorbs the per-resource variation through small knobs: default_fields_key, ids_help/ids_required, extra_options (turbopages' --bound-with-hrefs), and an optional criteria_builder callback (advideos' string Ids, turbopages' BoundWithHrefs). CLI surface preserved 1:1 — --help option order and --dry-run payloads verified byte-identical for all five. Patchability is genuinely preserved (a strict improvement over the lifecycle factory, whose closure-pinned create_client silently bypasses patches): the new api.resolve_module_create_client re-reads create_client from the live command module at call time, so patch.object(<module>, "create_client", ...) — used by unit tests and the coverage wire-payload capture — intercepts the live path. This is what keeps the schema-parity coverage gate green. Remaining get-command groups and the sibling helpers are tracked as follow-ups under epic #584. Full offline suite green (2535 passed). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@claude @codex review. Focus on critical issues: bugs, security vulnerabilities, logical errors, data loss risks, performance problems. This is a dedup refactor (#582) that introduces a make_get_command factory and migrates 5 simple get-commands; it must preserve the CLI surface 1:1 — pay special attention to (a) byte-level divergence in --help option order, i18n help keys, or --dry-run payloads vs pre-refactor; (b) the dynamic create_client resolution via api.resolve_module_create_client (patchability for tests + coverage wire-payload capture); (c) the --help option ordering produced by applying extra_options/--ids around get_options. Scope is intentionally Group 1 only — Groups 2-4 and sibling helpers are tracked as follow-ups #587/#588/#589. Do NOT nitpick style, naming, or formatting. |
|
Claude finished @axisrow's task in 5m 0s —— View job Review:
|
|
Codex Review: Didn't find any major issues. Can't wait for the next one! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Review of #586 noted that the migrated get-commands build the client after the --dry-run guard (matching the lifecycle factory and CLAUDE.md), so `get --dry-run` no longer resolves credentials. That divergence is intentional and consistent with the sibling factory; this test pins it via `_dry_run` (empty env), so credential resolution cannot silently creep back into the dry-run path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Thanks @claude @codex. Triage: Item 1 — dry-run no longer resolves credentials. Confirmed and intentional: the factory builds the client after the Minor notes (non-blocking, left as-is):
Codex: no issues. Full offline suite green (2536 passed), ruff clean. Proceeding to merge once CI is green. |
|
To use Codex here, create an environment for this repo. |
|
Claude finished @axisrow's task in 37s —— View job Triage confirmed — resolution is sound ✅Thanks @axisrow. I checked the lock-in commit Item 1 — dry-run no longer resolves credentials. Agreed on all points:
Minor notes — agree, leave as-is:
No remaining concerns from my side — no critical bugs, CLI surface preserved 1:1, and the |
Closes #582. Part of epic #584 (аудит дублирования кода).
Что сделано
Введена фабрика
direct_cli/commands/_get.py::make_get_command— общий скелет тела v5get-команды (разрешить поля → собратьSelectionCriteria→ общие params → dry-run печать или post + format), по образцуmake_lifecycle_command. На неё переведены 5 самых простых get-команд:advideos,businesses,negativekeywordsharedsets,vcards,turbopages.Вариативность ресурсов фабрика покрывает небольшими «ручками»:
default_fields_key,ids_help/ids_required,extra_options(--bound-with-hrefsу turbopages) и опциональныйcriteria_builder(строковыеIdsу advideos,BoundWithHrefsу turbopages).Patchability — строго лучше lifecycle-фабрики
Lifecycle-фабрика захватывает
create_clientв замыкании при загрузке модуля, из-за чегоpatch.object(module, "create_client")не перехватывает live-путь (латентный дефект; lifecycle-команды покрыты только через--dry-run). Здесь это исправлено: новыйapi.resolve_module_create_clientперечитываетcreate_clientиз живого модуля команды в момент вызова, поэтомуpatch.object(<module>, "create_client", ...)— используемый юнит-тестами и coverage wire-payload capture (scripts/build_api_coverage_report.py) — перехватывает live-путь. Именно это держит зелёным schema-parity coverage-гейт.Байт-идентичность (проверено)
--help(порядок опций, i18n-ключи) и--dry-runpayload байт-идентичны для всех 5 команд (сверка с эталоном до рефакторинга, включая строковые vs целочисленныеIdsиBoundWithHrefs).test_read_cassettes.py) для этих 5 команд проходят — live-путь не изменился./simplify: 4 ревьюера; применён выносresolve_module_create_clientвapi.py, приватизация_default_ids_criteria, удаление неиспользуемогоservice; декларативный criteria-механизм отложен в follow-up под реальные требования групп 2-3 (YAGNI).Follow-up (под эпиком #584)
Остальная миграция вынесена отдельными issue (расширяют фабрику под свои паттерны с собственной верификацией байт-идентичности):
*FieldNames+add_criteria_csv): adextensions, adimages, leads, retargeting, sitelinks, feeds, clients, agencyclients.enforce_criteria_array_limits): dynamicads, smartadtargets, dynamicfeedadtargets, bids, bidmodifiers, reports, keywordbids.make_set_bids_command), feat(ads get): add --text-ad-fields for type-specific field retrieval #13 (execute_add).Diff: +198 / −214 (нетто −16).
🤖 Generated with Claude Code