From 98c9fb9402e113a15975039ff2830a23ee7311fa Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Sat, 16 May 2026 13:48:50 -0400 Subject: [PATCH] fix(tests): read column values not stale ORM entities after Core-DML merge (MissingGreenlet) Co-Authored-By: Claude Opus 4.7 (1M context) --- tests/test_tag_merge.py | 54 +++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/tests/test_tag_merge.py b/tests/test_tag_merge.py index 033efc2..687f28f 100644 --- a/tests/test_tag_merge.py +++ b/tests/test_tag_merge.py @@ -281,13 +281,15 @@ async def test_merge_repoints_existing_aliases(db): ) await db.flush() await svc.merge(a.id, b.id) - db.expire_all() # merge() uses Core DML; drop stale identity-map state - al = ( - await db.execute( - select(TagAlias).where(TagAlias.alias_string == "oldpred") + # Read the column value, not the entity: merge() uses Core DML, so an + # ORM instance would be stale and a lazy reload here would emit sync IO + # outside the async greenlet (MissingGreenlet). + cid = await db.scalar( + select(TagAlias.canonical_tag_id).where( + TagAlias.alias_string == "oldpred" ) - ).scalar_one() - assert al.canonical_tag_id == b.id + ) + assert cid == b.id @pytest.mark.asyncio @@ -299,9 +301,8 @@ async def test_merge_fandom_reparents_children(db): "ChildChar", TagKind.character, fandom_id=f_src.id ) await svc.merge(f_src.id, f_tgt.id) - db.expire_all() # merge() uses Core DML; drop stale identity-map state - refreshed = await db.get(Tag, child.id) - assert refreshed.fandom_id == f_tgt.id + fid = await db.scalar(select(Tag.fandom_id).where(Tag.id == child.id)) + assert fid == f_tgt.id @pytest.mark.asyncio @@ -341,8 +342,15 @@ async def test_alias_per_observed_prediction_category(db): await db.flush() result = await svc.merge(a.id, b.id) assert result.alias_created is True - db.expire_all() - rows = (await db.execute(select(TagAlias))).scalars().all() + rows = ( + await db.execute( + select( + TagAlias.alias_string, + TagAlias.alias_category, + TagAlias.canonical_tag_id, + ) + ) + ).all() assert {(r.alias_string, r.alias_category) for r in rows} == { ("predname", "general"), ("predname", "copyright"), @@ -361,14 +369,15 @@ async def test_alias_fallback_to_kind_when_no_predictions(db): await db.flush() result = await svc.merge(a.id, b.id) assert result.alias_created is True - db.expire_all() - al = ( + row = ( await db.execute( - select(TagAlias).where(TagAlias.alias_string == "AllowNoPred") + select( + TagAlias.alias_category, TagAlias.canonical_tag_id + ).where(TagAlias.alias_string == "AllowNoPred") ) - ).scalar_one() - assert al.alias_category == "character" - assert al.canonical_tag_id == b.id + ).one() + assert row.alias_category == "character" + assert row.canonical_tag_id == b.id @pytest.mark.asyncio @@ -395,10 +404,9 @@ async def test_alias_create_does_not_clobber_existing(db): } await db.flush() await svc.merge(a.id, b.id) - db.expire_all() - al = ( - await db.execute( - select(TagAlias).where(TagAlias.alias_string == "dupalias") + cid = await db.scalar( + select(TagAlias.canonical_tag_id).where( + TagAlias.alias_string == "dupalias" ) - ).scalar_one() - assert al.canonical_tag_id == other.id # pre-existing alias untouched + ) + assert cid == other.id # pre-existing alias untouched