Skip to content

Feature/refactor all - #53

Open
sadrultoaha wants to merge 18 commits into
developfrom
feature/refactor-all
Open

Feature/refactor all#53
sadrultoaha wants to merge 18 commits into
developfrom
feature/refactor-all

Conversation

@sadrultoaha

Copy link
Copy Markdown
Collaborator

No description provided.

sadrultoaha and others added 18 commits July 16, 2026 18:40
`make quality` was passing on a stale .ruff_cache verdict: running
ruff with --no-cache surfaced 103 latent violations already present
in HEAD (98 unsorted imports, 2 unused imports, 2 quoted
annotations) plus formatting drift in 13 files. All auto-fixed with
ruff format + ruff check --fix; no behavioral changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Real bugs fixed:
- edit_product crashed with NameError (undefined `formats`) when a GAM
  product was saved with an explicit line item type; now passes
  product.format_ids to generate_default_config
- product suggestions computed already_exists against the first
  *character* of each product ID (scalars() rows are plain strings,
  `product[0]` sliced them); now compares full IDs
- scheduled delivery webhooks computed max+1 sequence_number then
  dropped it: payloads never carried the AdCP sequence_number field
  and WebhookDeliveryLog rows always recorded 1; now assigned to the
  response alongside the other webhook metadata fields

Dead code removed:
- /api/gam/test-connection and /api/gam/get-advertisers routes:
  unreferenced legacy duplicates of the tenant-scoped routes in
  gam.py/principals.py; the former crashed with NameError (undefined
  oauth_client_id/tenant_id) swallowed by a catch-all except
- ~25 write-only variables, a try/except that only re-raised, a
  redundant GAMAuthManager construction, unused imports, ambiguous
  `l` loop names
- test_auth Test 3 mocked the legacy session.query path that the
  SQLAlchemy 2.0 production code never calls (and referenced an
  undefined mock); rewired to the scalars seam, assertion unchanged

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The blanket ignores documented counts that no longer exist (the "12
bare excepts" and "4 F821 false positives" were already fixed; the
remaining F841/E741 sites were removed in the previous commit). Fix
the last six violations in scripts/ and promote all four rules to
enforced so regressions fail the build. tests/ keeps a scoped
per-file exemption for F841/E741 (154 pre-existing arrange-only
bindings) to avoid churning guarded test files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ruff --fix for RET (else-after-return family), SIM (needless bool,
same-arm ifs, yoda conditions), PIE790 (unnecessary placeholders),
PERF and C4 comprehension rules: 298 sites, safe fixes only — no
unsafe fixes applied, no behavior changes. Enforce RET501/505/506/
507/508 and PIE790 in the lint gate now that src/ and scripts/ are
at zero (tests keep pre-existing occurrences via per-file-ignores).

Also convert two stray prints to logging: a [NAMING DEBUG] print in
the mock adapter's media-buy path and an exception print in
default_products; deliberate console banners (config validation,
database provisioning, health report CLI) are left as prints.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three date.today() call sites (GAM forecast window, GAM order
projection, update-media-buy default) depended on the server's local
timezone; use datetime.now(UTC).date() so behavior is identical
across deployments. In strategy time-jump handling, current_time is
initialized timezone-aware but the jump assigned a naive strptime
result, so a later aware/naive comparison could raise TypeError —
the parsed target date is now UTC-aware.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The four sync endpoints passed the LazyScopedSession proxy where
GAMOrdersService is annotated to take a sqlalchemy Session; calling
the proxy returns the underlying thread-local Session (the same
object the surrounding code commits through), which satisfies the
annotation without behavior change. Clears the 4 mypy errors that
had been masked by the incremental cache.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
9 of the 20 unit test files that failed collection (all pre-existing:
the same failures reproduce at the branch base commit in a clean
worktree) are repaired with verified equivalents; assertions are
unchanged:

- src.app was deleted in "Sales Agent 2.0" (7fbd30e): the four
  REST/transport files now build the app via core.main.build_app().
  NOTE: build_app() fail-fasts on the DB health check, so these four
  still need a DB-less bootstrap mode or a move to tests/integration.
- adcp 6.4: FormatId moved to adcp.types; Assets classes renumbered
  (Assets5->Assets25 video, Assets9->Assets29 html,
  Assets18->Assets39 group, Assets19->Assets41, Assets22->Assets44)
  — mappings verified against the installed package.
- MediaBuyStatus.pending_activation no longer exists; the faithful
  wire-enum substitute for "accepted, awaiting start" is
  pending_start.
- test_delivery.py: dropped imports of the deleted flat-param
  MCP/A2A wrappers; the two wrapper-only tests are removed with a
  pointer to the delegate/harness transport coverage; the 11
  _impl-based test classes are unchanged.
