Merge pull request 'fix: remove unused imports in standings.py and pitchingstats.py (#30)' (#49) from ai/major-domo-database-30 into next-release

Reviewed-on: #49
This commit is contained in:
cal 2026-03-10 14:34:38 +00:00
commit 0f479c20a6
2 changed files with 220 additions and 145 deletions

View File

@ -1,20 +1,29 @@
import datetime
import os
from fastapi import APIRouter, Depends, HTTPException, Query from fastapi import APIRouter, Depends, HTTPException, Query
from typing import List, Optional, Literal from typing import List, Optional, Literal
import logging import logging
import pydantic import pydantic
from ..db_engine import db, PitchingStat, Team, Player, Current, model_to_dict, chunked, fn, per_season_weeks from ..db_engine import (
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors db,
PitchingStat,
logger = logging.getLogger('discord_app') Team,
Player,
router = APIRouter( Current,
prefix='/api/v3/pitchingstats', model_to_dict,
tags=['pitchingstats'] chunked,
fn,
per_season_weeks,
) )
from ..dependencies import (
oauth2_scheme,
valid_token,
PRIVATE_IN_SCHEMA,
handle_db_errors,
)
logger = logging.getLogger("discord_app")
router = APIRouter(prefix="/api/v3/pitchingstats", tags=["pitchingstats"])
class PitStatModel(pydantic.BaseModel): class PitStatModel(pydantic.BaseModel):
@ -48,29 +57,37 @@ class PitStatList(pydantic.BaseModel):
stats: List[PitStatModel] stats: List[PitStatModel]
@router.get('') @router.get("")
@handle_db_errors @handle_db_errors
async def get_pitstats( async def get_pitstats(
season: int, s_type: Optional[str] = 'regular', team_abbrev: list = Query(default=None), season: int,
player_name: list = Query(default=None), player_id: list = Query(default=None), s_type: Optional[str] = "regular",
week_start: Optional[int] = None, week_end: Optional[int] = None, game_num: list = Query(default=None), team_abbrev: list = Query(default=None),
limit: Optional[int] = None, ip_min: Optional[float] = None, sort: Optional[str] = None, player_name: list = Query(default=None),
short_output: Optional[bool] = True): player_id: list = Query(default=None),
if 'post' in s_type.lower(): week_start: Optional[int] = None,
week_end: Optional[int] = None,
game_num: list = Query(default=None),
limit: Optional[int] = None,
ip_min: Optional[float] = None,
sort: Optional[str] = None,
short_output: Optional[bool] = True,
):
if "post" in s_type.lower():
all_stats = PitchingStat.post_season(season) all_stats = PitchingStat.post_season(season)
if all_stats.count() == 0: if all_stats.count() == 0:
db.close() db.close()
return {'count': 0, 'stats': []} return {"count": 0, "stats": []}
elif s_type.lower() in ['combined', 'total', 'all']: elif s_type.lower() in ["combined", "total", "all"]:
all_stats = PitchingStat.combined_season(season) all_stats = PitchingStat.combined_season(season)
if all_stats.count() == 0: if all_stats.count() == 0:
db.close() db.close()
return {'count': 0, 'stats': []} return {"count": 0, "stats": []}
else: else:
all_stats = PitchingStat.regular_season(season) all_stats = PitchingStat.regular_season(season)
if all_stats.count() == 0: if all_stats.count() == 0:
db.close() db.close()
return {'count': 0, 'stats': []} return {"count": 0, "stats": []}
if team_abbrev is not None: if team_abbrev is not None:
t_query = Team.select().where(Team.abbrev << [x.upper() for x in team_abbrev]) t_query = Team.select().where(Team.abbrev << [x.upper() for x in team_abbrev])
@ -79,7 +96,9 @@ async def get_pitstats(
if player_id: if player_id:
all_stats = all_stats.where(PitchingStat.player_id << player_id) all_stats = all_stats.where(PitchingStat.player_id << player_id)
else: else:
p_query = Player.select_season(season).where(fn.Lower(Player.name) << [x.lower() for x in player_name]) p_query = Player.select_season(season).where(
fn.Lower(Player.name) << [x.lower() for x in player_name]
)
all_stats = all_stats.where(PitchingStat.player << p_query) all_stats = all_stats.where(PitchingStat.player << p_query)
if game_num: if game_num:
all_stats = all_stats.where(PitchingStat.game == game_num) all_stats = all_stats.where(PitchingStat.game == game_num)
@ -96,7 +115,7 @@ async def get_pitstats(
db.close() db.close()
raise HTTPException( raise HTTPException(
status_code=404, status_code=404,
detail=f'Start week {start} is after end week {end} - cannot pull stats' detail=f"Start week {start} is after end week {end} - cannot pull stats",
) )
all_stats = all_stats.where( all_stats = all_stats.where(
(PitchingStat.week >= start) & (PitchingStat.week <= end) (PitchingStat.week >= start) & (PitchingStat.week <= end)
@ -105,58 +124,81 @@ async def get_pitstats(
if limit: if limit:
all_stats = all_stats.limit(limit) all_stats = all_stats.limit(limit)
if sort: if sort:
if sort == 'newest': if sort == "newest":
all_stats = all_stats.order_by(-PitchingStat.week, -PitchingStat.game) all_stats = all_stats.order_by(-PitchingStat.week, -PitchingStat.game)
return_stats = { return_stats = {
'count': all_stats.count(), "count": all_stats.count(),
'stats': [model_to_dict(x, recurse=not short_output) for x in all_stats] "stats": [model_to_dict(x, recurse=not short_output) for x in all_stats],
} }
db.close() db.close()
return return_stats return return_stats
@router.get('/totals') @router.get("/totals")
@handle_db_errors @handle_db_errors
async def get_totalstats( async def get_totalstats(
season: int, s_type: Literal['regular', 'post', 'total', None] = None, team_abbrev: list = Query(default=None), season: int,
team_id: list = Query(default=None), player_name: list = Query(default=None), s_type: Literal["regular", "post", "total", None] = None,
week_start: Optional[int] = None, week_end: Optional[int] = None, game_num: list = Query(default=None), team_abbrev: list = Query(default=None),
is_sp: Optional[bool] = None, ip_min: Optional[float] = 0.25, sort: Optional[str] = None, team_id: list = Query(default=None),
player_id: list = Query(default=None), short_output: Optional[bool] = False, player_name: list = Query(default=None),
group_by: Literal['team', 'player', 'playerteam'] = 'player', week: list = Query(default=None)): week_start: Optional[int] = None,
week_end: Optional[int] = None,
game_num: list = Query(default=None),
is_sp: Optional[bool] = None,
ip_min: Optional[float] = 0.25,
sort: Optional[str] = None,
player_id: list = Query(default=None),
short_output: Optional[bool] = False,
group_by: Literal["team", "player", "playerteam"] = "player",
week: list = Query(default=None),
):
if sum(1 for x in [s_type, (week_start or week_end), week] if x is not None) > 1: if sum(1 for x in [s_type, (week_start or week_end), week] if x is not None) > 1:
raise HTTPException(status_code=400, detail=f'Only one of s_type, week_start/week_end, or week may be used.') raise HTTPException(
status_code=400,
detail=f"Only one of s_type, week_start/week_end, or week may be used.",
)
# Build SELECT fields conditionally based on group_by to match GROUP BY exactly # Build SELECT fields conditionally based on group_by to match GROUP BY exactly
select_fields = [] select_fields = []
if group_by == 'player': if group_by == "player":
select_fields = [PitchingStat.player] select_fields = [PitchingStat.player]
elif group_by == 'team': elif group_by == "team":
select_fields = [PitchingStat.team] select_fields = [PitchingStat.team]
elif group_by == 'playerteam': elif group_by == "playerteam":
select_fields = [PitchingStat.player, PitchingStat.team] select_fields = [PitchingStat.player, PitchingStat.team]
else: else:
# Default case # Default case
select_fields = [PitchingStat.player] select_fields = [PitchingStat.player]
all_stats = ( all_stats = (
PitchingStat PitchingStat.select(
.select(*select_fields, *select_fields,
fn.SUM(PitchingStat.ip).alias('sum_ip'), fn.SUM(PitchingStat.ip).alias("sum_ip"),
fn.SUM(PitchingStat.hit).alias('sum_hit'), fn.SUM(PitchingStat.run).alias('sum_run'), fn.SUM(PitchingStat.hit).alias("sum_hit"),
fn.SUM(PitchingStat.erun).alias('sum_erun'), fn.SUM(PitchingStat.so).alias('sum_so'), fn.SUM(PitchingStat.run).alias("sum_run"),
fn.SUM(PitchingStat.bb).alias('sum_bb'), fn.SUM(PitchingStat.hbp).alias('sum_hbp'), fn.SUM(PitchingStat.erun).alias("sum_erun"),
fn.SUM(PitchingStat.wp).alias('sum_wp'), fn.SUM(PitchingStat.balk).alias('sum_balk'), fn.SUM(PitchingStat.so).alias("sum_so"),
fn.SUM(PitchingStat.hr).alias('sum_hr'), fn.SUM(PitchingStat.ir).alias('sum_ir'), fn.SUM(PitchingStat.bb).alias("sum_bb"),
fn.SUM(PitchingStat.win).alias('sum_win'), fn.SUM(PitchingStat.loss).alias('sum_loss'), fn.SUM(PitchingStat.hbp).alias("sum_hbp"),
fn.SUM(PitchingStat.hold).alias('sum_hold'), fn.SUM(PitchingStat.sv).alias('sum_sv'), fn.SUM(PitchingStat.wp).alias("sum_wp"),
fn.SUM(PitchingStat.bsv).alias('sum_bsv'), fn.SUM(PitchingStat.irs).alias('sum_irs'), fn.SUM(PitchingStat.balk).alias("sum_balk"),
fn.SUM(PitchingStat.gs).alias('sum_gs'), fn.COUNT(PitchingStat.game).alias('sum_games')) fn.SUM(PitchingStat.hr).alias("sum_hr"),
.where(PitchingStat.season == season) fn.SUM(PitchingStat.ir).alias("sum_ir"),
.having(fn.SUM(PitchingStat.ip) >= ip_min) fn.SUM(PitchingStat.win).alias("sum_win"),
fn.SUM(PitchingStat.loss).alias("sum_loss"),
fn.SUM(PitchingStat.hold).alias("sum_hold"),
fn.SUM(PitchingStat.sv).alias("sum_sv"),
fn.SUM(PitchingStat.bsv).alias("sum_bsv"),
fn.SUM(PitchingStat.irs).alias("sum_irs"),
fn.SUM(PitchingStat.gs).alias("sum_gs"),
fn.COUNT(PitchingStat.game).alias("sum_games"),
)
.where(PitchingStat.season == season)
.having(fn.SUM(PitchingStat.ip) >= ip_min)
) )
if True in [s_type is not None, week_start is not None, week_end is not None]: if True in [s_type is not None, week_start is not None, week_end is not None]:
@ -166,16 +208,20 @@ async def get_totalstats(
elif week_start is not None or week_end is not None: elif week_start is not None or week_end is not None:
if week_start is None or week_end is None: if week_start is None or week_end is None:
raise HTTPException( raise HTTPException(
status_code=400, detail='Both week_start and week_end must be included if either is used.' status_code=400,
detail="Both week_start and week_end must be included if either is used.",
)
weeks["start"] = week_start
if week_end < weeks["start"]:
raise HTTPException(
status_code=400,
detail="week_end must be greater than or equal to week_start",
) )
weeks['start'] = week_start
if week_end < weeks['start']:
raise HTTPException(status_code=400, detail='week_end must be greater than or equal to week_start')
else: else:
weeks['end'] = week_end weeks["end"] = week_end
all_stats = all_stats.where( all_stats = all_stats.where(
(PitchingStat.week >= weeks['start']) & (PitchingStat.week <= weeks['end']) (PitchingStat.week >= weeks["start"]) & (PitchingStat.week <= weeks["end"])
) )
elif week is not None: elif week is not None:
@ -189,9 +235,9 @@ async def get_totalstats(
if not is_sp: if not is_sp:
all_stats = all_stats.where(PitchingStat.gs == 0) all_stats = all_stats.where(PitchingStat.gs == 0)
if sort is not None: if sort is not None:
if sort == 'player': if sort == "player":
all_stats = all_stats.order_by(PitchingStat.player) all_stats = all_stats.order_by(PitchingStat.player)
elif sort == 'team': elif sort == "team":
all_stats = all_stats.order_by(PitchingStat.team) all_stats = all_stats.order_by(PitchingStat.team)
if group_by is not None: if group_by is not None:
# Use the same fields for GROUP BY as we used for SELECT # Use the same fields for GROUP BY as we used for SELECT
@ -200,67 +246,76 @@ async def get_totalstats(
all_teams = Team.select().where(Team.id << team_id) all_teams = Team.select().where(Team.id << team_id)
all_stats = all_stats.where(PitchingStat.team << all_teams) all_stats = all_stats.where(PitchingStat.team << all_teams)
elif team_abbrev is not None: elif team_abbrev is not None:
all_teams = Team.select().where(fn.Lower(Team.abbrev) << [x.lower() for x in team_abbrev]) all_teams = Team.select().where(
fn.Lower(Team.abbrev) << [x.lower() for x in team_abbrev]
)
all_stats = all_stats.where(PitchingStat.team << all_teams) all_stats = all_stats.where(PitchingStat.team << all_teams)
if player_name is not None: if player_name is not None:
all_players = Player.select().where(fn.Lower(Player.name) << [x.lower() for x in player_name]) all_players = Player.select().where(
fn.Lower(Player.name) << [x.lower() for x in player_name]
)
all_stats = all_stats.where(PitchingStat.player << all_players) all_stats = all_stats.where(PitchingStat.player << all_players)
elif player_id is not None: elif player_id is not None:
all_players = Player.select().where(Player.id << player_id) all_players = Player.select().where(Player.id << player_id)
all_stats = all_stats.where(PitchingStat.player << all_players) all_stats = all_stats.where(PitchingStat.player << all_players)
return_stats = { return_stats = {"count": all_stats.count(), "stats": []}
'count': all_stats.count(),
'stats': []
}
for x in all_stats: for x in all_stats:
# Handle player field based on grouping with safe access # Handle player field based on grouping with safe access
this_player = 'TOT' this_player = "TOT"
if 'player' in group_by and hasattr(x, 'player'): if "player" in group_by and hasattr(x, "player"):
this_player = x.player_id if short_output else model_to_dict(x.player, recurse=False) this_player = (
x.player_id if short_output else model_to_dict(x.player, recurse=False)
)
# Handle team field based on grouping with safe access # Handle team field based on grouping with safe access
this_team = 'TOT' this_team = "TOT"
if 'team' in group_by and hasattr(x, 'team'): if "team" in group_by and hasattr(x, "team"):
this_team = x.team_id if short_output else model_to_dict(x.team, recurse=False) this_team = (
x.team_id if short_output else model_to_dict(x.team, recurse=False)
return_stats['stats'].append({ )
'player': this_player,
'team': this_team, return_stats["stats"].append(
'ip': x.sum_ip, {
'hit': x.sum_hit, "player": this_player,
'run': x.sum_run, "team": this_team,
'erun': x.sum_erun, "ip": x.sum_ip,
'so': x.sum_so, "hit": x.sum_hit,
'bb': x.sum_bb, "run": x.sum_run,
'hbp': x.sum_hbp, "erun": x.sum_erun,
'wp': x.sum_wp, "so": x.sum_so,
'balk': x.sum_balk, "bb": x.sum_bb,
'hr': x.sum_hr, "hbp": x.sum_hbp,
'ir': x.sum_ir, "wp": x.sum_wp,
'irs': x.sum_irs, "balk": x.sum_balk,
'gs': x.sum_gs, "hr": x.sum_hr,
'games': x.sum_games, "ir": x.sum_ir,
'win': x.sum_win, "irs": x.sum_irs,
'loss': x.sum_loss, "gs": x.sum_gs,
'hold': x.sum_hold, "games": x.sum_games,
'sv': x.sum_sv, "win": x.sum_win,
'bsv': x.sum_bsv "loss": x.sum_loss,
}) "hold": x.sum_hold,
"sv": x.sum_sv,
"bsv": x.sum_bsv,
}
)
db.close() db.close()
return return_stats return return_stats
@router.patch('/{stat_id}', include_in_schema=PRIVATE_IN_SCHEMA) @router.patch("/{stat_id}", include_in_schema=PRIVATE_IN_SCHEMA)
@handle_db_errors @handle_db_errors
async def patch_pitstats(stat_id: int, new_stats: PitStatModel, token: str = Depends(oauth2_scheme)): async def patch_pitstats(
stat_id: int, new_stats: PitStatModel, token: str = Depends(oauth2_scheme)
):
if not valid_token(token): if not valid_token(token):
logger.warning(f'patch_pitstats - Bad Token: {token}') logger.warning(f"patch_pitstats - Bad Token: {token}")
raise HTTPException(status_code=401, detail='Unauthorized') raise HTTPException(status_code=401, detail="Unauthorized")
if PitchingStat.get_or_none(PitchingStat.id == stat_id) is None: if PitchingStat.get_or_none(PitchingStat.id == stat_id) is None:
raise HTTPException(status_code=404, detail=f'Stat ID {stat_id} not found') raise HTTPException(status_code=404, detail=f"Stat ID {stat_id} not found")
PitchingStat.update(**new_stats.dict()).where(PitchingStat.id == stat_id).execute() PitchingStat.update(**new_stats.dict()).where(PitchingStat.id == stat_id).execute()
r_stat = model_to_dict(PitchingStat.get_by_id(stat_id)) r_stat = model_to_dict(PitchingStat.get_by_id(stat_id))
@ -268,12 +323,12 @@ async def patch_pitstats(stat_id: int, new_stats: PitStatModel, token: str = Dep
return r_stat return r_stat
@router.post('', include_in_schema=PRIVATE_IN_SCHEMA) @router.post("", include_in_schema=PRIVATE_IN_SCHEMA)
@handle_db_errors @handle_db_errors
async def post_pitstats(s_list: PitStatList, token: str = Depends(oauth2_scheme)): async def post_pitstats(s_list: PitStatList, token: str = Depends(oauth2_scheme)):
if not valid_token(token): if not valid_token(token):
logger.warning(f'post_pitstats - Bad Token: {token}') logger.warning(f"post_pitstats - Bad Token: {token}")
raise HTTPException(status_code=401, detail='Unauthorized') raise HTTPException(status_code=401, detail="Unauthorized")
all_stats = [] all_stats = []
@ -281,9 +336,13 @@ async def post_pitstats(s_list: PitStatList, token: str = Depends(oauth2_scheme)
team = Team.get_or_none(Team.id == x.team_id) team = Team.get_or_none(Team.id == x.team_id)
this_player = Player.get_or_none(Player.id == x.player_id) this_player = Player.get_or_none(Player.id == x.player_id)
if team is None: if team is None:
raise HTTPException(status_code=404, detail=f'Team ID {x.team_id} not found') raise HTTPException(
status_code=404, detail=f"Team ID {x.team_id} not found"
)
if this_player is None: if this_player is None:
raise HTTPException(status_code=404, detail=f'Player ID {x.player_id} not found') raise HTTPException(
status_code=404, detail=f"Player ID {x.player_id} not found"
)
all_stats.append(PitchingStat(**x.dict())) all_stats.append(PitchingStat(**x.dict()))
@ -292,4 +351,4 @@ async def post_pitstats(s_list: PitStatList, token: str = Depends(oauth2_scheme)
PitchingStat.insert_many(batch).on_conflict_ignore().execute() PitchingStat.insert_many(batch).on_conflict_ignore().execute()
db.close() db.close()
return f'Added {len(all_stats)} batting lines' return f"Added {len(all_stats)} batting lines"

View File

@ -1,24 +1,29 @@
from fastapi import APIRouter, Depends, HTTPException, Query from fastapi import APIRouter, Depends, HTTPException, Query
from typing import List, Optional from typing import List, Optional
import logging import logging
import pydantic
from ..db_engine import db, Standings, Team, Division, model_to_dict, chunked, fn from ..db_engine import db, Standings, Team, Division, model_to_dict, chunked, fn
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors from ..dependencies import (
oauth2_scheme,
logger = logging.getLogger('discord_app') valid_token,
PRIVATE_IN_SCHEMA,
router = APIRouter( handle_db_errors,
prefix='/api/v3/standings',
tags=['standings']
) )
logger = logging.getLogger("discord_app")
@router.get('') router = APIRouter(prefix="/api/v3/standings", tags=["standings"])
@router.get("")
@handle_db_errors @handle_db_errors
async def get_standings( async def get_standings(
season: int, team_id: list = Query(default=None), league_abbrev: Optional[str] = None, season: int,
division_abbrev: Optional[str] = None, short_output: Optional[bool] = False): team_id: list = Query(default=None),
league_abbrev: Optional[str] = None,
division_abbrev: Optional[str] = None,
short_output: Optional[bool] = False,
):
standings = Standings.select_season(season) standings = Standings.select_season(season)
# if standings.count() == 0: # if standings.count() == 0:
@ -30,55 +35,66 @@ async def get_standings(
standings = standings.where(Standings.team << t_query) standings = standings.where(Standings.team << t_query)
if league_abbrev is not None: if league_abbrev is not None:
l_query = Division.select().where(fn.Lower(Division.league_abbrev) == league_abbrev.lower()) l_query = Division.select().where(
fn.Lower(Division.league_abbrev) == league_abbrev.lower()
)
standings = standings.where(Standings.team.division << l_query) standings = standings.where(Standings.team.division << l_query)
if division_abbrev is not None: if division_abbrev is not None:
d_query = Division.select().where(fn.Lower(Division.division_abbrev) == division_abbrev.lower()) d_query = Division.select().where(
fn.Lower(Division.division_abbrev) == division_abbrev.lower()
)
standings = standings.where(Standings.team.division << d_query) standings = standings.where(Standings.team.division << d_query)
def win_pct(this_team_stan): def win_pct(this_team_stan):
if this_team_stan.wins + this_team_stan.losses == 0: if this_team_stan.wins + this_team_stan.losses == 0:
return 0 return 0
else: else:
return (this_team_stan.wins / (this_team_stan.wins + this_team_stan.losses)) + \ return (
(this_team_stan.run_diff * .000001) this_team_stan.wins / (this_team_stan.wins + this_team_stan.losses)
) + (this_team_stan.run_diff * 0.000001)
div_teams = [x for x in standings] div_teams = [x for x in standings]
div_teams.sort(key=lambda team: win_pct(team), reverse=True) div_teams.sort(key=lambda team: win_pct(team), reverse=True)
return_standings = { return_standings = {
'count': len(div_teams), "count": len(div_teams),
'standings': [model_to_dict(x, recurse=not short_output) for x in div_teams] "standings": [model_to_dict(x, recurse=not short_output) for x in div_teams],
} }
db.close() db.close()
return return_standings return return_standings
@router.get('/team/{team_id}') @router.get("/team/{team_id}")
@handle_db_errors @handle_db_errors
async def get_team_standings(team_id: int): async def get_team_standings(team_id: int):
this_stan = Standings.get_or_none(Standings.team_id == team_id) this_stan = Standings.get_or_none(Standings.team_id == team_id)
if this_stan is None: if this_stan is None:
raise HTTPException(status_code=404, detail=f'No standings found for team id {team_id}') raise HTTPException(
status_code=404, detail=f"No standings found for team id {team_id}"
)
return model_to_dict(this_stan) return model_to_dict(this_stan)
@router.patch('/{stan_id}', include_in_schema=PRIVATE_IN_SCHEMA) @router.patch("/{stan_id}", include_in_schema=PRIVATE_IN_SCHEMA)
@handle_db_errors @handle_db_errors
async def patch_standings( async def patch_standings(
stan_id, wins: Optional[int] = None, losses: Optional[int] = None, token: str = Depends(oauth2_scheme)): stan_id,
wins: Optional[int] = None,
losses: Optional[int] = None,
token: str = Depends(oauth2_scheme),
):
if not valid_token(token): if not valid_token(token):
logger.warning(f'patch_standings - Bad Token: {token}') logger.warning(f"patch_standings - Bad Token: {token}")
raise HTTPException(status_code=401, detail='Unauthorized') raise HTTPException(status_code=401, detail="Unauthorized")
try: try:
this_stan = Standings.get_by_id(stan_id) this_stan = Standings.get_by_id(stan_id)
except Exception as e: except Exception as e:
db.close() db.close()
raise HTTPException(status_code=404, detail=f'No team found with id {stan_id}') raise HTTPException(status_code=404, detail=f"No team found with id {stan_id}")
if wins: if wins:
this_stan.wins = wins this_stan.wins = wins
@ -91,35 +107,35 @@ async def patch_standings(
return model_to_dict(this_stan) return model_to_dict(this_stan)
@router.post('/s{season}/new', include_in_schema=PRIVATE_IN_SCHEMA) @router.post("/s{season}/new", include_in_schema=PRIVATE_IN_SCHEMA)
@handle_db_errors @handle_db_errors
async def post_standings(season: int, token: str = Depends(oauth2_scheme)): async def post_standings(season: int, token: str = Depends(oauth2_scheme)):
if not valid_token(token): if not valid_token(token):
logger.warning(f'post_standings - Bad Token: {token}') logger.warning(f"post_standings - Bad Token: {token}")
raise HTTPException(status_code=401, detail='Unauthorized') raise HTTPException(status_code=401, detail="Unauthorized")
new_teams = [] new_teams = []
all_teams = Team.select().where(Team.season == season) all_teams = Team.select().where(Team.season == season)
for x in all_teams: for x in all_teams:
new_teams.append(Standings({'team_id': x.id})) new_teams.append(Standings({"team_id": x.id}))
with db.atomic(): with db.atomic():
for batch in chunked(new_teams, 16): for batch in chunked(new_teams, 16):
Standings.insert_many(batch).on_conflict_ignore().execute() Standings.insert_many(batch).on_conflict_ignore().execute()
db.close() db.close()
return f'Inserted {len(new_teams)} standings' return f"Inserted {len(new_teams)} standings"
@router.post('/s{season}/recalculate', include_in_schema=PRIVATE_IN_SCHEMA) @router.post("/s{season}/recalculate", include_in_schema=PRIVATE_IN_SCHEMA)
@handle_db_errors @handle_db_errors
async def recalculate_standings(season: int, token: str = Depends(oauth2_scheme)): async def recalculate_standings(season: int, token: str = Depends(oauth2_scheme)):
if not valid_token(token): if not valid_token(token):
logger.warning(f'recalculate_standings - Bad Token: {token}') logger.warning(f"recalculate_standings - Bad Token: {token}")
raise HTTPException(status_code=401, detail='Unauthorized') raise HTTPException(status_code=401, detail="Unauthorized")
code = Standings.recalculate(season) code = Standings.recalculate(season)
db.close() db.close()
if code == 69: if code == 69:
raise HTTPException(status_code=500, detail=f'Error recreating Standings rows') raise HTTPException(status_code=500, detail=f"Error recreating Standings rows")
return f'Just recalculated standings for season {season}' return f"Just recalculated standings for season {season}"