fix: a second _seed_seen shadowed the one the recapture tests call (4386)
CI and images / lint (push) Successful in 3s
CI and images / extension-version (push) Successful in 3s
CI and images / frontend-build (push) Successful in 21s
CI and images / backend-lint-and-test (push) Successful in 32s
CI and images / integration (push) Successful in 2m13s
CI and images / sign-extension (push) Successful in 2s
CI and images / build-agent (push) Successful in 5s
CI and images / build-web (push) Successful in 1m45s
CI and images / smoke-web (push) Successful in 1m6s
CI and images / promote (push) Skipped

Run 7422 integration: two #830 tests died with
`_seed_seen() got an unexpected keyword argument 'post_id'`. Not those tests'
fault — I defined a second `_seed_seen` at the BOTTOM of the module, taking a
list of media instead of one key, and Python's last definition wins for every
call site in the file including the ones 500 lines above it.

Renamed to `_seed_all_seen` and made it loop over the existing one-key helper,
so there is one definition of what seeding the ledger means. The nearby
failure mode is worth naming: a helper defined below the tests that use it is
invisible at the point of use, and shadowing produces a TypeError in code
nobody touched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVjrnpQjRgHdvq95rASoiR
This commit is contained in:
2026-09-24 06:39:49 -04:00
co-authored by Claude Opus 5
parent 2b093958a4
commit 970d17f98a
+15 -13
View File
@@ -1156,14 +1156,16 @@ def _iso(days_ago):
return (datetime.now(UTC) - timedelta(days=days_ago)).isoformat() return (datetime.now(UTC) - timedelta(days=days_ago)).isoformat()
def _seed_seen(sync_engine, source_id, media): def _seed_all_seen(sync_engine, source_id, media):
factory = sessionmaker(sync_engine, expire_on_commit=False) """Several media through the module's existing one-key `_seed_seen`.
with factory() as s:
for m in media: A distinct NAME, not a second definition: the first version of this shadowed
s.add(PatreonSeenMedia( `_seed_seen` from the bottom of the file, and the two #830 recapture tests
source_id=source_id, filehash=_ledger_key(m), post_id=m.post_id, that pass it a `post_id=` kwarg broke on a TypeError. A helper defined below
)) the tests that use it is invisible at the point of use.
s.commit() """
for m in media:
_seed_seen(sync_engine, source_id, _ledger_key(m), post_id=m.post_id)
@pytest.mark.asyncio @pytest.mark.asyncio
@@ -1174,7 +1176,7 @@ async def test_a_run_of_seen_items_does_not_stop_a_tick_inside_the_window(
around at the second and never looked at the third, which is exactly where around at the second and never looked at the third, which is exactly where
an edited post lives.""" an edited post lives."""
seen = [_media(f"p{i}", 1) for i in range(1, 4)] seen = [_media(f"p{i}", 1) for i in range(1, 4)]
_seed_seen(sync_engine, source_id, seen) _seed_all_seen(sync_engine, source_id, seen)
client = _FakeClient( client = _FakeClient(
[(None, [(m.post_id, [m]) for m in seen])], [(None, [(m.post_id, [m]) for m in seen])],
@@ -1201,7 +1203,7 @@ async def test_the_early_out_still_fires_once_the_walk_is_below_the_horizon(
did. Asserted beside the test above because the window is only correct if did. Asserted beside the test above because the window is only correct if
BOTH conditions are required; either one alone is a different feature.""" BOTH conditions are required; either one alone is a different feature."""
seen = [_media(f"p{i}", 1) for i in range(1, 4)] seen = [_media(f"p{i}", 1) for i in range(1, 4)]
_seed_seen(sync_engine, source_id, seen) _seed_all_seen(sync_engine, source_id, seen)
client = _FakeClient( client = _FakeClient(
[(None, [(m.post_id, [m]) for m in seen])], [(None, [(m.post_id, [m]) for m in seen])],
@@ -1226,7 +1228,7 @@ async def test_a_window_of_zero_is_the_behaviour_that_shipped_before_it(
"""The off switch. Recent posts, a window of 0 → the walk stops on the """The off switch. Recent posts, a window of 0 → the walk stops on the
count alone, so an operator who wants the old cheap tick has one.""" count alone, so an operator who wants the old cheap tick has one."""
seen = [_media(f"p{i}", 1) for i in range(1, 4)] seen = [_media(f"p{i}", 1) for i in range(1, 4)]
_seed_seen(sync_engine, source_id, seen) _seed_all_seen(sync_engine, source_id, seen)
client = _FakeClient( client = _FakeClient(
[(None, [(m.post_id, [m]) for m in seen])], [(None, [(m.post_id, [m]) for m in seen])],
@@ -1252,7 +1254,7 @@ async def test_a_backfill_ignores_the_window_because_it_never_early_outs(
every body — a horizon there would be a third answer to a two-answer every body — a horizon there would be a third answer to a two-answer
question.""" question."""
seen = [_media(f"p{i}", 1) for i in range(1, 4)] seen = [_media(f"p{i}", 1) for i in range(1, 4)]
_seed_seen(sync_engine, source_id, seen) _seed_all_seen(sync_engine, source_id, seen)
client = _FakeClient( client = _FakeClient(
[(None, [(m.post_id, [m]) for m in seen])], [(None, [(m.post_id, [m]) for m in seen])],
@@ -1407,7 +1409,7 @@ async def test_a_post_whose_date_will_not_parse_falls_back_to_the_count(
into the window. It reads as "not provably recent", which leaves that post into the window. It reads as "not provably recent", which leaves that post
on the behaviour it had before the window existed.""" on the behaviour it had before the window existed."""
seen = [_media(f"p{i}", 1) for i in range(1, 4)] seen = [_media(f"p{i}", 1) for i in range(1, 4)]
_seed_seen(sync_engine, source_id, seen) _seed_all_seen(sync_engine, source_id, seen)
client = _FakeClient( client = _FakeClient(
[(None, [(m.post_id, [m]) for m in seen])], [(None, [(m.post_id, [m]) for m in seen])],