- test_delivery_date_window.py: kept the _normalize_reporting_window
  half; removed the half testing _clamp_target_date_to_now, which
  was deleted with the GAM freshness validator call site.

Duplication baseline refresh: 19 fingerprints surfaced by formatting
normalization and recent merges (both halves of each pair predate
this work); accepted via the hook's --update-baseline mechanism.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…_any

Executes step 1 of mypy.ini's documented strictness roadmap ("bugs
hide in Any returns"). Every function returning Any where a concrete
type is declared now uses a typed intermediate or cast — no behavior
changes, no type: ignore, no annotations loosened. Verified with a
cold (--no-incremental) mypy run over all of src/ and an unchanged
unit-suite result (307/5962/24, byte-identical totals).

One annotation was genuinely wrong and is corrected:
json_type.process_bind_param deliberately passes BaseModel through
to the engine's pydantic serializer but declared it could not.

Latent bugs noted for follow-up (not changed here): broadstreet
delete_* endpoints can return None where dict is declared (empty
204 bodies); broadstreet create_placement skips the response-envelope
unwrap its siblings do; mock adapter _is_simulation returns None
instead of False; `from adcp import WholesaleFeedEvent` types as Any
despite the adcp mypy plugin (upstream re-export gap).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
format_activity_from_audit_log (cyclomatic complexity 30) is now a
small orchestrator over focused helpers: _classify_activity,
_parse_audit_details, _build_detail_sections, _quoted_excerpt.
Behavior verified byte-identical across 90 golden input/output cases
(every operation type x timestamp bucket, naive and aware).

The extraction exposed the same relative-time bucketing copied in
three modules; all three now delegate to
core.utils.time_format.relative_time_ago. One deliberate improvement:
activity_feed previously returned "Unknown" for naive datetimes (a
TypeError swallowed by its catch-all); the shared helper treats naive
as UTC like the other two copies always did.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
delete_campaign/delete_advertisement/delete_zone declared dict returns
but DELETE endpoints answer with empty 204 bodies, so callers doing
.get() on the result would crash on None — normalize to {}.
create_placement now unwraps the response envelope like every sibling
create_* method. Mock adapter _is_simulation returned None (falsy
object) instead of False when no strategy context is set.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three complexity hotspots become small orchestrators over focused
module-level helpers, behavior locked before/after:

- get_principal_from_context (C=41 -> under 20): golden-mastered with
  28 synthetic inputs covering every branch, external lookups patched
  at their real import sites, and the chronological dependency call
  log asserted — outputs, exceptions, and lookup ORDER byte-identical.
- parse_form_data_to_policy_updates (C=43) and
  parse_pricing_options_from_form (C=31): golden-locked over
  branch-covering synthetic form inputs — both diffs empty.

Full unit suite unchanged: 307/5962/24 with a per-test set-diff of
zero new failures. Duplication ratchet tightened 18 -> 17 blocks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Dashboard revenue trend issued one DB query per day (30 per
  dashboard load, 365 for YTD). MediaBuyRepository gains
  list_in_flight_between(); the trend fetches the window once and
  buckets per day in Python with identical per-buy attribution math.
  list_in_flight_on_date delegates to the windowed query.
- Product-suggestions API rebuilt the default-products catalog inside
  the sort key and again per suggestion (O(n^2)); the default-ID set
  is now computed once per request.
- src/services/ai_parsing_comparison.py (unimported CLI tool, never
  part of the server) moves to scripts/ops/ where it is runnable
  without shipping in the service import tree.

Unit suite: totals unchanged (307/5962/24), per-test set-diff zero
new failures; mypy/ruff/duplication gates green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The details page called adapter.get_media_buy_delivery() inline — a
live GAM Reporting API round trip blocking every page visit. The page
now renders instantly from the persisted delivery snapshot
(delivered_impressions/delivered_amount/delivery_synced_at), and a new
GET /media-buy/<id>/delivery-metrics JSON endpoint (api_mode auth, so
expired sessions get JSON not HTML) performs the reporting fetch after
page load, refreshes the snapshot, and the template updates the
metrics in place — with an explicit snapshot/live/unavailable status
line. Package IDs from the adapter are inserted via textContent, never
as HTML. Route-conflict hook clean; unit totals unchanged
(307/5962/24, zero new failures).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Docker image bakes ENV ADCP_PORT=8000 for the run_all_services
entrypoint; the compose test path launches run_server.py with
ADCP_SALES_PORT=8080 and healthchecks 8080. setdefault("ADCP_PORT")
silently lost to the baked ENV, so the unified server bound 8000
while nginx proxied to 8080 — the stack could never become healthy
and ./run_all_tests.sh aborted before any suite ran. Assign instead
of setdefault; verified by a full stack run reaching healthy with
zero nginx upstream errors and the admin (128 passed) and ui
(7 passed) suites completing through the proxy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant