Make primary key typing stricter (#904)

This commit is contained in:
Erik Vroon
2024-09-10 20:32:59 +02:00
committed by GitHub
parent b3073c0fa6
commit 388afa585a
51 changed files with 367 additions and 313 deletions

View File

@@ -7,7 +7,6 @@ from bracket.models.db.account import UserAccountType
from bracket.sql.users import delete_user_and_owned_clubs, get_expired_demo_users
from bracket.utils.asyncio import AsyncioTasksManager
from bracket.utils.logging import logger
from bracket.utils.types import assert_some
CronjobT = Callable[[], Awaitable[None]]
@@ -21,7 +20,7 @@ async def delete_demo_accounts() -> None:
for demo_user in demo_users:
assert demo_user.account_type is UserAccountType.DEMO
user_id = assert_some(demo_user.id)
user_id = demo_user.id
await delete_user_and_owned_clubs(user_id)

View File

@@ -40,7 +40,7 @@ async def schedule_all_unscheduled_matches(tournament_id: TournamentId) -> None:
for match in round_.matches:
if match.start_time is None and match.position_in_schedule is None:
await sql_reschedule_match_and_determine_duration_and_margin(
assert_some(match.id),
match.id,
court.id,
start_time,
position_in_schedule,
@@ -63,7 +63,7 @@ async def schedule_all_unscheduled_matches(tournament_id: TournamentId) -> None:
if match.start_time is None and match.position_in_schedule is None:
await sql_reschedule_match_and_determine_duration_and_margin(
assert_some(match.id),
match.id,
courts[-1].id,
start_time,
position_in_schedule,
@@ -92,7 +92,7 @@ async def reorder_matches_for_court(
last_start_time = tournament.start_time
for i, match_pos in enumerate(matches_this_court):
await sql_reschedule_match_and_determine_duration_and_margin(
assert_some(match_pos.match.id),
match_pos.match.id,
court_id,
last_start_time,
position_in_schedule=i,
@@ -151,7 +151,7 @@ async def update_start_times_of_matches(tournament_id: TournamentId) -> None:
scheduled_matches = get_scheduled_matches(stages)
for court in courts:
await reorder_matches_for_court(tournament, scheduled_matches, assert_some(court.id))
await reorder_matches_for_court(tournament, scheduled_matches, court.id)
def get_scheduled_matches(stages: list[StageWithStageItems]) -> list[MatchPosition]:

View File

@@ -22,13 +22,9 @@ def get_active_and_next_rounds(
active_round = next((round_ for round_ in stage_item.rounds if round_.is_active), None)
def is_round_in_future(round_: RoundWithMatches) -> bool:
return (
(assert_some(round_.id) > assert_some(active_round.id))
if active_round is not None
else True
)
return (round_.id > active_round.id) if active_round is not None else True
rounds_chronologically_sorted = sorted(stage_item.rounds, key=lambda r: assert_some(r.id))
rounds_chronologically_sorted = sorted(stage_item.rounds, key=lambda r: r.id)
next_round = next(
(round_ for round_ in rounds_chronologically_sorted if is_round_in_future(round_)),
None,
@@ -53,7 +49,7 @@ async def schedule_all_matches_for_swiss_round(
assert len(active_round.matches) <= len(courts)
for i, match in enumerate(active_round.matches):
court_id = assert_some(courts[i].id)
court_id = courts[i].id
last_match = (
next((m for m in matches_per_court[court_id][::-1] if m.match.id != match.id), None)
if court_id in matches_per_court
@@ -83,7 +79,7 @@ async def schedule_all_matches_for_swiss_round(
)
rescheduling_operations.append(
sql_reschedule_match_and_determine_duration_and_margin(
assert_some(last_match.match.id),
last_match.match.id,
court_id,
assert_some(last_match.match.start_time),
assert_some(last_match.match.position_in_schedule),
@@ -104,7 +100,7 @@ async def schedule_all_matches_for_swiss_round(
rescheduling_operations.append(
sql_reschedule_match_and_determine_duration_and_margin(
assert_some(match.id), court_id, start_time, pos_in_schedule, match, tournament
match.id, court_id, start_time, pos_in_schedule, match, tournament
)
)

View File

@@ -8,7 +8,7 @@ from bracket.logic.scheduling.round_robin import (
build_round_robin_stage_item,
get_number_of_rounds_to_create_round_robin,
)
from bracket.models.db.round import RoundToInsert
from bracket.models.db.round import RoundInsertable
from bracket.models.db.stage_item import StageItem, StageType
from bracket.models.db.stage_item_inputs import (
StageItemInputOptionFinal,
@@ -19,7 +19,7 @@ from bracket.models.db.util import StageWithStageItems
from bracket.sql.rounds import get_next_round_name, sql_create_round
from bracket.sql.stage_items import get_stage_item
from bracket.utils.id_types import StageId, TournamentId
from bracket.utils.types import assert_some
from tests.integration_tests.mocks import MOCK_NOW
async def create_rounds_for_new_stage_item(
@@ -38,16 +38,18 @@ async def create_rounds_for_new_stage_item(
for _ in range(rounds_count):
await sql_create_round(
RoundToInsert(
stage_item_id=assert_some(stage_item.id),
name=await get_next_round_name(tournament_id, assert_some(stage_item.id)),
RoundInsertable(
created=MOCK_NOW,
is_draft=False,
stage_item_id=stage_item.id,
name=await get_next_round_name(tournament_id, stage_item.id),
),
)
async def build_matches_for_stage_item(stage_item: StageItem, tournament_id: TournamentId) -> None:
await create_rounds_for_new_stage_item(tournament_id, stage_item)
stage_item_with_rounds = await get_stage_item(tournament_id, assert_some(stage_item.id))
stage_item_with_rounds = await get_stage_item(tournament_id, stage_item.id)
if stage_item_with_rounds is None:
raise ValueError(
@@ -73,7 +75,7 @@ def determine_available_inputs(
teams: list[FullTeamWithPlayers],
stages: list[StageWithStageItems],
) -> list[StageItemInputOptionTentative | StageItemInputOptionFinal]:
results_team_ids = [assert_some(team.id) for team in teams]
results_team_ids = [team.id for team in teams]
results_tentative = []
for stage in stages:

View File

@@ -5,7 +5,6 @@ from bracket.sql.matches import sql_create_match
from bracket.sql.rounds import get_rounds_for_stage_item
from bracket.sql.tournaments import sql_get_tournament
from bracket.utils.id_types import TournamentId
from bracket.utils.types import assert_some
def determine_matches_first_round(
@@ -18,7 +17,7 @@ def determine_matches_first_round(
second_input = stage_item.inputs[i + 1]
suggestions.append(
MatchCreateBody(
round_id=assert_some(round_.id),
round_id=round_.id,
court_id=None,
team1_id=first_input.team_id,
team1_winner_from_stage_item_id=first_input.winner_from_stage_item_id,
@@ -51,7 +50,7 @@ def determine_matches_subsequent_round(
suggestions.append(
MatchCreateBody(
round_id=assert_some(round_.id),
round_id=round_.id,
court_id=None,
team1_id=None,
team1_winner_from_stage_item_id=None,
@@ -59,8 +58,8 @@ def determine_matches_subsequent_round(
team2_id=None,
team2_winner_from_stage_item_id=None,
team2_winner_position=None,
team1_winner_from_match_id=assert_some(first_match.id),
team2_winner_from_match_id=assert_some(second_match.id),
team1_winner_from_match_id=first_match.id,
team2_winner_from_match_id=second_match.id,
duration_minutes=tournament.duration_minutes,
margin_minutes=tournament.margin_minutes,
custom_duration_minutes=None,

View File

@@ -62,7 +62,7 @@ async def set_team_ids_for_match(
stage_item_x_team_rankings,
)
await sql_update_team_ids_for_match(assert_some(match.id), team1_id, team2_id)
await sql_update_team_ids_for_match(match.id, team1_id, team2_id)
async def get_team_rankings_lookup_for_stage(

View File

@@ -47,7 +47,7 @@ def get_number_of_teams_played_per_team(
if isinstance(match, MatchWithDetailsDefinitive):
for team in match.teams:
if team.active and team.id not in excluded_team_ids:
result[assert_some(team.id)] += 1
result[team.id] += 1
return result
@@ -80,7 +80,7 @@ def get_possible_upcoming_matches_for_swiss(
)
for team in teams_to_schedule:
if team.id not in times_played_per_team:
times_played_per_team[assert_some(team.id)] = 0
times_played_per_team[team.id] = 0
min_times_played = min(times_played_per_team.values()) if len(times_played_per_team) > 0 else 0
@@ -100,8 +100,8 @@ def get_possible_upcoming_matches_for_swiss(
continue
times_played_min = min(
times_played_per_team[assert_some(team1.id)],
times_played_per_team[assert_some(team2.id)],
times_played_per_team[team1.id],
times_played_per_team[team2.id],
)
suggested_match = check_team_combination_adheres_to_filter(
team1, team2, filter_, is_recommended=times_played_min <= min_times_played

View File

@@ -5,7 +5,6 @@ from bracket.models.db.util import StageItemWithRounds
from bracket.sql.matches import sql_create_match
from bracket.sql.tournaments import sql_get_tournament
from bracket.utils.id_types import TournamentId
from bracket.utils.types import assert_some
def get_round_robin_combinations(team_count: int) -> list[list[tuple[int, int]]]:
@@ -48,7 +47,7 @@ async def build_round_robin_stage_item(
team_1, team_2 = stage_item.inputs[team_1_id], stage_item.inputs[team_2_id]
match = MatchCreateBody(
round_id=assert_some(round_.id),
round_id=round_.id,
team1_id=team_1.team_id,
team1_winner_from_stage_item_id=team_1.winner_from_stage_item_id,
team1_winner_position=team_1.winner_position,

View File

@@ -9,7 +9,6 @@ from bracket.sql.rounds import get_rounds_for_stage_item
from bracket.sql.stages import get_full_tournament_details
from bracket.sql.teams import get_teams_with_members
from bracket.utils.id_types import StageItemId, TournamentId
from bracket.utils.types import assert_some
async def get_draft_round_in_stage_item(
@@ -40,7 +39,7 @@ async def get_upcoming_matches_for_swiss_round(
if not round_.is_draft:
raise HTTPException(400, "There is no draft round, so no matches can be scheduled.")
rounds = await get_rounds_for_stage_item(tournament_id, assert_some(stage_item.id))
rounds = await get_rounds_for_stage_item(tournament_id, stage_item.id)
teams = await get_teams_with_members(tournament_id, only_active_teams=True)
return get_possible_upcoming_matches_for_swiss(match_filter, rounds, teams)

View File

@@ -14,7 +14,6 @@ from bracket.sql.clubs import create_club
from bracket.sql.rankings import sql_create_ranking
from bracket.sql.tournaments import sql_create_tournament
from bracket.utils.id_types import UserId
from bracket.utils.types import assert_some
if TYPE_CHECKING:
from bracket.models.db.user import UserBase
@@ -80,7 +79,7 @@ async def setup_demo_account(user_id: UserId) -> None:
tournament = TournamentBody(
name="Demo Tournament",
club_id=assert_some(club_inserted.id),
club_id=club_inserted.id,
start_time=datetime_utc.future(hours=1),
dashboard_public=False,
players_can_be_in_multiple_teams=False,

View File

@@ -9,7 +9,6 @@ from bracket.sql.stages import get_full_tournament_details, sql_delete_stage
from bracket.sql.teams import sql_delete_teams_of_tournament
from bracket.sql.tournaments import sql_delete_tournament, sql_get_tournament
from bracket.utils.id_types import TournamentId
from bracket.utils.types import assert_some
async def get_tournament_logo_path(tournament_id: TournamentId) -> str | None:
@@ -36,7 +35,7 @@ async def sql_delete_tournament_completely(tournament_id: TournamentId) -> None:
for stage_item in stage.stage_items:
await sql_delete_stage_item(stage_item.id)
await sql_delete_stage(tournament_id, assert_some(stage.id))
await sql_delete_stage(tournament_id, stage.id)
for ranking in await get_all_rankings_in_tournament(tournament_id):
await sql_delete_ranking(tournament_id, ranking.id)

View File

@@ -4,12 +4,15 @@ from bracket.models.db.shared import BaseModelORM
from bracket.utils.id_types import ClubId
class Club(BaseModelORM):
id: ClubId | None = None
class ClubInsertable(BaseModelORM):
name: str
created: datetime_utc
class Club(ClubInsertable):
id: ClubId
class ClubCreateBody(BaseModelORM):
name: str

View File

@@ -4,13 +4,16 @@ from bracket.models.db.shared import BaseModelORM
from bracket.utils.id_types import CourtId, TournamentId
class Court(BaseModelORM):
id: CourtId | None = None
class CourtInsertable(BaseModelORM):
name: str
created: datetime_utc
tournament_id: TournamentId
class Court(CourtInsertable):
id: CourtId
class CourtBody(BaseModelORM):
name: str

View File

@@ -10,8 +10,7 @@ from bracket.utils.id_types import CourtId, MatchId, PlayerId, RoundId, StageIte
from bracket.utils.types import assert_some
class MatchBase(BaseModelORM):
id: MatchId | None = None
class MatchBaseInsertable(BaseModelORM):
created: datetime_utc
start_time: datetime_utc | None = None
duration_minutes: int
@@ -32,7 +31,7 @@ class MatchBase(BaseModelORM):
)
class Match(MatchBase):
class MatchInsertable(MatchBaseInsertable):
team1_id: TeamId | None = None
team2_id: TeamId | None = None
team1_winner_position: int | None = None
@@ -49,6 +48,10 @@ class Match(MatchBase):
return 1 if self.team1_score > self.team2_score else 0
class Match(MatchInsertable):
id: MatchId
class MatchWithDetails(Match):
court: Court | None = None

View File

@@ -7,8 +7,7 @@ from bracket.models.db.shared import BaseModelORM
from bracket.utils.id_types import PlayerId, TournamentId
class Player(BaseModelORM):
id: PlayerId | None = None
class PlayerInsertable(BaseModelORM):
active: bool
name: str
created: datetime_utc
@@ -19,6 +18,10 @@ class Player(BaseModelORM):
draws: int = 0
losses: int = 0
class Player(PlayerInsertable):
id: PlayerId
def __hash__(self) -> int:
return self.id if self.id is not None else int(self.created.timestamp())

View File

@@ -1,8 +1,7 @@
from bracket.models.db.shared import BaseModelORM
from bracket.utils.id_types import PlayerId, PlayerXTeamId, TeamId
from bracket.utils.id_types import PlayerId, TeamId
class PlayerXTeam(BaseModelORM):
id: PlayerXTeamId | None = None
class PlayerXTeamInsertable(BaseModelORM):
player_id: PlayerId
team_id: TeamId

View File

@@ -4,15 +4,18 @@ from bracket.models.db.shared import BaseModelORM
from bracket.utils.id_types import RoundId, StageItemId
class Round(BaseModelORM):
id: RoundId | None = None
stage_item_id: StageItemId
class RoundInsertable(BaseModelORM):
created: datetime_utc
stage_item_id: StageItemId
is_draft: bool
is_active: bool = False
name: str
class Round(RoundInsertable):
id: RoundId
class RoundUpdateBody(BaseModelORM):
name: str
is_draft: bool
@@ -22,9 +25,3 @@ class RoundUpdateBody(BaseModelORM):
class RoundCreateBody(BaseModelORM):
name: str | None = None
stage_item_id: StageItemId
class RoundToInsert(RoundUpdateBody):
stage_item_id: StageItemId
is_draft: bool = False
is_active: bool = False

View File

@@ -6,14 +6,17 @@ from bracket.models.db.shared import BaseModelORM
from bracket.utils.id_types import StageId, TournamentId
class Stage(BaseModelORM):
id: StageId | None = None
class StageInsertable(BaseModelORM):
tournament_id: TournamentId
name: str
created: datetime_utc
is_active: bool
class Stage(StageInsertable):
id: StageId
class StageUpdateBody(BaseModelORM):
name: str

View File

@@ -20,8 +20,7 @@ class StageType(EnumAutoStr):
return self in [StageType.SWISS]
class StageItemToInsert(BaseModelORM):
id: StageItemId | None = None
class StageItemInsertable(BaseModelORM):
stage_id: StageId
name: str
created: datetime_utc
@@ -30,7 +29,7 @@ class StageItemToInsert(BaseModelORM):
ranking_id: RankingId | None = None
class StageItem(StageItemToInsert):
class StageItem(StageItemInsertable):
id: StageItemId

View File

@@ -7,7 +7,7 @@ from bracket.utils.id_types import MatchId, StageItemId, StageItemInputId, TeamI
class StageItemInputBase(BaseModelORM):
id: StageItemInputId | None = None
id: StageItemInputId
slot: int
tournament_id: TournamentId
stage_item_id: StageItemId | None = None

View File

@@ -12,11 +12,9 @@ from bracket.logic.ranking.statistics import START_ELO
from bracket.models.db.player import Player
from bracket.models.db.shared import BaseModelORM
from bracket.utils.id_types import PlayerId, TeamId, TournamentId
from bracket.utils.types import assert_some
class Team(BaseModelORM):
id: TeamId | None = None
class TeamInsertable(BaseModelORM):
created: datetime_utc
name: str
tournament_id: TournamentId
@@ -29,8 +27,12 @@ class Team(BaseModelORM):
logo_path: str | None = None
class Team(TeamInsertable):
id: TeamId
class TeamWithPlayers(BaseModel):
id: TeamId | None = None
id: TeamId
players: list[Player]
elo_score: Decimal = START_ELO
swiss_score: Decimal = Decimal("0.0")
@@ -42,7 +44,7 @@ class TeamWithPlayers(BaseModel):
@property
def player_ids(self) -> list[PlayerId]:
return [assert_some(player.id) for player in self.players]
return [player.id for player in self.players]
@field_validator("players", mode="before")
def handle_players(values: list[Player]) -> list[Player]: # type: ignore[misc]
@@ -88,15 +90,3 @@ class TeamBody(BaseModelORM):
class TeamMultiBody(BaseModelORM):
names: str = Field(..., min_length=1)
active: bool
class TeamToInsert(BaseModelORM):
created: datetime_utc
name: str
tournament_id: TournamentId
active: bool
elo_score: Decimal = Decimal("0.0")
swiss_score: Decimal = Decimal("0.0")
wins: int = 0
draws: int = 0
losses: int = 0

View File

@@ -6,8 +6,7 @@ from bracket.utils.id_types import ClubId, TournamentId
from bracket.utils.pydantic import EmptyStrToNone
class Tournament(BaseModelORM):
id: TournamentId | None = None
class TournamentInsertable(BaseModelORM):
club_id: ClubId
name: str
created: datetime_utc
@@ -21,6 +20,10 @@ class Tournament(BaseModelORM):
auto_assign_courts: bool
class Tournament(TournamentInsertable):
id: TournamentId
class TournamentUpdateBody(BaseModelORM):
start_time: datetime_utc
name: str

View File

@@ -14,7 +14,6 @@ if TYPE_CHECKING:
class UserBase(BaseModelORM):
id: UserId | None = None
email: str
name: str
created: datetime_utc
@@ -27,12 +26,16 @@ class UserBase(BaseModelORM):
return subscription_lookup[self.account_type]
class User(UserBase):
class UserInsertable(UserBase):
password_hash: str | None = None
class User(UserInsertable):
id: UserId
class UserPublic(UserBase):
pass
id: UserId
class UserToUpdate(BaseModel):

View File

@@ -10,8 +10,11 @@ class UserXClubRelation(EnumAutoStr):
COLLABORATOR = auto()
class UserXClub(BaseModelORM):
id: UserXClubId | None = None
class UserXClubInsertable(BaseModelORM):
user_id: UserId
club_id: ClubId
relation: UserXClubRelation
class UserXClub(UserXClubInsertable):
id: UserXClubId

View File

@@ -103,7 +103,7 @@ async def user_authenticated_for_tournament(
) -> UserPublic:
user = await check_jwt_and_get_user(token)
if not user or not await get_user_access_to_tournament(tournament_id, assert_some(user.id)):
if not user or not await get_user_access_to_tournament(tournament_id, user.id):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
@@ -118,7 +118,7 @@ async def user_authenticated_for_club(
) -> UserPublic:
user = await check_jwt_and_get_user(token)
if not user or not await get_user_access_to_club(club_id, assert_some(user.id)):
if not user or not await get_user_access_to_club(club_id, user.id):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
@@ -134,9 +134,7 @@ async def user_authenticated_or_public_dashboard(
try:
token: str = assert_some(await oauth2_scheme(request))
user = await check_jwt_and_get_user(token)
if user is not None and await get_user_access_to_tournament(
tournament_id, assert_some(user.id)
):
if user is not None and await get_user_access_to_tournament(tournament_id, user.id):
return user
except HTTPException:
pass

View File

@@ -8,23 +8,22 @@ from bracket.routes.models import ClubResponse, ClubsResponse, SuccessResponse
from bracket.sql.clubs import create_club, get_clubs_for_user_id, sql_delete_club, sql_update_club
from bracket.utils.errors import ForeignKey, check_foreign_key_violation
from bracket.utils.id_types import ClubId
from bracket.utils.types import assert_some
router = APIRouter()
@router.get("/clubs", response_model=ClubsResponse)
async def get_clubs(user: UserPublic = Depends(user_authenticated)) -> ClubsResponse:
return ClubsResponse(data=await get_clubs_for_user_id(assert_some(user.id)))
return ClubsResponse(data=await get_clubs_for_user_id(user.id))
@router.post("/clubs", response_model=ClubResponse)
async def create_new_club(
club: ClubCreateBody, user: UserPublic = Depends(user_authenticated)
) -> ClubResponse:
existing_clubs = await get_clubs_for_user_id(assert_some(user.id))
existing_clubs = await get_clubs_for_user_id(user.id)
check_requirement(existing_clubs, user, "max_clubs")
return ClubResponse(data=await create_club(club, assert_some(user.id)))
return ClubResponse(data=await create_club(club, user.id))
@router.delete("/clubs/{club_id}", response_model=SuccessResponse)

View File

@@ -75,7 +75,7 @@ async def delete_match(
) -> SuccessResponse:
round_ = await get_round_by_id(tournament_id, match.round_id)
await sql_delete_match(assert_some(match.id))
await sql_delete_match(match.id)
await recalculate_ranking_for_stage_item_id(tournament_id, assert_some(round_).stage_item_id)
return SuccessResponse()

View File

@@ -9,7 +9,7 @@ from bracket.logic.subscriptions import check_requirement
from bracket.models.db.round import (
Round,
RoundCreateBody,
RoundToInsert,
RoundInsertable,
RoundUpdateBody,
)
from bracket.models.db.user import UserPublic
@@ -26,6 +26,7 @@ from bracket.sql.stage_items import get_stage_item
from bracket.sql.stages import get_full_tournament_details
from bracket.sql.validation import check_foreign_keys_belong_to_tournament
from bracket.utils.id_types import RoundId, TournamentId
from tests.integration_tests.mocks import MOCK_NOW
router = APIRouter()
@@ -84,7 +85,9 @@ async def create_round(
)
round_id = await sql_create_round(
RoundToInsert(
RoundInsertable(
created=MOCK_NOW,
is_draft=False,
stage_item_id=round_body.stage_item_id,
name=await get_next_round_name(tournament_id, round_body.stage_item_id),
),

View File

@@ -9,7 +9,13 @@ from heliclockter import datetime_utc
from bracket.database import database
from bracket.logic.subscriptions import check_requirement
from bracket.logic.teams import get_team_logo_path
from bracket.models.db.team import FullTeamWithPlayers, Team, TeamBody, TeamMultiBody, TeamToInsert
from bracket.models.db.team import (
FullTeamWithPlayers,
Team,
TeamBody,
TeamInsertable,
TeamMultiBody,
)
from bracket.models.db.user import UserPublic
from bracket.routes.auth import (
user_authenticated_for_tournament,
@@ -91,7 +97,7 @@ async def update_team_by_id(
),
values=team_body.model_dump(exclude={"player_ids"}),
)
await update_team_members(assert_some(team.id), tournament_id, team_body.player_ids)
await update_team_members(team.id, tournament_id, team_body.player_ids)
return SingleTeamResponse(
data=assert_some(
@@ -113,7 +119,7 @@ async def update_team_logo(
_: UserPublic = Depends(user_authenticated_for_tournament),
team: Team = Depends(team_dependency),
) -> SingleTeamResponse:
team_id = assert_some(team.id)
team_id = team.id
old_logo_path = await get_team_logo_path(tournament_id, team_id)
filename: str | None = None
new_logo_path: str | None = None
@@ -157,7 +163,7 @@ async def delete_team(
ForeignKey.matches_team2_id_fkey,
}
):
await sql_delete_team(tournament_id, assert_some(team.id))
await sql_delete_team(tournament_id, team.id)
return SuccessResponse()
@@ -175,7 +181,7 @@ async def create_team(
last_record_id = await database.execute(
query=teams.insert(),
values=TeamToInsert(
values=TeamInsertable(
**team_to_insert.model_dump(exclude={"player_ids"}),
created=datetime_utc.now(),
tournament_id=tournament_id,
@@ -201,7 +207,7 @@ async def create_multiple_teams(
for team_name in team_names:
await database.execute(
query=teams.insert(),
values=TeamToInsert(
values=TeamInsertable(
name=team_name,
active=team_body.active,
created=datetime_utc.now(),

View File

@@ -42,7 +42,6 @@ from bracket.utils.errors import (
)
from bracket.utils.id_types import TournamentId
from bracket.utils.logging import logger
from bracket.utils.types import assert_some
router = APIRouter()
unauthorized_exception = HTTPException(
@@ -84,7 +83,7 @@ async def get_tournaments(
return TournamentsResponse(data=[tournament])
case _, _ if isinstance(user, UserPublic):
user_club_ids = await get_which_clubs_has_user_access_to(assert_some(user.id))
user_club_ids = await get_which_clubs_has_user_access_to(user.id)
return TournamentsResponse(
data=await sql_get_tournaments(tuple(user_club_ids), endpoint_name)
)
@@ -131,9 +130,7 @@ async def create_tournament(
existing_tournaments = await sql_get_tournaments((tournament_to_insert.club_id,))
check_requirement(existing_tournaments, user, "max_tournaments")
has_access_to_club = await get_user_access_to_club(
tournament_to_insert.club_id, assert_some(user.id)
)
has_access_to_club = await get_user_access_to_club(tournament_to_insert.club_id, user.id)
if not has_access_to_club:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,

View File

@@ -9,7 +9,7 @@ from bracket.logic.subscriptions import setup_demo_account
from bracket.models.db.account import UserAccountType
from bracket.models.db.user import (
DemoUserToRegister,
User,
UserInsertable,
UserPasswordToUpdate,
UserPublic,
UserToRegister,
@@ -60,7 +60,7 @@ async def update_user_details(
if user_public.id != user_id:
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Can't change details of this user")
await update_user(assert_some(user_public.id), user_to_update)
await update_user(user_public.id, user_to_update)
user_updated = await get_user_by_id(user_id)
return UserPublicResponse(data=assert_some(user_updated))
@@ -72,7 +72,7 @@ async def put_user_password(
user_public: UserPublic = Depends(user_authenticated),
) -> SuccessResponse:
assert user_public.id == user_id
await update_user_password(assert_some(user_public.id), hash_password(user_to_update.password))
await update_user_password(user_public.id, hash_password(user_to_update.password))
return SuccessResponse()
@@ -84,7 +84,7 @@ async def register_user(user_to_register: UserToRegister) -> TokenResponse:
if not await verify_captcha_token(user_to_register.captcha_token):
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Failed to validate captcha")
user = User(
user = UserInsertable(
email=user_to_register.email,
password_hash=hash_password(user_to_register.password),
name=user_to_register.name,
@@ -100,9 +100,7 @@ async def register_user(user_to_register: UserToRegister) -> TokenResponse:
data={"user": user_created.email}, expires_delta=access_token_expires
)
return TokenResponse(
data=Token(
access_token=access_token, token_type="bearer", user_id=assert_some(user_created.id)
)
data=Token(access_token=access_token, token_type="bearer", user_id=user_created.id)
)
@@ -117,7 +115,7 @@ async def register_demo_user(user_to_register: DemoUserToRegister) -> TokenRespo
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Failed to validate captcha")
username = f"demo-{uuid4()}"
user = User(
user = UserInsertable(
email=f"{username}@example.org",
password_hash=hash_password(str(uuid4())),
name=username,
@@ -132,9 +130,7 @@ async def register_demo_user(user_to_register: DemoUserToRegister) -> TokenRespo
access_token = create_access_token(
data={"user": user_created.email}, expires_delta=access_token_expires
)
await setup_demo_account(assert_some(user_created.id))
await setup_demo_account(user_created.id)
return TokenResponse(
data=Token(
access_token=access_token, token_type="bearer", user_id=assert_some(user_created.id)
)
data=Token(access_token=access_token, token_type="bearer", user_id=user_created.id)
)

View File

@@ -28,7 +28,7 @@ async def create_club(club: ClubCreateBody, user_id: UserId) -> Club:
club_created = Club.model_validate(dict(result._mapping))
await sql_give_user_access_to_club(user_id, assert_some(club_created.id))
await sql_give_user_access_to_club(user_id, club_created.id)
return club_created

View File

@@ -1,12 +1,12 @@
from bracket.database import database
from bracket.models.db.round import RoundToInsert
from bracket.models.db.round import RoundInsertable
from bracket.models.db.util import RoundWithMatches
from bracket.sql.stage_items import get_stage_item
from bracket.sql.stages import get_full_tournament_details
from bracket.utils.id_types import RoundId, StageItemId, TournamentId
async def sql_create_round(round_: RoundToInsert) -> RoundId:
async def sql_create_round(round_: RoundInsertable) -> RoundId:
query = """
INSERT INTO rounds (created, is_draft, is_active, name, stage_item_id)
VALUES (NOW(), :is_draft, :is_active, :name, :stage_item_id)

View File

@@ -1,7 +1,7 @@
from bracket.database import database
from bracket.logic.tournaments import sql_delete_tournament_completely
from bracket.models.db.account import UserAccountType
from bracket.models.db.user import User, UserInDB, UserPublic, UserToUpdate
from bracket.models.db.user import User, UserInDB, UserInsertable, UserPublic, UserToUpdate
from bracket.schema import users
from bracket.sql.clubs import get_clubs_for_user_id, sql_delete_club
from bracket.sql.tournaments import sql_get_tournaments
@@ -87,7 +87,7 @@ async def get_expired_demo_users() -> list[UserPublic]:
return [UserPublic.model_validate(demo_user) for demo_user in result]
async def create_user(user: User) -> User:
async def create_user(user: UserInsertable) -> User:
query = """
INSERT INTO users (email, name, password_hash, created, account_type)
VALUES (:email, :name, :password_hash, :created, :account_type)
@@ -130,10 +130,10 @@ async def get_user(email: str) -> UserInDB | None:
async def delete_user_and_owned_clubs(user_id: UserId) -> None:
for club in await get_clubs_for_user_id(user_id):
club_id = assert_some(club.id)
club_id = club.id
for tournament in await sql_get_tournaments((club_id,), None):
tournament_id = assert_some(tournament.id)
tournament_id = tournament.id
await sql_delete_tournament_completely(tournament_id)
await sql_delete_club(club_id)

View File

@@ -10,23 +10,23 @@ from bracket.logic.ranking.elo import (
)
from bracket.logic.scheduling.builder import build_matches_for_stage_item
from bracket.models.db.account import UserAccountType
from bracket.models.db.club import Club
from bracket.models.db.court import Court
from bracket.models.db.club import ClubInsertable
from bracket.models.db.court import CourtInsertable
from bracket.models.db.match import Match, MatchBody
from bracket.models.db.player import Player
from bracket.models.db.player_x_team import PlayerXTeam
from bracket.models.db.player import PlayerInsertable
from bracket.models.db.player_x_team import PlayerXTeamInsertable
from bracket.models.db.ranking import RankingInsertable
from bracket.models.db.round import Round
from bracket.models.db.stage import Stage
from bracket.models.db.stage_item import StageItem, StageItemCreateBody
from bracket.models.db.round import RoundInsertable
from bracket.models.db.stage import StageInsertable
from bracket.models.db.stage_item import StageItemCreateBody, StageItemInsertable
from bracket.models.db.stage_item_inputs import (
StageItemInputCreateBodyFinal,
StageItemInputCreateBodyTentative,
)
from bracket.models.db.team import Team
from bracket.models.db.tournament import Tournament
from bracket.models.db.user import User
from bracket.models.db.user_x_club import UserXClub, UserXClubRelation
from bracket.models.db.team import TeamInsertable
from bracket.models.db.tournament import TournamentInsertable
from bracket.models.db.user import UserInsertable
from bracket.models.db.user_x_club import UserXClubInsertable, UserXClubRelation
from bracket.schema import (
clubs,
courts,
@@ -102,7 +102,7 @@ async def create_admin_user() -> UserId:
assert config.admin_password
user = await create_user(
User(
UserInsertable(
name="Admin",
email=config.admin_email,
password_hash=hash_password(config.admin_password),
@@ -110,7 +110,7 @@ async def create_admin_user() -> UserId:
account_type=UserAccountType.REGULAR,
)
)
return assert_some(user.id)
return user.id
async def init_db_when_empty() -> UserId | None:
@@ -144,18 +144,18 @@ async def sql_create_dev_db() -> UserId:
alembic_stamp_head()
table_lookup: dict[type, Table] = {
User: users,
Club: clubs,
Stage: stages,
Team: teams,
UserXClub: users_x_clubs,
PlayerXTeam: players_x_teams,
Player: players,
Round: rounds,
UserInsertable: users,
ClubInsertable: clubs,
StageInsertable: stages,
TeamInsertable: teams,
UserXClubInsertable: users_x_clubs,
PlayerXTeamInsertable: players_x_teams,
PlayerInsertable: players,
RoundInsertable: rounds,
Match: matches,
Tournament: tournaments,
Court: courts,
StageItem: stage_items,
TournamentInsertable: tournaments,
CourtInsertable: courts,
StageItemInsertable: stage_items,
RankingInsertable: rankings,
}
@@ -174,12 +174,15 @@ async def sql_create_dev_db() -> UserId:
club_id_1 = await insert_dummy(DUMMY_CLUB, ClubId)
await insert_dummy(
UserXClub(user_id=user_id_1, club_id=club_id_1, relation=UserXClubRelation.OWNER), int
UserXClubInsertable(user_id=user_id_1, club_id=club_id_1, relation=UserXClubRelation.OWNER),
int,
)
if real_user_id is not None:
await insert_dummy(
UserXClub(user_id=real_user_id, club_id=club_id_1, relation=UserXClubRelation.OWNER),
UserXClubInsertable(
user_id=real_user_id, club_id=club_id_1, relation=UserXClubRelation.OWNER
),
int,
)

View File

@@ -4,18 +4,18 @@ from zoneinfo import ZoneInfo
from heliclockter import datetime_utc
from bracket.models.db.account import UserAccountType
from bracket.models.db.club import Club
from bracket.models.db.court import Court
from bracket.models.db.match import Match
from bracket.models.db.player import Player
from bracket.models.db.player_x_team import PlayerXTeam
from bracket.models.db.club import ClubInsertable
from bracket.models.db.court import CourtInsertable
from bracket.models.db.match import MatchInsertable
from bracket.models.db.player import PlayerInsertable
from bracket.models.db.player_x_team import PlayerXTeamInsertable
from bracket.models.db.ranking import RankingInsertable
from bracket.models.db.round import Round
from bracket.models.db.stage import Stage
from bracket.models.db.stage_item import StageItemToInsert, StageType
from bracket.models.db.team import Team
from bracket.models.db.tournament import Tournament
from bracket.models.db.user import User
from bracket.models.db.round import RoundInsertable
from bracket.models.db.stage import StageInsertable
from bracket.models.db.stage_item import StageItemInsertable, StageType
from bracket.models.db.team import TeamInsertable
from bracket.models.db.tournament import TournamentInsertable
from bracket.models.db.user import UserInsertable
from bracket.utils.id_types import (
ClubId,
CourtId,
@@ -34,12 +34,12 @@ DUMMY_MOCK_TIME = datetime_utc(2022, 1, 11, 4, 32, 11, tzinfo=ZoneInfo("UTC"))
# We don't know any db IDs here, so we use a placeholder for foreign keys.
DB_PLACEHOLDER_ID = -42
DUMMY_CLUB = Club(
DUMMY_CLUB = ClubInsertable(
name="Some Cool Club",
created=DUMMY_MOCK_TIME,
)
DUMMY_TOURNAMENT = Tournament(
DUMMY_TOURNAMENT = TournamentInsertable(
club_id=ClubId(DB_PLACEHOLDER_ID),
name="Some Cool Tournament",
created=DUMMY_MOCK_TIME,
@@ -53,21 +53,21 @@ DUMMY_TOURNAMENT = Tournament(
margin_minutes=5,
)
DUMMY_STAGE1 = Stage(
DUMMY_STAGE1 = StageInsertable(
tournament_id=TournamentId(DB_PLACEHOLDER_ID),
created=DUMMY_MOCK_TIME,
is_active=True,
name="Group Stage",
)
DUMMY_STAGE2 = Stage(
DUMMY_STAGE2 = StageInsertable(
tournament_id=TournamentId(DB_PLACEHOLDER_ID),
created=DUMMY_MOCK_TIME,
is_active=False,
name="Knockout Stage",
)
DUMMY_STAGE_ITEM1 = StageItemToInsert(
DUMMY_STAGE_ITEM1 = StageItemInsertable(
stage_id=StageId(DB_PLACEHOLDER_ID),
ranking_id=RankingId(DB_PLACEHOLDER_ID),
created=DUMMY_MOCK_TIME,
@@ -76,7 +76,7 @@ DUMMY_STAGE_ITEM1 = StageItemToInsert(
name="Group A",
)
DUMMY_STAGE_ITEM2 = StageItemToInsert(
DUMMY_STAGE_ITEM2 = StageItemInsertable(
stage_id=StageId(DB_PLACEHOLDER_ID),
ranking_id=RankingId(DB_PLACEHOLDER_ID),
created=DUMMY_MOCK_TIME,
@@ -85,7 +85,7 @@ DUMMY_STAGE_ITEM2 = StageItemToInsert(
name="Group B",
)
DUMMY_STAGE_ITEM3 = StageItemToInsert(
DUMMY_STAGE_ITEM3 = StageItemInsertable(
stage_id=StageId(DB_PLACEHOLDER_ID),
ranking_id=RankingId(DB_PLACEHOLDER_ID),
created=DUMMY_MOCK_TIME,
@@ -94,28 +94,28 @@ DUMMY_STAGE_ITEM3 = StageItemToInsert(
name="Bracket A",
)
DUMMY_ROUND1 = Round(
DUMMY_ROUND1 = RoundInsertable(
stage_item_id=StageItemId(DB_PLACEHOLDER_ID),
created=DUMMY_MOCK_TIME,
is_draft=False,
name="Round 1",
)
DUMMY_ROUND2 = Round(
DUMMY_ROUND2 = RoundInsertable(
stage_item_id=StageItemId(DB_PLACEHOLDER_ID),
created=DUMMY_MOCK_TIME,
is_draft=True,
name="Round 2",
)
DUMMY_ROUND3 = Round(
DUMMY_ROUND3 = RoundInsertable(
stage_item_id=StageItemId(DB_PLACEHOLDER_ID),
created=DUMMY_MOCK_TIME,
is_draft=False,
name="Round 3",
)
DUMMY_MATCH1 = Match(
DUMMY_MATCH1 = MatchInsertable(
created=DUMMY_MOCK_TIME,
start_time=DUMMY_MOCK_TIME,
round_id=RoundId(DB_PLACEHOLDER_ID),
@@ -137,7 +137,7 @@ DUMMY_MATCH1 = Match(
position_in_schedule=1,
)
DUMMY_USER = User(
DUMMY_USER = UserInsertable(
email="admin@example.com",
name="Admin",
password_hash=hash_password("adminadmin"),
@@ -145,28 +145,28 @@ DUMMY_USER = User(
account_type=UserAccountType.REGULAR,
)
DUMMY_TEAM1 = Team(
DUMMY_TEAM1 = TeamInsertable(
created=DUMMY_MOCK_TIME,
name="Team 1",
tournament_id=TournamentId(DB_PLACEHOLDER_ID),
active=True,
)
DUMMY_TEAM2 = Team(
DUMMY_TEAM2 = TeamInsertable(
created=DUMMY_MOCK_TIME,
name="Team 2",
tournament_id=TournamentId(DB_PLACEHOLDER_ID),
active=True,
)
DUMMY_TEAM3 = Team(
DUMMY_TEAM3 = TeamInsertable(
created=DUMMY_MOCK_TIME,
name="Team 3",
tournament_id=TournamentId(DB_PLACEHOLDER_ID),
active=True,
)
DUMMY_TEAM4 = Team(
DUMMY_TEAM4 = TeamInsertable(
created=DUMMY_MOCK_TIME,
name="Team 4",
tournament_id=TournamentId(DB_PLACEHOLDER_ID),
@@ -174,74 +174,74 @@ DUMMY_TEAM4 = Team(
)
DUMMY_PLAYER1 = Player(
DUMMY_PLAYER1 = PlayerInsertable(
name="Player 01",
active=True,
created=DUMMY_MOCK_TIME,
tournament_id=TournamentId(DB_PLACEHOLDER_ID),
)
DUMMY_PLAYER2 = Player(
DUMMY_PLAYER2 = PlayerInsertable(
name="Player 02",
active=True,
created=DUMMY_MOCK_TIME,
tournament_id=TournamentId(DB_PLACEHOLDER_ID),
)
DUMMY_PLAYER3 = Player(
DUMMY_PLAYER3 = PlayerInsertable(
name="Player 03",
active=True,
created=DUMMY_MOCK_TIME,
tournament_id=TournamentId(DB_PLACEHOLDER_ID),
)
DUMMY_PLAYER4 = Player(
DUMMY_PLAYER4 = PlayerInsertable(
name="Player 04",
active=True,
created=DUMMY_MOCK_TIME,
tournament_id=TournamentId(DB_PLACEHOLDER_ID),
)
DUMMY_PLAYER5 = Player(
DUMMY_PLAYER5 = PlayerInsertable(
name="Player 05",
active=True,
created=DUMMY_MOCK_TIME,
tournament_id=TournamentId(DB_PLACEHOLDER_ID),
)
DUMMY_PLAYER6 = Player(
DUMMY_PLAYER6 = PlayerInsertable(
name="Player 06",
active=True,
created=DUMMY_MOCK_TIME,
tournament_id=TournamentId(DB_PLACEHOLDER_ID),
)
DUMMY_PLAYER7 = Player(
DUMMY_PLAYER7 = PlayerInsertable(
name="Player 07",
active=True,
created=DUMMY_MOCK_TIME,
tournament_id=TournamentId(DB_PLACEHOLDER_ID),
)
DUMMY_PLAYER8 = Player(
DUMMY_PLAYER8 = PlayerInsertable(
name="Player 08",
active=True,
created=DUMMY_MOCK_TIME,
tournament_id=TournamentId(DB_PLACEHOLDER_ID),
)
DUMMY_PLAYER_X_TEAM = PlayerXTeam(
DUMMY_PLAYER_X_TEAM = PlayerXTeamInsertable(
player_id=PlayerId(DB_PLACEHOLDER_ID),
team_id=TeamId(DB_PLACEHOLDER_ID),
)
DUMMY_COURT1 = Court(
DUMMY_COURT1 = CourtInsertable(
name="Court 1",
created=DUMMY_MOCK_TIME,
tournament_id=TournamentId(DB_PLACEHOLDER_ID),
)
DUMMY_COURT2 = Court(
DUMMY_COURT2 = CourtInsertable(
name="Court 2",
created=DUMMY_MOCK_TIME,
tournament_id=TournamentId(DB_PLACEHOLDER_ID),

View File

@@ -10,14 +10,13 @@ from bracket.config import config
from bracket.database import database
from bracket.logger import get_logger
from bracket.models.db.account import UserAccountType
from bracket.models.db.user import User
from bracket.models.db.user import UserInsertable
from bracket.sql.users import (
check_whether_email_is_in_use,
create_user,
)
from bracket.utils.db_init import sql_create_dev_db
from bracket.utils.security import hash_password
from bracket.utils.types import assert_some
logger = get_logger("cli")
@@ -72,7 +71,7 @@ async def create_dev_db() -> None:
@click.option("--name", prompt="Name", help="The name associated with the account.")
@run_async
async def register_user(email: str, password: str, name: str) -> None:
user = User(
user = UserInsertable(
email=email,
password_hash=hash_password(password),
name=name,
@@ -83,7 +82,6 @@ async def register_user(email: str, password: str, name: str) -> None:
logger.error("Email address already in use")
raise SystemExit(1)
user_created = await create_user(user)
assert_some(user_created.id)
logger.info(f"Created user with id: {user_created.id}")

View File

@@ -19,7 +19,6 @@ from bracket.utils.dummy_records import (
DUMMY_TEAM1,
)
from bracket.utils.http import HTTPMethod
from bracket.utils.types import assert_some
from tests.integration_tests.api.shared import SUCCESS_RESPONSE, send_tournament_request
from tests.integration_tests.models import AuthContext
from tests.integration_tests.sql import (
@@ -55,30 +54,30 @@ async def test_activate_next_stage(
DUMMY_TEAM1.model_copy(update={"tournament_id": auth_context.tournament.id})
) as team_inserted_4,
):
tournament_id = assert_some(auth_context.tournament.id)
tournament_id = auth_context.tournament.id
stage_item_1 = await sql_create_stage_item(
tournament_id,
StageItemCreateBody(
stage_id=assert_some(stage_inserted_1.id),
stage_id=stage_inserted_1.id,
name=DUMMY_STAGE_ITEM1.name,
team_count=DUMMY_STAGE_ITEM1.team_count,
type=DUMMY_STAGE_ITEM1.type,
inputs=[
StageItemInputCreateBodyFinal(
slot=1,
team_id=assert_some(team_inserted_1.id),
team_id=team_inserted_1.id,
),
StageItemInputCreateBodyFinal(
slot=2,
team_id=assert_some(team_inserted_2.id),
team_id=team_inserted_2.id,
),
StageItemInputCreateBodyFinal(
slot=3,
team_id=assert_some(team_inserted_3.id),
team_id=team_inserted_3.id,
),
StageItemInputCreateBodyFinal(
slot=4,
team_id=assert_some(team_inserted_4.id),
team_id=team_inserted_4.id,
),
],
),
@@ -86,7 +85,7 @@ async def test_activate_next_stage(
stage_item_2 = await sql_create_stage_item(
tournament_id,
StageItemCreateBody(
stage_id=assert_some(stage_inserted_2.id),
stage_id=stage_inserted_2.id,
name=DUMMY_STAGE_ITEM3.name,
team_count=2,
type=DUMMY_STAGE_ITEM3.type,
@@ -108,12 +107,12 @@ async def test_activate_next_stage(
await build_matches_for_stage_item(stage_item_2, tournament_id)
# Set match score to get a winner (team 2) that goes to the next round
[prev_stage, _] = await get_full_tournament_details(assert_some(auth_context.tournament.id))
[prev_stage, _] = await get_full_tournament_details(auth_context.tournament.id)
match1 = prev_stage.stage_items[0].rounds[0].matches[0]
assert isinstance(match1, MatchWithDetailsDefinitive)
assert match1.team2.id == team_inserted_2.id
await sql_update_match(
assert_some(match1.id),
match1.id,
MatchBody(**match1.model_copy(update={"team2_score": 42}).model_dump()),
auth_context.tournament,
)
@@ -121,7 +120,7 @@ async def test_activate_next_stage(
response = await send_tournament_request(
HTTPMethod.POST, "stages/activate?direction=next", auth_context, json={}
)
[_, next_stage] = await get_full_tournament_details(assert_some(auth_context.tournament.id))
[_, next_stage] = await get_full_tournament_details(auth_context.tournament.id)
await sql_delete_stage_item_with_foreign_keys(stage_item_2.id)
await sql_delete_stage_item_with_foreign_keys(stage_item_1.id)

View File

@@ -1,6 +1,6 @@
from heliclockter import datetime_utc
from bracket.models.db.round import RoundToInsert
from bracket.models.db.round import RoundInsertable
from bracket.models.db.stage_item import StageItemCreateBody, StageType
from bracket.models.db.stage_item_inputs import (
StageItemInputCreateBodyFinal,
@@ -21,6 +21,7 @@ from tests.integration_tests.api.shared import (
SUCCESS_RESPONSE,
send_tournament_request,
)
from tests.integration_tests.mocks import MOCK_NOW
from tests.integration_tests.models import AuthContext
from tests.integration_tests.sql import (
inserted_court,
@@ -46,28 +47,34 @@ async def test_schedule_matches_auto(
DUMMY_TEAM1.model_copy(update={"tournament_id": auth_context.tournament.id})
) as team_inserted_2,
):
tournament_id = assert_some(auth_context.tournament.id)
tournament_id = auth_context.tournament.id
stage_item_1 = await sql_create_stage_item(
tournament_id,
StageItemCreateBody(
stage_id=assert_some(stage_inserted_1.id),
stage_id=stage_inserted_1.id,
name=DUMMY_STAGE_ITEM1.name,
team_count=2,
type=StageType.SWISS,
inputs=[
StageItemInputCreateBodyFinal(
slot=1,
team_id=assert_some(team_inserted_1.id),
team_id=team_inserted_1.id,
),
StageItemInputCreateBodyFinal(
slot=2,
team_id=assert_some(team_inserted_2.id),
team_id=team_inserted_2.id,
),
],
),
)
await sql_create_round(
RoundToInsert(stage_item_id=stage_item_1.id, name="", is_draft=True, is_active=False),
RoundInsertable(
stage_item_id=stage_item_1.id,
name="",
is_draft=True,
is_active=False,
created=MOCK_NOW,
),
)
response = await send_tournament_request(
@@ -103,31 +110,43 @@ async def test_start_next_round(
DUMMY_TEAM1.model_copy(update={"tournament_id": auth_context.tournament.id})
) as team_inserted_2,
):
tournament_id = assert_some(auth_context.tournament.id)
tournament_id = auth_context.tournament.id
stage_item_1 = await sql_create_stage_item(
tournament_id,
StageItemCreateBody(
stage_id=assert_some(stage_inserted_1.id),
stage_id=stage_inserted_1.id,
name=DUMMY_STAGE_ITEM1.name,
team_count=2,
type=StageType.SWISS,
inputs=[
StageItemInputCreateBodyFinal(
slot=1,
team_id=assert_some(team_inserted_1.id),
team_id=team_inserted_1.id,
),
StageItemInputCreateBodyFinal(
slot=2,
team_id=assert_some(team_inserted_2.id),
team_id=team_inserted_2.id,
),
],
),
)
round_1_id = await sql_create_round(
RoundToInsert(stage_item_id=stage_item_1.id, name="", is_draft=True, is_active=False),
RoundInsertable(
stage_item_id=stage_item_1.id,
name="",
is_draft=True,
is_active=False,
created=MOCK_NOW,
),
)
round_2_id = await sql_create_round(
RoundToInsert(stage_item_id=stage_item_1.id, name="", is_draft=True, is_active=False),
RoundInsertable(
stage_item_id=stage_item_1.id,
name="",
is_draft=True,
is_active=False,
created=MOCK_NOW,
),
)
try:

View File

@@ -1,8 +1,7 @@
from bracket.models.db.user_x_club import UserXClub, UserXClubRelation
from bracket.models.db.user_x_club import UserXClubInsertable, UserXClubRelation
from bracket.sql.clubs import get_clubs_for_user_id, sql_delete_club
from bracket.utils.dummy_records import DUMMY_CLUB, DUMMY_MOCK_TIME
from bracket.utils.http import HTTPMethod
from bracket.utils.types import assert_some
from tests.integration_tests.api.shared import send_auth_request
from tests.integration_tests.models import AuthContext
from tests.integration_tests.sql import inserted_club, inserted_user_x_club
@@ -27,7 +26,7 @@ async def test_create_club(
) -> None:
payload = {"name": "Some Cool Club"}
response = await send_auth_request(HTTPMethod.POST, "clubs", auth_context, json=payload)
user_id = assert_some(auth_context.user.id)
user_id = auth_context.user.id
clubs = await get_clubs_for_user_id(user_id)
club_id = response["data"]["id"]
@@ -43,9 +42,9 @@ async def test_delete_club(
) -> None:
async with inserted_club(DUMMY_CLUB) as club_inserted:
async with inserted_user_x_club(
UserXClub(
user_id=assert_some(auth_context.user.id),
club_id=assert_some(club_inserted.id),
UserXClubInsertable(
user_id=auth_context.user.id,
club_id=club_inserted.id,
relation=UserXClubRelation.OWNER,
)
):

View File

@@ -19,7 +19,6 @@ from bracket.utils.dummy_records import (
DUMMY_TEAM2,
)
from bracket.utils.http import HTTPMethod
from bracket.utils.types import assert_some
from tests.integration_tests.api.shared import SUCCESS_RESPONSE, send_tournament_request
from tests.integration_tests.models import AuthContext
from tests.integration_tests.sql import (
@@ -286,25 +285,25 @@ async def test_upcoming_matches_endpoint(
DUMMY_PLAYER1.model_copy(
update={"elo_score": Decimal("1100.0"), "tournament_id": auth_context.tournament.id}
),
assert_some(team1_inserted.id),
team1_inserted.id,
) as player_inserted_1,
inserted_player_in_team(
DUMMY_PLAYER2.model_copy(
update={"elo_score": Decimal("1300.0"), "tournament_id": auth_context.tournament.id}
),
assert_some(team2_inserted.id),
team2_inserted.id,
) as player_inserted_2,
inserted_player_in_team(
DUMMY_PLAYER3.model_copy(
update={"elo_score": Decimal("1200.0"), "tournament_id": auth_context.tournament.id}
),
assert_some(team1_inserted.id),
team1_inserted.id,
) as player_inserted_3,
inserted_player_in_team(
DUMMY_PLAYER4.model_copy(
update={"elo_score": Decimal("1400.0"), "tournament_id": auth_context.tournament.id}
),
assert_some(team2_inserted.id),
team2_inserted.id,
) as player_inserted_4,
):
json_response = await send_tournament_request(

View File

@@ -11,7 +11,6 @@ from bracket.sql.rankings import (
from bracket.utils.db import fetch_one_parsed_certain
from bracket.utils.dummy_records import DUMMY_RANKING1, DUMMY_TEAM1
from bracket.utils.http import HTTPMethod
from bracket.utils.types import assert_some
from tests.integration_tests.api.shared import SUCCESS_RESPONSE, send_tournament_request
from tests.integration_tests.models import AuthContext
from tests.integration_tests.sql import inserted_ranking, inserted_team
@@ -45,7 +44,7 @@ async def test_create_ranking(
response = await send_tournament_request(HTTPMethod.POST, "rankings", auth_context, json={})
assert response.get("success") is True, response
tournament_id = assert_some(auth_context.tournament.id)
tournament_id = auth_context.tournament.id
for ranking in await get_all_rankings_in_tournament(tournament_id):
if ranking.position != 0:
await sql_delete_ranking(tournament_id, ranking.id)

View File

@@ -12,7 +12,6 @@ from bracket.utils.dummy_records import (
DUMMY_TEAM2,
)
from bracket.utils.http import HTTPMethod
from bracket.utils.types import assert_some
from tests.integration_tests.api.shared import SUCCESS_RESPONSE, send_tournament_request
from tests.integration_tests.models import AuthContext
from tests.integration_tests.sql import (
@@ -65,9 +64,9 @@ async def test_reschedule_match(
) as match_inserted,
):
body = MatchRescheduleBody(
old_court_id=assert_some(court1_inserted.id),
old_court_id=court1_inserted.id,
old_position=1,
new_court_id=assert_some(court2_inserted.id),
new_court_id=court2_inserted.id,
new_position=2,
)
assert (
@@ -79,7 +78,7 @@ async def test_reschedule_match(
)
== SUCCESS_RESPONSE
)
match = await sql_get_match(assert_some(match_inserted.id))
match = await sql_get_match(match_inserted.id)
await assert_row_count_and_clear(matches, 0)
assert match.court_id == body.new_court_id

View File

@@ -15,7 +15,6 @@ from bracket.utils.dummy_records import (
DUMMY_TEAM1,
)
from bracket.utils.http import HTTPMethod
from bracket.utils.types import assert_some
from tests.integration_tests.api.shared import (
SUCCESS_RESPONSE,
send_tournament_request,
@@ -51,30 +50,30 @@ async def test_schedule_all_matches(
DUMMY_TEAM1.model_copy(update={"tournament_id": auth_context.tournament.id})
) as team_inserted_4,
):
tournament_id = assert_some(auth_context.tournament.id)
tournament_id = auth_context.tournament.id
stage_item_1 = await sql_create_stage_item(
tournament_id,
StageItemCreateBody(
stage_id=assert_some(stage_inserted_1.id),
stage_id=stage_inserted_1.id,
name=DUMMY_STAGE_ITEM1.name,
team_count=DUMMY_STAGE_ITEM1.team_count,
type=DUMMY_STAGE_ITEM1.type,
inputs=[
StageItemInputCreateBodyFinal(
slot=1,
team_id=assert_some(team_inserted_1.id),
team_id=team_inserted_1.id,
),
StageItemInputCreateBodyFinal(
slot=2,
team_id=assert_some(team_inserted_2.id),
team_id=team_inserted_2.id,
),
StageItemInputCreateBodyFinal(
slot=3,
team_id=assert_some(team_inserted_3.id),
team_id=team_inserted_3.id,
),
StageItemInputCreateBodyFinal(
slot=4,
team_id=assert_some(team_inserted_4.id),
team_id=team_inserted_4.id,
),
],
),
@@ -82,7 +81,7 @@ async def test_schedule_all_matches(
stage_item_2 = await sql_create_stage_item(
tournament_id,
StageItemCreateBody(
stage_id=assert_some(stage_inserted_1.id),
stage_id=stage_inserted_1.id,
name=DUMMY_STAGE_ITEM3.name,
team_count=2,
type=DUMMY_STAGE_ITEM3.type,

View File

@@ -11,7 +11,6 @@ from bracket.utils.dummy_records import (
DUMMY_TEAM1,
)
from bracket.utils.http import HTTPMethod
from bracket.utils.types import assert_some
from tests.integration_tests.api.shared import (
SUCCESS_RESPONSE,
send_request,
@@ -147,7 +146,7 @@ async def test_update_stage(
)
== SUCCESS_RESPONSE
)
[updated_stage] = await get_full_tournament_details(assert_some(auth_context.tournament.id))
[updated_stage] = await get_full_tournament_details(auth_context.tournament.id)
assert len(updated_stage.stage_items) == 1
assert updated_stage.name == body["name"]
@@ -173,9 +172,7 @@ async def test_activate_stage(
)
== SUCCESS_RESPONSE
)
[prev_stage, next_stage] = await get_full_tournament_details(
assert_some(auth_context.tournament.id)
)
[prev_stage, next_stage] = await get_full_tournament_details(auth_context.tournament.id)
assert prev_stage.is_active is False
assert next_stage.is_active is True

View File

@@ -88,7 +88,7 @@ async def test_create_tournament(
# Cleanup
tournament = assert_some(await sql_get_tournament_by_endpoint_name(dashboard_endpoint))
await sql_delete_tournament_completely(assert_some(tournament.id))
await sql_delete_tournament_completely(tournament.id)
async def test_update_tournament(
@@ -133,7 +133,7 @@ async def test_delete_tournament(
== SUCCESS_RESPONSE
)
await sql_delete_tournament(assert_some(tournament_inserted.id))
await sql_delete_tournament(tournament_inserted.id)
async def test_tournament_upload_and_remove_logo(

View File

@@ -1,13 +1,12 @@
from bracket.cronjobs.scheduling import delete_demo_accounts
from bracket.models.db.account import UserAccountType
from bracket.sql.users import get_user_by_id, update_user_account_type
from bracket.utils.types import assert_some
from tests.integration_tests.sql import inserted_auth_context
async def test_delete_demo_accounts() -> None:
async with inserted_auth_context() as auth_context:
user_id = assert_some(auth_context.user.id)
user_id = auth_context.user.id
await update_user_account_type(user_id, UserAccountType.DEMO)
assert await get_user_by_id(user_id) is not None

View File

@@ -4,7 +4,7 @@ from zoneinfo import ZoneInfo
from heliclockter import datetime_utc, timedelta
from bracket.models.db.account import UserAccountType
from bracket.models.db.user import User
from bracket.models.db.user import UserInsertable
from bracket.routes.auth import ACCESS_TOKEN_EXPIRE_MINUTES, create_access_token
MOCK_NOW = datetime_utc(
@@ -16,8 +16,8 @@ def generate_email() -> str:
return f"donald_duck-{uuid4()}"
def get_mock_user() -> User:
return User(
def get_mock_user() -> UserInsertable:
return UserInsertable(
email=generate_email(),
name="Donald Duck",
# hash of 'mypassword'
@@ -27,7 +27,7 @@ def get_mock_user() -> User:
)
def get_mock_token(mock_user: User) -> str:
def get_mock_token(mock_user: UserInsertable) -> str:
return create_access_token(
data={"user": mock_user.email},
expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES),

View File

@@ -5,19 +5,19 @@ from typing import cast
from sqlalchemy import Table
from bracket.database import database
from bracket.models.db.club import Club
from bracket.models.db.court import Court
from bracket.models.db.match import Match
from bracket.models.db.player import Player
from bracket.models.db.player_x_team import PlayerXTeam
from bracket.models.db.club import Club, ClubInsertable
from bracket.models.db.court import Court, CourtInsertable
from bracket.models.db.match import Match, MatchInsertable
from bracket.models.db.player import Player, PlayerInsertable
from bracket.models.db.player_x_team import PlayerXTeamInsertable
from bracket.models.db.ranking import Ranking, RankingInsertable
from bracket.models.db.round import Round
from bracket.models.db.stage import Stage
from bracket.models.db.stage_item import StageItem, StageItemToInsert
from bracket.models.db.team import Team
from bracket.models.db.tournament import Tournament
from bracket.models.db.user import User, UserInDB
from bracket.models.db.user_x_club import UserXClub, UserXClubRelation
from bracket.models.db.round import Round, RoundInsertable
from bracket.models.db.stage import Stage, StageInsertable
from bracket.models.db.stage_item import StageItem, StageItemInsertable
from bracket.models.db.team import Team, TeamInsertable
from bracket.models.db.tournament import Tournament, TournamentInsertable
from bracket.models.db.user import UserInDB, UserInsertable
from bracket.models.db.user_x_club import UserXClub, UserXClubInsertable, UserXClubRelation
from bracket.schema import (
clubs,
courts,
@@ -36,7 +36,7 @@ from bracket.schema import (
from bracket.utils.db import insert_generic
from bracket.utils.dummy_records import DUMMY_CLUB, DUMMY_RANKING1, DUMMY_TOURNAMENT
from bracket.utils.id_types import TeamId
from bracket.utils.types import BaseModelT, assert_some
from bracket.utils.types import BaseModelT
from tests.integration_tests.mocks import get_mock_token, get_mock_user
from tests.integration_tests.models import AuthContext
@@ -59,33 +59,33 @@ async def inserted_generic(
@asynccontextmanager
async def inserted_user(user: User) -> AsyncIterator[UserInDB]:
async def inserted_user(user: UserInsertable) -> AsyncIterator[UserInDB]:
async with inserted_generic(user, users, UserInDB) as row_inserted:
yield cast(UserInDB, row_inserted)
@asynccontextmanager
async def inserted_club(club: Club) -> AsyncIterator[Club]:
async def inserted_club(club: ClubInsertable) -> AsyncIterator[Club]:
async with inserted_generic(club, clubs, Club) as row_inserted:
yield row_inserted
yield cast(Club, row_inserted)
@asynccontextmanager
async def inserted_tournament(tournament: Tournament) -> AsyncIterator[Tournament]:
async def inserted_tournament(tournament: TournamentInsertable) -> AsyncIterator[Tournament]:
async with inserted_generic(tournament, tournaments, Tournament) as row_inserted:
yield row_inserted
yield cast(Tournament, row_inserted)
@asynccontextmanager
async def inserted_team(team: Team) -> AsyncIterator[Team]:
async def inserted_team(team: TeamInsertable) -> AsyncIterator[Team]:
async with inserted_generic(team, teams, Team) as row_inserted:
yield row_inserted
yield cast(Team, row_inserted)
@asynccontextmanager
async def inserted_court(court: Court) -> AsyncIterator[Court]:
async def inserted_court(court: CourtInsertable) -> AsyncIterator[Court]:
async with inserted_generic(court, courts, Court) as row_inserted:
yield row_inserted
yield cast(Court, row_inserted)
@asynccontextmanager
@@ -95,50 +95,52 @@ async def inserted_ranking(ranking: RankingInsertable) -> AsyncIterator[Ranking]
@asynccontextmanager
async def inserted_player(player: Player) -> AsyncIterator[Player]:
async def inserted_player(player: PlayerInsertable) -> AsyncIterator[Player]:
async with inserted_generic(player, players, Player) as row_inserted:
yield row_inserted
yield cast(Player, row_inserted)
@asynccontextmanager
async def inserted_player_in_team(player: Player, team_id: TeamId) -> AsyncIterator[Player]:
async def inserted_player_in_team(
player: PlayerInsertable, team_id: TeamId
) -> AsyncIterator[Player]:
async with inserted_generic(player, players, Player) as row_inserted:
async with inserted_generic(
PlayerXTeam(player_id=assert_some(row_inserted.id), team_id=team_id),
PlayerXTeamInsertable(player_id=cast(Player, row_inserted).id, team_id=team_id),
players_x_teams,
PlayerXTeam,
PlayerXTeamInsertable,
):
yield row_inserted
yield cast(Player, row_inserted)
@asynccontextmanager
async def inserted_stage(stage: Stage) -> AsyncIterator[Stage]:
async def inserted_stage(stage: StageInsertable) -> AsyncIterator[Stage]:
async with inserted_generic(stage, stages, Stage) as row_inserted:
yield row_inserted
yield cast(Stage, row_inserted)
@asynccontextmanager
async def inserted_stage_item(stage_item: StageItemToInsert) -> AsyncIterator[StageItem]:
async def inserted_stage_item(stage_item: StageItemInsertable) -> AsyncIterator[StageItem]:
async with inserted_generic(stage_item, stage_items, StageItem) as row_inserted:
yield StageItem(**row_inserted.model_dump())
@asynccontextmanager
async def inserted_round(round_: Round) -> AsyncIterator[Round]:
async def inserted_round(round_: RoundInsertable) -> AsyncIterator[Round]:
async with inserted_generic(round_, rounds, Round) as row_inserted:
yield row_inserted
yield cast(Round, row_inserted)
@asynccontextmanager
async def inserted_match(match: Match) -> AsyncIterator[Match]:
async def inserted_match(match: MatchInsertable) -> AsyncIterator[Match]:
async with inserted_generic(match, matches, Match) as row_inserted:
yield row_inserted
yield cast(Match, row_inserted)
@asynccontextmanager
async def inserted_user_x_club(user_x_club: UserXClub) -> AsyncIterator[UserXClub]:
async def inserted_user_x_club(user_x_club: UserXClubInsertable) -> AsyncIterator[UserXClub]:
async with inserted_generic(user_x_club, users_x_clubs, UserXClub) as row_inserted:
yield row_inserted
yield cast(UserXClub, row_inserted)
@asynccontextmanager
@@ -155,9 +157,9 @@ async def inserted_auth_context() -> AsyncIterator[AuthContext]:
DUMMY_RANKING1.model_copy(update={"tournament_id": tournament_inserted.id})
) as ranking_inserted,
inserted_user_x_club(
UserXClub(
UserXClubInsertable(
user_id=user_inserted.id,
club_id=assert_some(club_inserted.id),
club_id=club_inserted.id,
relation=UserXClubRelation.OWNER,
)
) as user_x_club_inserted,

View File

@@ -11,7 +11,16 @@ from bracket.models.db.stage_item_inputs import StageItemInputFinal
from bracket.models.db.team import FullTeamWithPlayers
from bracket.models.db.util import RoundWithMatches, StageItemWithRounds
from bracket.utils.dummy_records import DUMMY_TEAM1, DUMMY_TEAM2
from bracket.utils.id_types import RankingId, RoundId, StageId, StageItemId, TeamId, TournamentId
from bracket.utils.id_types import (
MatchId,
RankingId,
RoundId,
StageId,
StageItemId,
StageItemInputId,
TeamId,
TournamentId,
)
def test_determine_ranking_for_stage_item_elimination() -> None:
@@ -21,8 +30,10 @@ def test_determine_ranking_for_stage_item_elimination() -> None:
StageItemWithRounds(
rounds=[
RoundWithMatches(
id=RoundId(-1),
matches=[
MatchWithDetailsDefinitive(
id=MatchId(-1),
team1=FullTeamWithPlayers(
**DUMMY_TEAM1.model_dump(), players=[], id=TeamId(-1)
),
@@ -37,6 +48,7 @@ def test_determine_ranking_for_stage_item_elimination() -> None:
team2_score=0,
),
MatchWithDetailsDefinitive(
id=MatchId(-1),
team1=FullTeamWithPlayers(
**DUMMY_TEAM1.model_dump(), players=[], id=TeamId(-1)
),
@@ -51,6 +63,7 @@ def test_determine_ranking_for_stage_item_elimination() -> None:
team2_score=2,
),
MatchWithDetails( # This gets ignored in ranking calculation
id=MatchId(-1),
created=now,
duration_minutes=90,
margin_minutes=15,
@@ -66,8 +79,12 @@ def test_determine_ranking_for_stage_item_elimination() -> None:
)
],
inputs=[
StageItemInputFinal(team_id=TeamId(-1), slot=1, tournament_id=tournament_id),
StageItemInputFinal(team_id=TeamId(-2), slot=2, tournament_id=tournament_id),
StageItemInputFinal(
id=StageItemInputId(-1), team_id=TeamId(-1), slot=1, tournament_id=tournament_id
),
StageItemInputFinal(
id=StageItemInputId(-2), team_id=TeamId(-2), slot=2, tournament_id=tournament_id
),
],
type_name="Single Elimination",
team_count=4,
@@ -103,8 +120,10 @@ def test_determine_ranking_for_stage_item_swiss() -> None:
StageItemWithRounds(
rounds=[
RoundWithMatches(
id=RoundId(-1),
matches=[
MatchWithDetailsDefinitive(
id=MatchId(-1),
team1=FullTeamWithPlayers(
**DUMMY_TEAM1.model_dump(), players=[], id=TeamId(-1)
),
@@ -119,6 +138,7 @@ def test_determine_ranking_for_stage_item_swiss() -> None:
team2_score=0,
),
MatchWithDetailsDefinitive(
id=MatchId(-2),
team1=FullTeamWithPlayers(
**DUMMY_TEAM1.model_dump(), players=[], id=TeamId(-1)
),
@@ -133,6 +153,7 @@ def test_determine_ranking_for_stage_item_swiss() -> None:
team2_score=2,
),
MatchWithDetails( # This gets ignored in ranking calculation
id=MatchId(-3),
created=now,
duration_minutes=90,
margin_minutes=15,
@@ -148,8 +169,12 @@ def test_determine_ranking_for_stage_item_swiss() -> None:
)
],
inputs=[
StageItemInputFinal(team_id=TeamId(-1), slot=1, tournament_id=tournament_id),
StageItemInputFinal(team_id=TeamId(-2), slot=2, tournament_id=tournament_id),
StageItemInputFinal(
id=StageItemInputId(-1), team_id=TeamId(-1), slot=1, tournament_id=tournament_id
),
StageItemInputFinal(
id=StageItemInputId(-2), team_id=TeamId(-2), slot=2, tournament_id=tournament_id
),
],
type_name="Swiss",
team_count=4,
@@ -185,6 +210,7 @@ def test_determine_ranking_for_stage_item_swiss_no_matches() -> None:
StageItemWithRounds(
rounds=[
RoundWithMatches(
id=RoundId(-1),
matches=[],
stage_item_id=StageItemId(-1),
created=now,
@@ -193,8 +219,12 @@ def test_determine_ranking_for_stage_item_swiss_no_matches() -> None:
)
],
inputs=[
StageItemInputFinal(team_id=TeamId(-1), slot=1, tournament_id=tournament_id),
StageItemInputFinal(team_id=TeamId(-2), slot=2, tournament_id=tournament_id),
StageItemInputFinal(
id=StageItemInputId(-1), team_id=TeamId(-1), slot=1, tournament_id=tournament_id
),
StageItemInputFinal(
id=StageItemInputId(-2), team_id=TeamId(-2), slot=2, tournament_id=tournament_id
),
],
type_name="Swiss",
team_count=4,

View File

@@ -5,7 +5,7 @@ from fastapi import HTTPException
from bracket.logic.scheduling.ladder_teams import get_possible_upcoming_matches_for_swiss
from bracket.models.db.match import Match, MatchFilter, MatchWithDetailsDefinitive, SuggestedMatch
from bracket.models.db.team import FullTeamWithPlayers, Team
from bracket.models.db.team import FullTeamWithPlayers, TeamInsertable
from bracket.models.db.util import RoundWithMatches
from bracket.utils.dummy_records import (
DUMMY_MATCH1,
@@ -14,7 +14,7 @@ from bracket.utils.dummy_records import (
DUMMY_TEAM3,
DUMMY_TEAM4,
)
from bracket.utils.id_types import StageItemId, TeamId
from bracket.utils.id_types import MatchId, RoundId, StageItemId, TeamId
from tests.integration_tests.mocks import MOCK_NOW
MATCH_FILTER = MatchFilter(elo_diff_threshold=50, iterations=100, limit=20, only_recommended=False)
@@ -25,7 +25,7 @@ def test_no_draft_round() -> None:
get_possible_upcoming_matches_for_swiss(MATCH_FILTER, [], [])
def get_team(team: Team, team_id: TeamId) -> FullTeamWithPlayers:
def get_team(team: TeamInsertable, team_id: TeamId) -> FullTeamWithPlayers:
return FullTeamWithPlayers(
id=team_id,
**team.model_dump(exclude={"id"}),
@@ -60,14 +60,26 @@ def test_constraints() -> None:
rounds = [
RoundWithMatches(
matches=[get_match(DUMMY_MATCH1, team1, team2)],
id=RoundId(-1),
matches=[
get_match(
Match.model_validate(DUMMY_MATCH1.model_dump() | {"id": MatchId(-1)}),
team1,
team2,
)
],
is_draft=False,
stage_item_id=StageItemId(-1),
name="R1",
created=MOCK_NOW,
),
RoundWithMatches(
matches=[], is_draft=True, stage_item_id=StageItemId(-1), name="R2", created=MOCK_NOW
id=RoundId(-1),
matches=[],
is_draft=True,
stage_item_id=StageItemId(-1),
name="R2",
created=MOCK_NOW,
),
]
teams = [team1, team2, team3, team4]