Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 3b3a862

Browse files
committedJun 10, 2023
Update old schemas and routes to use new ORM layout
1 parent ab5f01e commit 3b3a862

File tree

17 files changed

+347
-143
lines changed

17 files changed

+347
-143
lines changed
 

‎api/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from starlette.middleware.authentication import AuthenticationMiddleware
33

44
from api.middleware import TokenAuthentication, on_auth_error
5-
from api.routers.old import old_routes_router
5+
from api.routers.v1 import v1_routes_router
66
from api.settings import Server
77

88
app = FastAPI(redoc_url="/", docs_url="/swagger")
@@ -13,4 +13,4 @@
1313
on_error=on_auth_error,
1414
)
1515

16-
app.include_router(old_routes_router)
16+
app.include_router(v1_routes_router)

‎api/models/orm/infraction.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class Infraction(Base):
1717
user_id: Mapped[int] = mapped_column(ForeignKey("users.user_id"))
1818
issued_in_jam_id: Mapped[int] = mapped_column(ForeignKey("jams.jam_id"))
1919
infraction_type: Mapped[InfractionType] = mapped_column(
20-
Enum(*InfractionType.__args__, name="infraction_type_enum"),
20+
Enum(*InfractionType.__args__, name="infraction_type"),
2121
nullable=False,
2222
)
2323
reason: Mapped[str] = mapped_column(String(), nullable=False)

‎api/models/schemas/old/infraction.py

Lines changed: 0 additions & 31 deletions
This file was deleted.

‎api/models/schemas/utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
def discord_ids_must_be_snowflake(field_to_check: int) -> int:
2+
"""Ensure the ids are valid Discord snowflakes."""
3+
if field_to_check and field_to_check.bit_length() > 64:
4+
raise ValueError("Field must fit within a 64 bit int.")
5+
return field_to_check

‎api/models/schemas/v1/infraction.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from pydantic import BaseModel, validator
2+
3+
from api.models.orm.infraction import InfractionType
4+
from api.models.schemas.utils import discord_ids_must_be_snowflake
5+
6+
7+
class InfractionBase(BaseModel):
8+
"""Base model for all infraction types."""
9+
10+
user_id: int
11+
jam_id: int
12+
reason: str
13+
infraction_type: InfractionType
14+
15+
# validators
16+
_ensure_valid_discord_id = validator("user_id", allow_reuse=True)(discord_ids_must_be_snowflake)
17+
18+
19+
class InfractionCreate(InfractionBase):
20+
"""The expected fields to create a new infraction."""
21+
22+
23+
class Infraction(InfractionBase):
24+
"""A model representing an infraction."""
25+
26+
id: int
27+
28+
class Config:
29+
"""Sets ORM mode to true so that pydantic will validate the objects returned by SQLAlchemy."""
30+
31+
orm_mode = True

‎api/models/schemas/old/jam.py renamed to ‎api/models/schemas/v1/jam.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
from pydantic import BaseModel
22

3-
from api.models.schemas.old import infraction, team, winner
3+
from api.models.schemas.v1 import infraction, team, winner
44

55

6-
class CodeJam(BaseModel):
7-
"""A model representing a codejam."""
6+
class CodeJamBase(BaseModel):
7+
"""A Base model representing a codejam."""
88

99
name: str
1010
teams: list[team.Team]
1111
ongoing: bool = False
1212

1313

14-
class CodeJamResponse(CodeJam):
14+
class CodeJamCreate(CodeJamBase):
15+
"""The expected fields to create a new Code Jam."""
16+
17+
18+
class CodeJam(CodeJamBase):
1519
"""Response model representing a code jam."""
1620

1721
id: int
18-
teams: list[team.TeamResponse]
19-
infractions: list[infraction.InfractionResponse]
22+
infractions: list[infraction.Infraction]
2023
winners: list[winner.Winner]
2124

2225
class Config:

‎api/models/schemas/old/team.py renamed to ‎api/models/schemas/v1/team.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
from pydantic import BaseModel
44

5-
from api.models.schemas.old import user
5+
from api.models.schemas.v1 import user
66

77

8-
class Team(BaseModel):
9-
"""A model representing a team for a codejam."""
8+
class TeamBase(BaseModel):
9+
"""A Base model representing a team for a codejam."""
1010

1111
name: str
1212
users: list[user.User]
1313
discord_role_id: Optional[int] = None
1414
discord_channel_id: Optional[int] = None
1515

1616

17-
class TeamResponse(Team):
17+
class Team(TeamBase):
1818
"""Response model representing a team."""
1919

2020
id: int
@@ -26,11 +26,11 @@ class Config:
2626
orm_mode = True
2727

2828

29-
class UserTeamResponse(BaseModel):
30-
"""Response model representing user and team relationship."""
29+
class UserTeam(BaseModel):
30+
"""A model representing user and team relationship."""
3131

3232
user_id: int
33-
team: TeamResponse
33+
team: Team
3434
is_leader: bool
3535

