fix: give the roster's column zip an explicit strict=False (387 D1, B905)
CI / lint (push) Successful in 3s
CI / extension-version (push) Successful in 3s
Build images / sign-extension (push) Successful in 4s
Build images / build-agent (push) Successful in 6s
CI / frontend-build (push) Successful in 22s
CI / backend-lint-and-test (push) Successful in 32s
Build images / build-web (push) Successful in 58s
Build images / smoke-web (push) Skipped
CI / integration (push) Successful in 2m5s
Build images / build-ml (push) Successful in 2m46s
Build images / promote (push) Skipped
CI / lint (push) Successful in 3s
CI / extension-version (push) Successful in 3s
Build images / sign-extension (push) Successful in 4s
Build images / build-agent (push) Successful in 6s
CI / frontend-build (push) Successful in 22s
CI / backend-lint-and-test (push) Successful in 32s
Build images / build-web (push) Successful in 58s
Build images / smoke-web (push) Skipped
CI / integration (push) Successful in 2m5s
Build images / build-ml (push) Successful in 2m46s
Build images / promote (push) Skipped
ef91fcf failed ruff's B905 lane on one zip(labels, cells) without strict=. Tests, integration and the frontend were already green on that SHA.
strict=False is the deliberate side, not the quiet one. strict=True raises a bare ValueError - not SubscribeStarDriftError - and would fail the whole roster sync over a column mismatch in `details`, which nothing reads yet. That would take down reconciliation and the gated-post reasons over a cosmetic markup change, while creator identity (id, slug) never depended on the columns at all.
But a shifted column would mislabel details silently (a price filed under "discord"), so a count mismatch now logs a canary warning, mirroring the feed parser's existing parse canary: diagnosable from the worker log, never fatal.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SHQB1YukL3VyvMK8rcbmV9
This commit is contained in:
@@ -396,6 +396,16 @@ def _roster_rows(table: str, identifier: str, base: str) -> list[Membership]:
|
|||||||
name = _ROSTER_NAME_RE.search(row)
|
name = _ROSTER_NAME_RE.search(row)
|
||||||
slug = unescape(href.group(1))
|
slug = unescape(href.group(1))
|
||||||
cells = _ROSTER_CELL_RE.findall(row)
|
cells = _ROSTER_CELL_RE.findall(row)
|
||||||
|
if len(cells) != len(labels):
|
||||||
|
# Canary, not a refusal. Identity above does not depend on columns,
|
||||||
|
# so a shifted column must not fail the whole roster — but it would
|
||||||
|
# silently mislabel `details` (a price filed under "discord"), so
|
||||||
|
# say so in the worker log where it is diagnosable.
|
||||||
|
log.warning(
|
||||||
|
"SubscribeStar roster %r: %d cells against %d headers — column "
|
||||||
|
"details may be mislabelled; markup likely changed (note #3989)",
|
||||||
|
identifier, len(cells), len(labels),
|
||||||
|
)
|
||||||
rows.append(Membership(
|
rows.append(Membership(
|
||||||
campaign_id=user_id.group(1),
|
campaign_id=user_id.group(1),
|
||||||
display_name=(_cell_text(name.group(1)) if name else "") or None,
|
display_name=(_cell_text(name.group(1)) if name else "") or None,
|
||||||
@@ -420,7 +430,7 @@ def _roster_rows(table: str, identifier: str, base: str) -> list[Membership]:
|
|||||||
# its <th>'s class at all.
|
# its <th>'s class at all.
|
||||||
"columns": {
|
"columns": {
|
||||||
label: _cell_text(cell)
|
label: _cell_text(cell)
|
||||||
for label, cell in zip(labels, cells)
|
for label, cell in zip(labels, cells, strict=False)
|
||||||
if label not in _ROSTER_SKIP_COLUMNS
|
if label not in _ROSTER_SKIP_COLUMNS
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user