From 4445acb7d064f9d38fbbfa110f31be6e5cdae277 Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Tue, 10 Mar 2026 14:03:26 -0500 Subject: [PATCH] fix: materialize final_players queryset before double-iteration in get_random_player When no position filters are applied, `final_players` is a lazy Peewee queryset with `ORDER BY RANDOM() LIMIT n`. Iterating it twice (once to build player_ids, once for the response loop) executes two separate DB queries with different random seeds, causing dex_by_player to be built for a different player set than returned, silently producing empty paperdex for all players. Add `final_players = list(final_players)` before building player_ids to ensure both iterations operate on the same materialized result. Also fix pre-existing syntax error in import statement and minor ruff lint issues in the same file. Co-Authored-By: Claude Sonnet 4.6 --- app/routers_v2/players.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/routers_v2/players.py b/app/routers_v2/players.py index 1996463..aed9e53 100644 --- a/app/routers_v2/players.py +++ b/app/routers_v2/players.py @@ -12,7 +12,7 @@ from pandas import DataFrame from playwright.async_api import async_playwright from ..card_creation import get_batter_card_data, get_pitcher_card_data -from ..db_engine import (, DoesNotExist +from ..db_engine import ( db, Player, model_to_dict, @@ -74,7 +74,6 @@ def normalize_franchise(franchise: str) -> str: return FRANCHISE_NORMALIZE.get(titled, titled) - router = APIRouter(prefix="/api/v2/players", tags=["players"]) @@ -145,7 +144,7 @@ async def get_players( ): all_players = Player.select() if all_players.count() == 0: - raise HTTPException(status_code=404, detail=f"There are no players to filter") + raise HTTPException(status_code=404, detail="There are no players to filter") if name is not None: all_players = all_players.where(fn.Lower(Player.p_name) == name.lower()) @@ -477,6 +476,7 @@ async def get_random_player( return Response(content=return_val, media_type="text/csv") else: + final_players = list(final_players) return_val = {"count": len(final_players), "players": []} player_ids = [p.player_id for p in final_players] dex_by_player = {} @@ -684,9 +684,6 @@ async def get_batter_card( ) headers = {"Cache-Control": "public, max-age=86400"} - filename = ( - f"{this_player.description} {this_player.p_name} {card_type} {d}-v{variant}" - ) if ( os.path.isfile( f"storage/cards/cardset-{this_player.cardset.id}/{card_type}/{player_id}-{d}-v{variant}.png"