3636
class Config:

‎api/models/schemas/old/user.py renamed to ‎api/models/schemas/v1/user.py

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,6 @@
11
from pydantic import BaseModel
22

3-
from api.models.schemas.old import infraction
4-
5-
6-
class User(BaseModel):
7-
"""A model representing a user for a codejam."""
8-
9-
user_id: int
10-
is_leader: bool
11-
12-
class Config:
13-
"""Sets ORM mode to true so that pydantic will validate the objects returned by SQLAlchemy."""
14-
15-
orm_mode = True
3+
from api.models.schemas.v1 import infraction
164

175

186
class ParticipationHistory(BaseModel):
@@ -23,18 +11,23 @@ class ParticipationHistory(BaseModel):
2311
first_place: bool
2412
team_id: int
2513
is_leader: bool
26-
infractions: list[infraction.InfractionResponse]
14+
infractions: list[infraction.Infraction]
2715

2816
class Config:
2917
"""Sets ORM mode to true so that pydantic will validate the objects returned by SQLAlchemy."""
3018

3119
orm_mode = True
3220

3321

34-
class UserResponse(BaseModel):
35-
"""Response model representing a user."""
22+
class UserBase(BaseModel):
23+
"""A Base model representing core data about a user."""
3624

3725
id: int
26+
27+
28+
class User(UserBase):
29+
"""Response model representing everything about a user."""
30+
3831
participation_history: list[ParticipationHistory]
3932

4033
class Config:
File renamed without changes.

‎api/routers/old/__init__.py

Lines changed: 0 additions & 10 deletions
This file was deleted.

‎api/routers/v1/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from fastapi import APIRouter
2+
3+
from api.routers.v1 import codejams, infractions, teams, users, winners
4+
5+
v1_routes_router = APIRouter()
6+
v1_routes_router.include_router(codejams.router)
7+
v1_routes_router.include_router(infractions.router)
8+
v1_routes_router.include_router(teams.router)
9+
v1_routes_router.include_router(users.router)
10+
v1_routes_router.include_router(winners.router)

‎api/routers/old/codejams.py renamed to ‎api/routers/v1/codejams.py

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@
44
from sqlalchemy import desc, update
55
from sqlalchemy.future import select
66

7-
from api.models import CodeJam, CodeJamResponse
87
from api.models.orm import Jam, Team, User
8+
from api.models.schemas.v1 import jam
99
from api.settings import DBSession
1010

1111
router = APIRouter(prefix="/codejams", tags=["codejams"])
1212

1313

1414
@router.get("/")
15-
async def get_codejams(session: DBSession) -> list[CodeJamResponse]:
15+
async def get_codejams(session: DBSession) -> list[jam.CodeJam]:
1616
"""Get all the codejams stored in the database."""
17-
codejams = await session.execute(select(Jam).order_by(desc(Jam.id)))
17+
codejams = await session.execute(select(Jam).order_by(desc(Jam.jam_id)))
1818
codejams.unique()
1919

2020
return codejams.scalars().all()
@@ -24,7 +24,7 @@ async def get_codejams(session: DBSession) -> list[CodeJamResponse]:
2424
"/{codejam_id}",
2525
responses={404: {"description": "CodeJam could not be found or there is no ongoing code jam."}},
2626
)
27-
async def get_codejam(codejam_id: int, session: DBSession) -> CodeJamResponse:
27+
async def get_codejam(codejam_id: int, session: DBSession) -> jam.CodeJam:
2828
"""
2929
Get a specific codejam stored in the database by ID.
3030
@@ -39,7 +39,7 @@ async def get_codejam(codejam_id: int, session: DBSession) -> CodeJamResponse:
3939
# With the current implementation, there should only be one ongoing codejam.
4040
return ongoing_jams[0]
4141

42-
jam_result = await session.execute(select(Jam).where(Jam.id == codejam_id))
42+
jam_result = await session.execute(select(Jam).where(Jam.jam_id == codejam_id))
4343
jam_result.unique()
4444

4545
if not (jam := jam_result.scalars().one_or_none()):
@@ -54,23 +54,23 @@ async def modify_codejam(
5454
session: DBSession,
5555
name: Optional[str] = None,
5656
ongoing: Optional[bool] = None,
57-
) -> CodeJamResponse:
57+
) -> jam.CodeJam:
5858
"""Modify the specified codejam to change its name and/or whether it's the ongoing code jam."""
59-
codejam = await session.execute(select(Jam).where(Jam.id == codejam_id))
59+
codejam = await session.execute(select(Jam).where(Jam.jam_id == codejam_id))
6060
codejam.unique()
6161

6262
if not codejam.scalars().one_or_none():
6363
raise HTTPException(status_code=404, detail="Code Jam with specified ID does not exist.")
6464

6565
if name is not None:
66-
await session.execute(update(Jam).where(Jam.id == codejam_id).values(name=name))
66+
await session.execute(update(Jam).where(Jam.jam_id == codejam_id).values(name=name))
6767

