From 05c2b6daf4836f79ed8c64618f55c6b84e5418ed Mon Sep 17 00:00:00 2001 From: kathryntanardy Date: Wed, 13 May 2026 21:04:47 -0700 Subject: [PATCH 1/6] Added 409 response. --- src/elections/urls.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/elections/urls.py b/src/elections/urls.py index 9ebe0cd..b33637c 100644 --- a/src/elections/urls.py +++ b/src/elections/urls.py @@ -275,15 +275,25 @@ async def update_election( "/{election_name}", description="Deletes an election from the database. Returns whether the election exists after deletion.", response_model=SuccessResponse, - responses={401: {"description": "Need to be logged in as an admin.", "model": DetailModel}}, + responses={ + 401: {"description": "Need to be logged in as an admin.", "model": DetailModel}, + 409: {"description": "Election is still referenced by nominee applications.", "model": DetailModel} + }, operation_id="delete_election", dependencies=[Depends(perm_election)], ) async def delete_election(db_session: database.DBSession, election_name: str): slugified_name = slugify(election_name) + existing_applications = await candidates.crud.get_all_candidates_in_election(db_session, slugified_name) + if existing_applications: + raise HTTPException( + status_code=status.HTTP_409_CONFLICT, + detail=f"{election_name} is still referenced by nominee applications.", + ) + await elections.crud.delete_election(db_session, slugified_name) await db_session.commit() - + old_election = await elections.crud.get_election(db_session, slugified_name) return JSONResponse({"success": old_election is None}) From 925baedc08b732167ccb2bed6e4386c6ddd60f09 Mon Sep 17 00:00:00 2001 From: kathryntanardy Date: Wed, 13 May 2026 21:20:07 -0700 Subject: [PATCH 2/6] your message --- .github/workflows/pytest_unit.yml | 2 +- src/elections/urls.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pytest_unit.yml b/.github/workflows/pytest_unit.yml index 41dc376..b3f963a 100644 --- a/.github/workflows/pytest_unit.yml +++ b/.github/workflows/pytest_unit.yml @@ -18,7 +18,7 @@ jobs: with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.*') }} - restore-keys: | + restore-keys: | ${{ runner.os }}-pip- - name: Install dependencies diff --git a/src/elections/urls.py b/src/elections/urls.py index b33637c..2a0ab18 100644 --- a/src/elections/urls.py +++ b/src/elections/urls.py @@ -286,14 +286,14 @@ async def delete_election(db_session: database.DBSession, election_name: str): slugified_name = slugify(election_name) existing_applications = await candidates.crud.get_all_candidates_in_election(db_session, slugified_name) - if existing_applications: + if existing_applications: raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail=f"{election_name} is still referenced by nominee applications.", ) - + await elections.crud.delete_election(db_session, slugified_name) await db_session.commit() - + old_election = await elections.crud.get_election(db_session, slugified_name) return JSONResponse({"success": old_election is None}) From b030c37c3e3b871475043f944da09fc6636a72ff Mon Sep 17 00:00:00 2001 From: kathryntanardy Date: Wed, 13 May 2026 21:42:33 -0700 Subject: [PATCH 3/6] Handle election delete conflict --- src/elections/urls.py | 2 +- tests/wip/test_github.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/elections/urls.py b/src/elections/urls.py index 2a0ab18..d88decb 100644 --- a/src/elections/urls.py +++ b/src/elections/urls.py @@ -277,7 +277,7 @@ async def update_election( response_model=SuccessResponse, responses={ 401: {"description": "Need to be logged in as an admin.", "model": DetailModel}, - 409: {"description": "Election is still referenced by nominee applications.", "model": DetailModel} + 409: {"description": "Election is still referenced by nominee applications.", "model": DetailModel}, }, operation_id="delete_election", dependencies=[Depends(perm_election)], diff --git a/tests/wip/test_github.py b/tests/wip/test_github.py index 671aefc..054ca91 100644 --- a/tests/wip/test_github.py +++ b/tests/wip/test_github.py @@ -4,11 +4,13 @@ # NOTE: must export API key to use github api (mostly...) + @pytest.mark.asyncio async def test__list_users(): member_list = await github.internals.list_members() print(member_list) + @pytest.mark.asyncio async def test__get_user_by_name(): user = await github.internals.get_user_by_username("EarthenSky") From 52a04b0797ab6b47c55bdce04beab54ce5feeac1 Mon Sep 17 00:00:00 2001 From: kathryntanardy Date: Sat, 16 May 2026 02:14:28 -0700 Subject: [PATCH 4/6] Updated try catch for 409 error --- src/elections/urls.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/elections/urls.py b/src/elections/urls.py index d88decb..bfab494 100644 --- a/src/elections/urls.py +++ b/src/elections/urls.py @@ -285,15 +285,15 @@ async def update_election( async def delete_election(db_session: database.DBSession, election_name: str): slugified_name = slugify(election_name) - existing_applications = await candidates.crud.get_all_candidates_in_election(db_session, slugified_name) - if existing_applications: + try: + await elections.crud.delete_election(db_session, slugified_name) + await db_session.commit() + except IntegrityError as error: + await db_session.rollback() raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail=f"{election_name} is still referenced by nominee applications.", ) - await elections.crud.delete_election(db_session, slugified_name) - await db_session.commit() - old_election = await elections.crud.get_election(db_session, slugified_name) return JSONResponse({"success": old_election is None}) From 46e295eac06355dd4fa223595fab698dbe064705 Mon Sep 17 00:00:00 2001 From: kathryntanardy Date: Sat, 16 May 2026 02:17:27 -0700 Subject: [PATCH 5/6] Imported error and fixed formatting --- src/elections/urls.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/elections/urls.py b/src/elections/urls.py index bfab494..2b51615 100644 --- a/src/elections/urls.py +++ b/src/elections/urls.py @@ -2,6 +2,7 @@ from fastapi import APIRouter, Depends, HTTPException, status from fastapi.responses import JSONResponse +from sqlalchemy.exc import IntegrityError import candidates.crud import database @@ -288,7 +289,7 @@ async def delete_election(db_session: database.DBSession, election_name: str): try: await elections.crud.delete_election(db_session, slugified_name) await db_session.commit() - except IntegrityError as error: + except IntegrityError: await db_session.rollback() raise HTTPException( status_code=status.HTTP_409_CONFLICT, From 47947ea2daa711d5a84388d2703d9b2da28cdce2 Mon Sep 17 00:00:00 2001 From: kathryntanardy Date: Tue, 19 May 2026 00:28:34 -0700 Subject: [PATCH 6/6] Fixed linting error. --- src/elections/urls.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/elections/urls.py b/src/elections/urls.py index 2b51615..62d9a2a 100644 --- a/src/elections/urls.py +++ b/src/elections/urls.py @@ -289,12 +289,12 @@ async def delete_election(db_session: database.DBSession, election_name: str): try: await elections.crud.delete_election(db_session, slugified_name) await db_session.commit() - except IntegrityError: + except IntegrityError as err: await db_session.rollback() raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail=f"{election_name} is still referenced by nominee applications.", - ) + ) from err old_election = await elections.crud.get_election(db_session, slugified_name) return JSONResponse({"success": old_election is None})