Skip to content

refactor: migrate Group-4 get commands to make_get_command (#588)#601

Merged
axisrow merged 1 commit into
mainfrom
refactor/issue-588-group4-clean-fits
Jun 20, 2026
Merged

refactor: migrate Group-4 get commands to make_get_command (#588)#601
axisrow merged 1 commit into
mainfrom
refactor/issue-588-group4-clean-fits

Conversation

@axisrow

@axisrow axisrow commented Jun 20, 2026

Copy link
Copy Markdown
Owner

Что

Завершает мигрируемую поверхность #588 — переводит 5 «сложных» Group-4 get-команд на общую фабрику make_get_command, переиспользуя только её существующие хуки (новых параметров фабрики нет):

Команда Хуки
adgroups get criteria_limits + 8 вложенных *FieldNames; конфликт --status/--statuses — в criteria_builder
keywords get criteria_limits + 2 вложенных; тот же конфликт в builder
creatives get require_criteria_message + 4 вложенных
strategies get require_criteria_message + 16 вложенных (крупнейший набор)
audiencetargets get criteria_limits + длинное require-сообщение, без вложенных

Фикс порядка проверок в фабрике

Вложенные *FieldNames теперь парсятся (и их UsageError на пустой CSV поднимается) до enforcement criteria-лимитов и до require-guard'а — как было во всех hand-rolled командах. --<nested> "" вместе с «нет фильтра» или с over-limit массивом отдаёт ошибку вложенного поля, а не require/limit. Парсенный dict по-прежнему мёрджится после common-params, поэтому порядок ключей payload не меняется. Побочно это восстанавливает исходный порядок nested-before-limits для уже мигрированного bidmodifiers get. Добавлен регрессионный тест в test_dry_run.

Инварианты

--help (порядок опций, все вложенные опции, choice/default у --is-archived), --dry-run payload'ы и edge-кейсы порядка ошибок (empty-nested vs no-filter и vs over-limit) — байт-идентичны, проверено на 33 эталонах через CliRunner, снятых с pre-migration дерева (git stash). Как и во всех прошлых миграциях фабрики, клиент резолвится только на live-пути → --dry-run для этих команд теперь token-free test seam.

Carve-out'ы (осознанно hand-rolled, задокументированы в _get.py)

  • ads getTextAdFieldNames всегда эмитится с per-field дефолтом (как у carved-out keywordbids); фабрика делает provided-only проекции.
  • campaigns get--fields через _parse_csv_option отвергает пустой CSV вместо silent-fallback к дефолтным FieldNames.

Проверки

  • Полный офлайн-набор 2554 passed (+2 новых регресс-теста), ruff чисто, все гейты зелёные (dry_run, api_coverage, read_cassettes, wsdl_parity_gate, i18n, comprehensive).
  • /simplify (4 линзы: reuse / simplification / altitude / byte-identity) — altitude поймал инверсию nested-vs-limits, исправлено; byte-identity подтвердил остальное идентичным.
  • Net −278 строк.

Closes #588

🤖 Generated with Claude Code

Move the five migratable "complex" get commands onto the shared
make_get_command factory, reusing only its existing hooks (no new
factory parameter):

- adgroups get, keywords get: criteria-limit + 8/2 nested *FieldNames;
  the --status/--statuses mutual-exclusion guard lives in the per-module
  criteria_builder.
- creatives get: require-filter + 4 nested.
- strategies get: require-filter + 16 nested (the largest set so far).
- audiencetargets get: criteria-limit + long require-filter message,
  no nested.

Factory ordering fix: nested *FieldNames are now parsed (and their
provided-but-empty-CSV UsageError raised) before both criteria-limit
enforcement and the empty-criteria require guard, matching the order
every hand-rolled command used. A "--<nested> ''" combined with no
filter or an over-limit array reports the nested error, not the
require/limit one. The parsed dict is still merged after the common
params, so payload key order is unchanged; this also restores the
pre-factory nested-before-limits order for the migrated bidmodifiers
get. A new test_dry_run regression test pins the precedence.

--help, --dry-run payloads and the error-precedence edge cases are
byte-identical, verified against 33 pre-migration baselines captured
via CliRunner from the pre-migration tree. As with every prior factory
migration, --dry-run is now a token-free test seam for these commands.

ads get and campaigns get stay hand-rolled as documented carve-outs
(see _get.py): ads always emits TextAdFieldNames with a per-field
default (like keywordbids); campaigns' --fields rejects an explicitly
empty CSV rather than falling back to the default FieldNames.

Net -278 lines.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@axisrow

axisrow commented Jun 20, 2026

Copy link
Copy Markdown
Owner Author

@claude @codex review. Focus on critical issues: bugs, security vulnerabilities, logical errors, data loss risks, performance problems. Do NOT nitpick style, naming conventions, minor formatting, or subjective preferences — only flag issues that could break functionality or cause real harm in production.

@claude

claude Bot commented Jun 20, 2026

Copy link
Copy Markdown

Claude finished @axisrow's task in 2m 52s —— View job


Code Review — Group-4 get migration to make_get_command

  • Read the diff vs origin/main
  • Review _get.py factory ordering change
  • Review migrated command modules (adgroups, keywords, creatives, strategies, audiencetargets)
  • Check regression test coverage
  • Post review

Reviewed for the requested focus only (bugs, logic errors, data-loss, performance). No critical issues found — this is a faithful, behavior-preserving migration.

Factory ordering change (_get.py) — correct

The move of nested-*FieldNames parsing to before enforce_criteria_array_limits and the require_criteria_message guard (_get.py:197-208) is the right fix and matches every pre-migration hand-rolled body:

  • The parsed dict is still merged after build_common_params (_get.py:218-219), so payload key order is unchanged. ✅
  • if parsed_nested: replacing if nested_specs: is safe — parse_nested_field_names returns {} when nothing was provided, and params.update({}) was already a no-op, so the result is identical. ✅
  • Error precedence now resolves to the nested error for --<nested> "" + over-limit and --<nested> "" + no-filter, pinned by the new test_get_empty_nested_field_names_precedes_criteria_limit regression test. ✅

Per-module migrations — faithful

I traced each criteria_builder against its original inline body:

  • adgroups / keywords — the --status/--statuses mutual-exclusion guard correctly lives inside the criteria_builder (adgroups.py:427, keywords.py), which runs before nested parsing — preserving the original "mutual-excl first" ordering. criteria_limitsrequire ordering preserved.
  • keywords nested error message — the old bespoke UsageError ("Provide a non-empty comma-separated <key> list.") is byte-identical to what parse_field_names_option (utils.py:88-93) raises, so the i18n key is unchanged. ✅
  • creatives / strategies — no criteria_limits in the originals, correctly omitted; Types casing (parse_csv_upper for creatives vs plain add_criteria_csv for strategies) and the --is-archived choice/default are preserved.
  • audiencetargets — long require-message passed through t() identically; option order (--ids → extras → get_options) preserved.

Minor / non-blocking

  • Client resolution now happens only on the live path, so --dry-run becomes token-free for these five commands. This shifts error ordering on the live path (validation errors now precede a missing-token error). The PR documents this as intentional and it's consistent with all prior factory migrations — flagging only for visibility, not a defect.

Verification note

I could not execute pytest/pip install in this sandbox (commands blocked by the environment), so I relied on static tracing rather than a live run. The PR reports the full offline suite green (2554 passed) and the logic checks out on inspection. If CI is green on this branch, I'd consider the behavioral invariants confirmed.

Verdict: ✅ Looks good — net −278 lines, no functional or data-loss risk identified.
· refactor/issue-588-group4-clean-fits

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: 6c756fc449

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

@axisrow
axisrow merged commit 221c008 into main Jun 20, 2026
6 checks passed
@axisrow
axisrow deleted the refactor/issue-588-group4-clean-fits branch June 20, 2026 13:49
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.

make_get_command: мигрировать сложные get-команды (Группа 4)

2 participants