6868
if ongoing is not None:
6969
# Make sure no other Jams are ongoing, and set the specified codejam to ongoing.
7070
await session.execute(update(Jam).where(Jam.ongoing == True).values(ongoing=False))
71-
await session.execute(update(Jam).where(Jam.id == codejam_id).values(ongoing=True))
71+
await session.execute(update(Jam).where(Jam.jam_id == codejam_id).values(ongoing=True))
7272

73-
jam_result = await session.execute(select(Jam).where(Jam.id == codejam_id))
73+
jam_result = await session.execute(select(Jam).where(Jam.jam_id == codejam_id))
7474
jam_result.unique()
7575

7676
jam = jam_result.scalars().one()
@@ -79,7 +79,7 @@ async def modify_codejam(
7979

8080

8181
@router.post("/")
82-
async def create_codejam(codejam: CodeJam, session: DBSession) -> CodeJamResponse:
82+
async def create_codejam(codejam: jam.CodeJamCreate, session: DBSession) -> jam.CodeJam:
8383
"""
8484
Create a new codejam and get back the one just created.
8585
@@ -94,34 +94,37 @@ async def create_codejam(codejam: CodeJam, session: DBSession) -> CodeJamRespons
9494
await session.flush()
9595

9696
for raw_team in codejam.teams:
97-
team = Team(
98-
jam_id=jam.id,
99-
name=raw_team.name,
100-
discord_role_id=raw_team.discord_role_id,
101-
discord_channel_id=raw_team.discord_channel_id,
102-
)
103-
session.add(team)
104-
# Flush here to receive team ID
105-
await session.flush()
106-
97+
created_users = []
10798
for raw_user in raw_team.users:
99+
if raw_user.is_leader:
100+
team_leader_id = raw_user.user_id
108101
if (
109-
not (await session.execute(select(User).where(User.id == raw_user.user_id)))
102+
not (await session.execute(select(User).where(User.user_id == raw_user.user_id)))
110103
.unique()
111104
.scalars()
112105
.one_or_none()
113106
):
114107
user = User(id=raw_user.user_id)
108+
created_users.append(user)
115109
session.add(user)
116110

117-
team_user = TeamUser(team_id=team.id, user_id=raw_user.user_id, is_leader=raw_user.is_leader)
118-
session.add(team_user)
111+
team = Team(
112+
jam_id=jam.jam_id,
113+
name=raw_team.name,
114+
discord_role_id=raw_team.discord_role_id,
115+
discord_channel_id=raw_team.discord_channel_id,
116+
team_leader_id=team_leader_id,
117+
)
118+
team.users = created_users
119+
session.add(team)
120+
# Flush here to receive team ID
121+
await session.flush()
119122

120123
await session.flush()
121124

122125
# Pydantic, what is synchronous, may attempt to call async methods if current jam
123126
# object is returned. To avoid this, fetch all data here, in async context.
124-
jam_result = await session.execute(select(Jam).where(Jam.id == jam.id))
127+
jam_result = await session.execute(select(Jam).where(Jam.jam_id == jam.jam_id))
125128
jam_result.unique()
126129

127130
jam = jam_result.scalars().one()

‎api/routers/old/infractions.py renamed to ‎api/routers/v1/infractions.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
from fastapi import APIRouter, HTTPException
22
from sqlalchemy.future import select
33

4-
from api.models import Infraction, InfractionResponse
54
from api.models.orm import Infraction as DbInfraction
65
from api.models.orm import Jam, User
6+
from api.models.schemas.v1.infraction import Infraction, InfractionCreate
77
from api.settings import DBSession
88

99
router = APIRouter(prefix="/infractions", tags=["infractions"])
1010

1111

1212
@router.get("/")
13-
async def get_infractions(session: DBSession) -> list[InfractionResponse]:
13+
async def get_infractions(session: DBSession) -> list[Infraction]:
1414
"""Get every infraction stored in the database."""
1515
infractions = await session.execute(select(DbInfraction))
1616
infractions.unique()
@@ -22,9 +22,9 @@ async def get_infractions(session: DBSession) -> list[InfractionResponse]:
2222
"/{infraction_id}",
2323
responses={404: {"description": "Infraction could not be found."}},
2424
)
25-
async def get_infraction(infraction_id: int, session: DBSession) -> InfractionResponse:
25+
async def get_infraction(infraction_id: int, session: DBSession) -> Infraction:
2626
"""Get a specific infraction stored in the database by ID."""
27-
infraction_result = await session.execute(select(DbInfraction).where(DbInfraction.id == infraction_id))
27+
infraction_result = await session.execute(select(DbInfraction).where(DbInfraction.infraction_id == infraction_id))
2828
infraction_result.unique()
2929

3030
if not (infraction := infraction_result.scalars().one_or_none()):
@@ -38,16 +38,18 @@ async def get_infraction(infraction_id: int, session: DBSession) -> InfractionRe
3838
responses={404: {"Description": "Jam ID or User ID could not be found."}},
3939
)
4040
async def create_infraction(
41-
infraction: Infraction,
41+
infraction: InfractionCreate,
4242
session: DBSession,
43-
) -> InfractionResponse:
43+
) -> Infraction:
4444
"""Add an infraction for a user to the database."""
45-
jam_id = (await session.execute(select(Jam.id).where(Jam.id == infraction.jam_id))).scalars().one_or_none()
45+
jam_id = (await session.execute(select(Jam.jam_id).where(Jam.jam_id == infraction.jam_id))).scalars().one_or_none()
4646

4747
if jam_id is None:
4848
raise HTTPException(404, "Jam with specified ID could not be found.")
4949

50-
user_id = (await session.execute(select(User.id).where(User.id == infraction.user_id))).scalars().one_or_none()
50+
user_id = (
51+
(await session.execute(select(User.user_id).where(User.user_id == infraction.user_id))).scalars().one_or_none()
52+
)
5153

5254
if user_id is None:
5355
raise HTTPException(404, "User with specified ID could not be found.")
@@ -58,7 +60,7 @@ async def create_infraction(
5860
session.add(infraction)
5961
await session.flush()
6062

61-
infraction_result = await session.execute(select(DbInfraction).where(DbInfraction.id == infraction.id))
63+
infraction_result = await session.execute(select(DbInfraction).where(DbInfraction.infraction_id == infraction.id))
6264
infraction_result.unique()
6365

6466
return infraction_result.scalars().one()

‎api/routers/old/teams.py renamed to ‎api/routers/v1/teams.py

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,18 @@
55
from sqlalchemy.ext.asyncio import AsyncSession
66
from sqlalchemy.future import select
77

8-
from api.models import TeamResponse, User
9-
from api.models.orm import Jam, Team
8+
from api.models.orm import Jam
9+
from api.models.orm import Team as DbTeam
1010
from api.models.orm import User as DbUser
11+
from api.models.schemas.v1 import team, user
1112
from api.settings import DBSession
1213

1314
router = APIRouter(prefix="/teams", tags=["teams"])
1415

1516

16-
async def ensure_team_exists(team_id: int, session: AsyncSession) -> Team:
17+
async def ensure_team_exists(team_id: int, session: AsyncSession) -> DbTeam:
1718
"""Ensure that a team with the given ID exists and return it."""
18-
teams = await session.execute(select(Team).where(Team.id == team_id))
19+
teams = await session.execute(select(DbTeam).where(DbTeam.team_id == team_id))
1920
teams.unique()
2021

2122
if not (team := teams.scalars().one_or_none()):
@@ -26,7 +27,7 @@ async def ensure_team_exists(team_id: int, session: AsyncSession) -> Team:
2627

2728
async def ensure_user_exists(user_id: int, session: AsyncSession) -> DbUser:
2829
"""Ensure that a user with the given ID exists and return it."""
29-
users = await session.execute(select(DbUser).where(DbUser.id == user_id))
30+
users = await session.execute(select(DbUser).where(DbUser.user_id == user_id))
3031
users.unique()
3132

3233
if not (user := users.scalars().one_or_none()):
@@ -36,12 +37,12 @@ async def ensure_user_exists(user_id: int, session: AsyncSession) -> DbUser:
3637

3738

3839
@router.get("/")
39-
async def get_teams(session: DBSession, current_jam: bool = False) -> list[TeamResponse]:
40+
async def get_teams(session: DBSession, current_jam: bool = False) -> list[team.Team]:
4041
"""Get every code jam team in the database."""
4142
if not current_jam:
42-
teams = await session.execute(select(Team))
43+
teams = await session.execute(select(DbTeam))
4344
else:
44-
teams = await session.execute(select(Team).join_from(Team, Jam).where(Jam.ongoing == True))
45+
teams = await session.execute(select(DbTeam).join_from(DbTeam, Jam).where(Jam.ongoing == True))
4546

4647
teams.unique()
4748
return teams.scalars().all()
@@ -52,15 +53,17 @@ async def find_team_by_name(
5253
name: str,
5354
session: DBSession,
5455
jam_id: Optional[int] = None,
55-
) -> TeamResponse:
56+
) -> team.Team:
5657
"""Get a specific code jam team by name."""
5758
if jam_id is None:
5859
teams = await session.execute(
59-
select(Team).join(Team.jam).where((func.lower(Team.name) == func.lower(name)) & (Jam.ongoing == True))
60+
select(DbTeam)
61+
.join(DbTeam.__annotations__)
62+
.where((func.lower(DbTeam.name) == func.lower(name)) & (Jam.ongoing == True))
6063
)
6164
else:
6265
teams = await session.execute(
63-
select(Team).where((func.lower(Team.name) == func.lower(name)) & (Team.jam_id == jam_id))
66+
select(DbTeam).where((func.lower(DbTeam.name) == func.lower(name)) & (DbTeam.jam_id == jam_id))
6467
)
6568

6669
teams.unique()
@@ -72,20 +75,20 @@ async def find_team_by_name(
7275

7376

7477
@router.get("/{team_id}", responses={404: {"description": "Team could not be found."}})
75-
async def get_team(team_id: int, session: DBSession) -> TeamResponse:
78+
async def get_team(team_id: int, session: DBSession) -> team.Team:
7679
"""Get a specific code jam team in the database by ID."""
7780
return await ensure_team_exists(team_id, session)
7881

7982

8083
@router.get("/{team_id}/users", responses={404: {"description": "Team could not be found."}})
81-
async def get_team_users(team_id: int, session: DBSession) -> list[User]:
84+
async def get_team_users(team_id: int, session: DBSession) -> list[user.User]:
8285
"""Get the users of a specific code jam team in the database."""
8386
await ensure_team_exists(team_id, session)
8487

85-
team_users = await session.execute(select(TeamUser).where(TeamUser.team_id == team_id))
86-
team_users.unique()
88+
# team_users = await session.execute(select(TeamUser).where(TeamUser.team_id == team_id))
89+
# team_users.unique()
8790

88-
return team_users.scalars().all()
91+
# return team_users.scalars().all()
8992

9093

9194
@router.post(
@@ -97,24 +100,24 @@ async def get_team_users(team_id: int, session: DBSession) -> list[User]:
97100
400: {"description": "This user is already on the team."},
98101
},
99102
)
100-
async def add_user_to_team(team_id: int, user_id: int, session: DBSession, is_leader: bool = False) -> User:
103+
async def add_user_to_team(team_id: int, user_id: int, session: DBSession, is_leader: bool = False) -> user.User:
101104
"""Add a user to a specific code jam team in the database."""
102105
await ensure_team_exists(team_id, session)
103106
await ensure_user_exists(user_id, session)
104107

105108
team_users = await session.execute(
106-
select(TeamUser).where((TeamUser.team_id == team_id) & (TeamUser.user_id == user_id))
109+
# select(TeamUser).where((TeamUser.team_id == team_id) & (TeamUser.user_id == user_id))
107110
)
108111
team_users.unique()
109112

110113
if team_users.scalars().one_or_none():
111114
raise HTTPException(status_code=400, detail="This user is already on this team.")
112115

113-
team_user = TeamUser(team_id=team_id, user_id=user_id, is_leader=is_leader)
114-
session.add(team_user)
116+
# team_user = TeamUser(team_id=team_id, user_id=user_id, is_leader=is_leader)
117+
# session.add(team_user)
115118
await session.flush()
116119

117-
return team_user
120+
# return team_user
118121

119122

120123
@router.delete(
@@ -136,7 +139,7 @@ async def remove_user_from_team(
136139
await ensure_team_exists(team_id, session)
137140

138141
team_users = await session.execute(
139-
select(TeamUser).where((TeamUser.team_id == team_id) & (TeamUser.user_id == user_id))
142+
# select(TeamUser).where((TeamUser.team_id == team_id) & (TeamUser.user_id == user_id))
140143
)
141144
team_users.unique()
142145

‎api/routers/old/users.py renamed to ‎api/routers/v1/users.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
from sqlalchemy.ext.asyncio import AsyncSession
55
from sqlalchemy.future import select
66

7-
from api.models import UserResponse, UserTeamResponse
8-
from api.models.orm import Jam, User
7+
from api.models.orm import jam
8+
from api.models.orm import user as dbuser
9+
from api.models.schemas.v1 import team, user
910
from api.settings import DBSession
1011

1112
router = APIRouter(prefix="/users", tags=["users"])
@@ -16,7 +17,7 @@ async def get_user_data(session: AsyncSession, user_id: int) -> dict[str, Any]:
1617
user: dict[str, Any] = {"id": user_id}
1718
participation_history = []
1819

19-
user_teams = await session.execute(select(TeamUser).where(TeamUser.user_id == user_id))
20+
user_teams = None # await session.execute(select(TeamUser).where(TeamUser.user_id == user_id))
2021
user_teams.unique()
2122

2223
for user_team in user_teams.scalars().all():
@@ -48,18 +49,18 @@ async def get_user_data(session: AsyncSession, user_id: int) -> dict[str, Any]:
4849

4950

5051
@router.get("/")
51-
async def get_users(session: DBSession) -> list[UserResponse]:
52+
async def get_users(session: DBSession) -> list[user.User]:
5253
"""Get information about all the users stored in the database."""
53-
users = await session.execute(select(User.id))
54+
users = await session.execute(select(dbuser.User.id))
5455
users.unique()
5556

5657
return [await get_user_data(session, user) for user in users.scalars().all()]
5758

5859

5960
@router.get("/{user_id}", responses={404: {"description": "User could not be found."}})
60-
async def get_user(user_id: int, session: DBSession) -> UserResponse:
61+
async def get_user(user_id: int, session: DBSession) -> user.User:
6162
"""Get a specific user stored in the database by ID."""
62-
user = await session.execute(select(User).where(User.id == user_id))
63+
user = await session.execute(select(dbuser.User).where(dbuser.User.id == user_id))
6364
user.unique()
6465

6566
if not user.scalars().one_or_none():
@@ -69,15 +70,15 @@ async def get_user(user_id: int, session: DBSession) -> UserResponse:
6970

7071

7172
@router.post("/{user_id}", responses={400: {"description": "User already exists."}})
72-
async def create_user(user_id: int, session: DBSession) -> UserResponse:
73+
async def create_user(user_id: int, session: DBSession) -> user.User:
7374
"""Create a new user with the specified ID to the database."""
74-
user = await session.execute(select(User).where(User.id == user_id))
75+
user = await session.execute(select(dbuser.User).where(dbuser.User.id == user_id))
7576
user.unique()
7677

7778
if user.scalars().one_or_none():
7879
raise HTTPException(status_code=400, detail="User with specified ID already exists.")
7980

80-
user = User(id=user_id)
81+
user = dbuser.User(id=user_id)
8182
session.add(user)
8283
await session.flush()
8384

@@ -94,20 +95,24 @@ async def create_user(user_id: int, session: DBSession) -> UserResponse:
9495
}
9596
},
9697
)
97-
async def get_current_team(user_id: int, session: DBSession) -> UserTeamResponse:
98+
async def get_current_team(user_id: int, session: DBSession) -> team.UserTeam:
9899
"""Get a user's current team information."""
99-
user = await session.execute(select(User).where(User.id == user_id))
100+
user = await session.execute(select(dbuser.User).where(dbuser.User.user_id == user_id))
100101
user.unique()
101102

102103
if not user.scalars().one_or_none():
103104
raise HTTPException(status_code=404, detail="User with specified ID could not be found.")
104105

105-
ongoing_jam = (await session.execute(select(Jam).where(Jam.ongoing == True))).unique().scalars().one_or_none()
106+
ongoing_jam = (
107+
(await session.execute(select(jam.Jam).where(jam.Jam.ongoing == True))).unique().scalars().one_or_none()
108+
)
106109

107110
if not ongoing_jam:
108111
raise HTTPException(status_code=404, detail="There is no ongoing codejam.")
109112

110-
user_teams = (await session.execute(select(TeamUser).where(TeamUser.user_id == user_id))).unique().scalars().all()
113+
user_teams = (
114+
None # (await session.execute(select(TeamUser).where(TeamUser.user_id == user_id))).unique().scalars().all()
115+
)
111116

112117
current_team = None
113118
for user_team in user_teams:
File renamed without changes.
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
"""New ORM models
2+
3+
Revision ID: 698fc7687b7f
4+
Revises: 3bb5cc4b5d48
5+
Create Date: 2023-03-25 22:25:55.765694
6+
7+
"""
8+
import sqlalchemy as sa
9+
from alembic import op
10+
11+
# revision identifiers, used by Alembic.
12+
revision = "698fc7687b7f"
13+
down_revision = "3bb5cc4b5d48"
14+
branch_labels = None
15+
depends_on = None
16+
17+
18+
def upgrade():
19+
op.drop_constraint("infractions_user_id_users_fk", "infractions", type_="foreignkey")
20+
op.drop_constraint("infractions_jam_id_jams_fk", "infractions", type_="foreignkey")
21+
op.drop_constraint("teams_jam_id_jams_fk", "teams", type_="foreignkey")
22+
op.drop_constraint("winners_jam_id_jams_fk", "winners", type_="foreignkey")
23+
op.drop_constraint("winners_user_id_users_fk", "winners", type_="foreignkey")
24+
op.drop_constraint("team_has_user_team_id_teams_fk", "team_has_user", type_="foreignkey")
25+
op.drop_constraint("team_has_user_user_id_users_fk", "team_has_user", type_="foreignkey")
26+
27+
op.drop_constraint("infractions_pk", "infractions")
28+
op.add_column("infractions", sa.Column("infraction_id", sa.Integer(), autoincrement=True, primary_key=True))
29+
op.create_primary_key("infractions_pk", "infractions", ["infraction_id"])
30+
op.execute("UPDATE infractions SET infraction_id = id")
31+
op.add_column("infractions", sa.Column("issued_in_jam_id", sa.Integer()))
32+
op.execute("UPDATE infractions SET issued_in_jam_id = jam_id")
33+
op.alter_column("infractions", "issued_in_jam_id", existing_type=sa.Integer(), nullable=False)
34+
35+
op.drop_constraint("jams_pk", "jams")
36+
op.add_column("jams", sa.Column("jam_id", sa.Integer(), autoincrement=True, primary_key=True))
37+
op.execute("UPDATE jams SET jam_id = id")
38+
op.create_primary_key("jams_pk", "jams", ["jam_id"])
39+
40+
op.drop_constraint("teams_pk", "teams")
41+
op.add_column("teams", sa.Column("team_id", sa.Integer(), autoincrement=True, primary_key=True))
42+
op.execute("UPDATE teams SET team_id = id")
43+
op.create_primary_key("teams_pk", "teams", ["team_id"])
44+
45+
op.drop_constraint("users_pk", "users")
46+
op.add_column(
47+
"users",
48+
sa.Column("user_id", sa.BigInteger(), autoincrement=False, primary_key=True, server_default=sa.func.random()),
49+
)
50+
op.execute("UPDATE users SET user_id = id")
51+
op.alter_column("users", "user_id", existing_type=sa.BigInteger(), server_default=None)
52+
op.create_primary_key("users_pk", "users", ["user_id"])
53+
54+
op.drop_column("infractions", "id")
55+
op.drop_column("infractions", "jam_id")
56+
op.create_foreign_key(op.f("infractions_user_id_users_fk"), "infractions", "users", ["user_id"], ["user_id"])
57+
op.create_foreign_key(
58+
op.f("infractions_issued_in_jam_id_jams_fk"), "infractions", "jams", ["issued_in_jam_id"], ["jam_id"]
59+
)
60+
61+
op.alter_column("infractions", "user_id", existing_type=sa.BIGINT(), nullable=False)
62+
op.alter_column("infractions", "reason", existing_type=sa.TEXT(), type_=sa.String(), existing_nullable=False)
63+
64+
op.alter_column("jams", "name", existing_type=sa.TEXT(), type_=sa.String(), existing_nullable=False)
65+
op.alter_column("jams", "ongoing", existing_type=sa.BOOLEAN(), server_default=None, existing_nullable=False)
66+
67+
op.drop_column("jams", "id")
68+
69+
op.add_column("teams", sa.Column("leader_id", sa.BigInteger()))
70+
op.execute(
71+
"UPDATE teams SET leader_id = tu.user_id from teams t join team_has_user tu USING(team_id) where tu.is_leader"
72+
)
73+
op.alter_column("teams", "leader_id", existing_type=sa.Integer(), nullable=False)
74+
75+
op.add_column("teams", sa.Column("winner", sa.Boolean(), nullable=True))
76+
op.add_column("teams", sa.Column("first_place_winner", sa.Boolean(), nullable=True))
77+
op.alter_column("teams", "name", existing_type=sa.TEXT(), type_=sa.String(), existing_nullable=False)
78+
op.alter_column("teams", "discord_role_id", existing_type=sa.BIGINT())
79+
op.alter_column("teams", "discord_channel_id", existing_type=sa.BIGINT())
80+
op.create_foreign_key(op.f("teams_jam_id_jams_fk"), "teams", "jams", ["jam_id"], ["jam_id"])
81+
op.drop_column("teams", "id")
82+
op.execute(
83+
"UPDATE teams "
84+
"SET winner = true, "
85+
"first_place_winner = w.first_place "
86+
"from teams t "
87+
"join winners w USING(jam_id)"
88+
)
89+
90+
op.drop_column("users", "id")
91+
op.create_foreign_key(op.f("teams_leader_id_users_fk"), "teams", "users", ["leader_id"], ["user_id"])
92+
93+
op.create_table(
94+
"jam_specific_details",
95+
sa.Column("jam_specific_detail_id", sa.Integer(), nullable=False),
96+
sa.Column("user_id", sa.BigInteger(), nullable=False),
97+
sa.Column("jam_id", sa.Integer(), nullable=False),
98+
sa.Column(
99+
"experience_level_git",
100+
sa.Enum("beginner", "decent", "expierienced", "very_expierienced", name="experience_level_git_enum"),
101+
nullable=False,
102+
),
103+
sa.Column(
104+
"experience_level_python",
105+
sa.Enum("beginner", "decent", "expierienced", "very_expierienced", name="experience_level_python_enum"),
106+
nullable=False,
107+
),
108+
sa.Column("time_zone", sa.String(), nullable=False),
109+
sa.Column("willing_to_lead", sa.Boolean(), nullable=False),
110+
sa.ForeignKeyConstraint(["jam_id"], ["jams.jam_id"], name=op.f("jam_specific_details_jam_id_jams_fk")),
111+
sa.ForeignKeyConstraint(["user_id"], ["users.user_id"], name=op.f("jam_specific_details_user_id_users_fk")),
112+
sa.PrimaryKeyConstraint("jam_specific_detail_id", name=op.f("jam_specific_details_pk")),
113+
)
114+
115+
op.create_table(
116+
"team_has_users",
117+
sa.Column("team_id", sa.Integer(), nullable=False),
118+
sa.Column("user_id", sa.BigInteger(), nullable=False),
119+
sa.ForeignKeyConstraint(["team_id"], ["teams.team_id"], name=op.f("team_has_users_team_id_teams_fk")),
120+
sa.ForeignKeyConstraint(["user_id"], ["users.user_id"], name=op.f("team_has_users_user_id_users_fk")),
121+
sa.PrimaryKeyConstraint("team_id", "user_id", name=op.f("team_has_users_pk")),
122+
)
123+
op.execute("INSERT INTO team_has_users (team_id, user_id) " "SELECT team_id, user_id " "FROM team_has_user")
124+
125+
op.drop_table("winners")
126+
op.drop_table("team_has_user")
127+
# ### end Alembic commands ###
128+
129+
130+
def downgrade():
131+
# ### commands auto generated by Alembic - please adjust! ###
132+
op.add_column("users", sa.Column("id", sa.BIGINT(), autoincrement=False, nullable=False))
133+
op.drop_column("users", "user_id")
134+
op.add_column("teams", sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False))
135+
op.drop_constraint(op.f("teams_jam_id_jams_fk"), "teams", type_="foreignkey")
136+
op.drop_constraint(op.f("teams_leader_id_users_fk"), "teams", type_="foreignkey")
137+
op.create_foreign_key("teams_jam_id_jams_fk", "teams", "jams", ["jam_id"], ["id"])
138+
op.alter_column("teams", "discord_channel_id", existing_type=sa.BIGINT(), nullable=True)
139+
op.alter_column("teams", "discord_role_id", existing_type=sa.BIGINT(), nullable=True)
140+
op.alter_column("teams", "name", existing_type=sa.String(), type_=sa.TEXT(), existing_nullable=False)
141+
op.drop_column("teams", "first_place_winner")
142+
op.drop_column("teams", "winner")
143+
op.drop_column("teams", "leader_id")
144+
op.drop_column("teams", "team_id")
145+
op.add_column(
146+
"jams",
147+
sa.Column(
148+
"id",
149+
sa.INTEGER(),
150+
server_default=sa.text("nextval('jams_id_seq'::regclass)"),
151+
autoincrement=True,
152+
nullable=False,
153+
),
154+
)
155+
op.alter_column(
156+
"jams", "ongoing", existing_type=sa.BOOLEAN(), server_default=sa.text("false"), existing_nullable=False
157+
)
158+
op.alter_column("jams", "name", existing_type=sa.String(), type_=sa.TEXT(), existing_nullable=False)
159+
op.drop_column("jams", "jam_id")
160+
op.add_column("infractions", sa.Column("jam_id", sa.INTEGER(), autoincrement=False, nullable=True))
161+
op.add_column("infractions", sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False))
162+
op.drop_constraint(op.f("infractions_issued_in_jam_id_jams_fk"), "infractions", type_="foreignkey")
163+
op.drop_constraint(op.f("infractions_user_id_users_fk"), "infractions", type_="foreignkey")
164+
op.create_foreign_key("infractions_jam_id_jams_fk", "infractions", "jams", ["jam_id"], ["id"])
165+
op.create_foreign_key("infractions_user_id_users_fk", "infractions", "users", ["user_id"], ["id"])
166+
op.alter_column("infractions", "reason", existing_type=sa.String(), type_=sa.TEXT(), existing_nullable=False)
167+
op.alter_column("infractions", "user_id", existing_type=sa.BIGINT(), nullable=True)
168+
op.drop_column("infractions", "issued_in_jam_id")
169+
op.drop_column("infractions", "infraction_id")
170+
op.create_table(
171+
"team_has_user",
172+
sa.Column("team_id", sa.INTEGER(), autoincrement=False, nullable=False),
173+
sa.Column("user_id", sa.BIGINT(), autoincrement=False, nullable=False),
174+
sa.Column("is_leader", sa.BOOLEAN(), autoincrement=False, nullable=False),
175+
sa.ForeignKeyConstraint(["team_id"], ["teams.id"], name="team_has_user_team_id_teams_fk"),
176+
sa.ForeignKeyConstraint(["user_id"], ["users.id"], name="team_has_user_user_id_users_fk"),
177+
sa.PrimaryKeyConstraint("team_id", "user_id", name="team_has_user_pk"),
178+
)
179+
op.create_table(
180+
"winners",
181+
sa.Column("jam_id", sa.INTEGER(), autoincrement=False, nullable=False),
182+
sa.Column("user_id", sa.BIGINT(), autoincrement=False, nullable=False),
183+
sa.Column("first_place", sa.BOOLEAN(), autoincrement=False, nullable=False),
184+
sa.ForeignKeyConstraint(["jam_id"], ["jams.id"], name="winners_jam_id_jams_fk"),
185+
sa.ForeignKeyConstraint(["user_id"], ["users.id"], name="winners_user_id_users_fk"),
186+
sa.PrimaryKeyConstraint("jam_id", "user_id", name="winners_pk"),
187+
)
188+
op.drop_table("team_has_users")
189+
op.drop_table("jam_specific_details")
190+
# ### end Alembic commands ###

0 commit comments

Comments
 (0)
Please sign in to comment.