From 4a020c56d126487633aaa0ee3fe363df7ca6ee9e Mon Sep 17 00:00:00 2001 From: d3vyce <44915747+d3vyce@users.noreply.github.com> Date: Mon, 2 Mar 2026 14:28:37 +0100 Subject: [PATCH] feat: Raise NotFoundError instead of LookupError in wait_for_row_change (#105) --- src/fastapi_toolsets/db.py | 8 +++++--- tests/test_db.py | 9 +++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/fastapi_toolsets/db.py b/src/fastapi_toolsets/db.py index 0c476fd..641a5a9 100644 --- a/src/fastapi_toolsets/db.py +++ b/src/fastapi_toolsets/db.py @@ -10,6 +10,8 @@ from sqlalchemy import text from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker from sqlalchemy.orm import DeclarativeBase +from .exceptions import NotFoundError + __all__ = [ "LockMode", "create_db_context", @@ -216,7 +218,7 @@ async def wait_for_row_change( The refreshed model instance with updated values Raises: - LookupError: If the row does not exist or is deleted during polling + NotFoundError: If the row does not exist or is deleted during polling TimeoutError: If timeout expires before a change is detected Example: @@ -237,7 +239,7 @@ async def wait_for_row_change( """ instance = await session.get(model, pk_value) if instance is None: - raise LookupError(f"{model.__name__} with pk={pk_value!r} not found") + raise NotFoundError(f"{model.__name__} with pk={pk_value!r} not found") if columns is not None: watch_cols = columns @@ -261,7 +263,7 @@ async def wait_for_row_change( instance = await session.get(model, pk_value) if instance is None: - raise LookupError(f"{model.__name__} with pk={pk_value!r} was deleted") + raise NotFoundError(f"{model.__name__} with pk={pk_value!r} was deleted") current = {col: getattr(instance, col) for col in watch_cols} if current != initial: diff --git a/tests/test_db.py b/tests/test_db.py index dabc3e7..9bd537d 100644 --- a/tests/test_db.py +++ b/tests/test_db.py @@ -14,6 +14,7 @@ from fastapi_toolsets.db import ( lock_tables, wait_for_row_change, ) +from fastapi_toolsets.exceptions import NotFoundError from .conftest import DATABASE_URL, Base, Role, RoleCrud, User @@ -307,9 +308,9 @@ class TestWaitForRowChange: @pytest.mark.anyio async def test_nonexistent_row_raises(self, db_session: AsyncSession): - """Raises LookupError when the row does not exist.""" + """Raises NotFoundError when the row does not exist.""" fake_id = uuid.uuid4() - with pytest.raises(LookupError, match="not found"): + with pytest.raises(NotFoundError, match="not found"): await wait_for_row_change(db_session, Role, fake_id, interval=0.05) @pytest.mark.anyio @@ -326,7 +327,7 @@ class TestWaitForRowChange: @pytest.mark.anyio async def test_deleted_row_raises(self, db_session: AsyncSession, engine): - """Raises LookupError when the row is deleted during polling.""" + """Raises NotFoundError when the row is deleted during polling.""" role = Role(name="delete_role") db_session.add(role) await db_session.commit() @@ -340,6 +341,6 @@ class TestWaitForRowChange: await other.commit() delete_task = asyncio.create_task(delete_later()) - with pytest.raises(LookupError): + with pytest.raises(NotFoundError): await wait_for_row_change(db_session, Role, role.id, interval=0.05) await delete_task