Fix linting errors across backend and frontend
All checks were successful
CI / backend-lint (push) Successful in 7s
CI / frontend-lint (push) Successful in 29s

Backend: auto-fix and format all ruff issues, manually fix B904/B023/
SIM117/B007/E741/F841 errors, suppress B008 (FastAPI Depends) and F821
(SQLAlchemy forward refs) in config. Frontend: allow constant exports,
disable React compiler-specific rules (set-state-in-effect,
preserve-manual-memoization).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Julian Tabel
2026-02-10 12:26:57 +01:00
parent 7f8890086f
commit e4111c67bc
48 changed files with 1225 additions and 883 deletions

View File

@@ -1,6 +1,8 @@
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from sqlalchemy import delete as sa_delete, func, select, update as sa_update
from sqlalchemy import delete as sa_delete
from sqlalchemy import func, select
from sqlalchemy import update as sa_update
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
@@ -9,9 +11,9 @@ from app.models.encounter import Encounter
from app.models.evolution import Evolution
from app.models.game import Game
from app.models.genlocke import Genlocke, GenlockeLeg
from app.models.genlocke_transfer import GenlockeTransfer
from app.models.nuzlocke_run import NuzlockeRun
from app.models.pokemon import Pokemon
from app.models.genlocke_transfer import GenlockeTransfer
from app.models.route import Route
from app.schemas.genlocke import (
AddLegRequest,
@@ -74,9 +76,7 @@ async def list_genlockes(session: AsyncSession = Depends(get_session)):
@router.get("/{genlocke_id}", response_model=GenlockeDetailResponse)
async def get_genlocke(
genlocke_id: int, session: AsyncSession = Depends(get_session)
):
async def get_genlocke(genlocke_id: int, session: AsyncSession = Depends(get_session)):
result = await session.execute(
select(Genlocke)
.where(Genlocke.id == genlocke_id)
@@ -112,7 +112,9 @@ async def get_genlocke(
legs_completed = 0
for leg in genlocke.legs:
run_status = leg.run.status if leg.run else None
enc_count, death_count = stats_by_run.get(leg.run_id, (0, 0)) if leg.run_id else (0, 0)
enc_count, death_count = (
stats_by_run.get(leg.run_id, (0, 0)) if leg.run_id else (0, 0)
)
total_encounters += enc_count
total_deaths += death_count
if run_status == "completed":
@@ -254,7 +256,9 @@ async def get_genlocke_graveyard(
)
)
deadliest = max(deaths_per_leg, key=lambda s: s.death_count) if deaths_per_leg else None
deadliest = (
max(deaths_per_leg, key=lambda s: s.death_count) if deaths_per_leg else None
)
return GenlockeGraveyardResponse(
entries=entries,
@@ -285,9 +289,7 @@ async def get_genlocke_lineages(
# Query all transfers for this genlocke
transfer_result = await session.execute(
select(GenlockeTransfer).where(
GenlockeTransfer.genlocke_id == genlocke_id
)
select(GenlockeTransfer).where(GenlockeTransfer.genlocke_id == genlocke_id)
)
transfers = transfer_result.scalars().all()
@@ -302,7 +304,11 @@ async def get_genlocke_lineages(
backward.add(t.target_encounter_id)
# Find roots: sources that are NOT targets
roots = [t.source_encounter_id for t in transfers if t.source_encounter_id not in backward]
roots = [
t.source_encounter_id
for t in transfers
if t.source_encounter_id not in backward
]
# Deduplicate while preserving order
seen_roots: set[int] = set()
unique_roots: list[int] = []
@@ -421,7 +427,7 @@ async def get_genlocke_lineages(
)
# Sort by first leg order, then by encounter ID
lineages.sort(key=lambda l: (l.legs[0].leg_order, l.legs[0].encounter_id))
lineages.sort(key=lambda lin: (lin.legs[0].leg_order, lin.legs[0].encounter_id))
return GenlockeLineageResponse(
lineages=lineages,
@@ -440,15 +446,11 @@ async def create_genlocke(
raise HTTPException(status_code=400, detail="Name is required")
# Validate all game_ids exist
result = await session.execute(
select(Game).where(Game.id.in_(data.game_ids))
)
result = await session.execute(select(Game).where(Game.id.in_(data.game_ids)))
found_games = {g.id: g for g in result.scalars().all()}
missing = [gid for gid in data.game_ids if gid not in found_games]
if missing:
raise HTTPException(
status_code=404, detail=f"Games not found: {missing}"
)
raise HTTPException(status_code=404, detail=f"Games not found: {missing}")
# Create genlocke
genlocke = Genlocke(
@@ -578,9 +580,7 @@ async def advance_leg(
raise HTTPException(status_code=404, detail="Genlocke not found")
if genlocke.status != "active":
raise HTTPException(
status_code=400, detail="Genlocke is not active"
)
raise HTTPException(status_code=400, detail="Genlocke is not active")
# Find the current leg
current_leg = None
@@ -596,9 +596,7 @@ async def advance_leg(
# Verify current leg's run is completed
if current_leg.run_id is None:
raise HTTPException(
status_code=400, detail="Current leg has no run"
)
raise HTTPException(status_code=400, detail="Current leg has no run")
current_run = await session.get(NuzlockeRun, current_leg.run_id)
if current_run is None or current_run.status != "completed":
raise HTTPException(
@@ -606,14 +604,10 @@ async def advance_leg(
)
if next_leg is None:
raise HTTPException(
status_code=400, detail="No next leg to advance to"
)
raise HTTPException(status_code=400, detail="No next leg to advance to")
if next_leg.run_id is not None:
raise HTTPException(
status_code=400, detail="Next leg already has a run"
)
raise HTTPException(status_code=400, detail="Next leg already has a run")
# Compute retired Pokemon families if retireHoF is enabled
if genlocke.genlocke_rules.get("retireHoF", False):
@@ -807,10 +801,12 @@ async def get_retired_families(
for leg in legs:
ids = leg.retired_pokemon_ids or []
cumulative.update(ids)
by_leg.append(RetiredLegResponse(
leg_order=leg.leg_order,
retired_pokemon_ids=ids,
))
by_leg.append(
RetiredLegResponse(
leg_order=leg.leg_order,
retired_pokemon_ids=ids,
)
)
return RetiredFamiliesResponse(
retired_pokemon_ids=sorted(cumulative),
@@ -837,12 +833,15 @@ async def update_genlocke(
update_data = data.model_dump(exclude_unset=True)
if "status" in update_data:
if update_data["status"] not in ("active", "completed", "failed"):
raise HTTPException(
status_code=400,
detail="Status must be one of: active, completed, failed",
)
if "status" in update_data and update_data["status"] not in (
"active",
"completed",
"failed",
):
raise HTTPException(
status_code=400,
detail="Status must be one of: active, completed, failed",
)
for field, value in update_data.items():
setattr(genlocke, field, value)
@@ -871,8 +870,7 @@ async def delete_genlocke(
# Delete legs explicitly to avoid ORM cascade issues
# (genlocke_id is non-nullable, so SQLAlchemy can't nullify it)
await session.execute(
sa_delete(GenlockeLeg)
.where(GenlockeLeg.genlocke_id == genlocke_id)
sa_delete(GenlockeLeg).where(GenlockeLeg.genlocke_id == genlocke_id)
)
await session.delete(genlocke)