Skip to content

Commit

Permalink
Merge e0b413e into 31a37b5
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisLovering committed Mar 21, 2023
2 parents 31a37b5 + e0b413e commit b5b0ff8
Show file tree
Hide file tree
Showing 11 changed files with 989 additions and 842 deletions.
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
rev: v4.4.0
hooks:
- id: check-merge-conflict
- id: check-toml
Expand All @@ -11,18 +11,18 @@ repos:
args: [--markdown-linebreak-ext=md]

- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.9.0
rev: v1.10.0
hooks:
- id: python-check-blanket-noqa

- repo: https://github.com/pycqa/isort
rev: 5.10.1
rev: 5.12.0
hooks:
- id: isort
name: isort (python)

- repo: https://github.com/python-poetry/poetry
rev: '1.2.2'
rev: 1.4.1
hooks:
- id: poetry-check
- id: poetry-export
Expand Down
5 changes: 5 additions & 0 deletions api/database.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
from typing import Annotated

from fastapi import Depends
from sqlalchemy import BigInteger, Boolean, Column, Enum, ForeignKey, Index, Integer, PrimaryKeyConstraint, Text, text
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker

from api.constants import Config
from api.dependencies import get_db_session

engine = create_async_engine(Config.DATABASE_URL)
Base = declarative_base()

Session = sessionmaker(engine, expire_on_commit=False, class_=AsyncSession)
DBSession = Annotated[AsyncSession, Depends(get_db_session)]


class TeamUser(Base):
Expand Down
21 changes: 9 additions & 12 deletions api/routers/codejams.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException
from fastapi import APIRouter, HTTPException
from sqlalchemy import desc, update
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select

from api.database import Jam, Team, TeamUser, User
from api.dependencies import get_db_session
from api.database import DBSession, Jam, Team, TeamUser, User
from api.models import CodeJam, CodeJamResponse

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


@router.get("/", response_model=list[CodeJamResponse])
async def get_codejams(session: AsyncSession = Depends(get_db_session)) -> list[Jam]:
@router.get("/")
async def get_codejams(session: DBSession) -> list[CodeJamResponse]:
"""Get all the codejams stored in the database."""
codejams = await session.execute(select(Jam).order_by(desc(Jam.id)))
codejams.unique()
Expand All @@ -23,10 +21,9 @@ async def get_codejams(session: AsyncSession = Depends(get_db_session)) -> list[

@router.get(
"/{codejam_id}",
response_model=CodeJamResponse,
responses={404: {"description": "CodeJam could not be found or there is no ongoing code jam."}},
)
async def get_codejam(codejam_id: int, session: AsyncSession = Depends(get_db_session)) -> Jam:
async def get_codejam(codejam_id: int, session: DBSession) -> CodeJamResponse:
"""
Get a specific codejam stored in the database by ID.
Expand All @@ -53,10 +50,10 @@ async def get_codejam(codejam_id: int, session: AsyncSession = Depends(get_db_se
@router.patch("/{codejam_id}", responses={404: {"description": "Code Jam with specified ID does not exist."}})
async def modify_codejam(
codejam_id: int,
session: DBSession,
name: Optional[str] = None,
ongoing: Optional[bool] = None,
session: AsyncSession = Depends(get_db_session),
) -> None:
) -> CodeJamResponse:
"""Modify the specified codejam to change its name and/or whether it's the ongoing code jam."""
codejam = await session.execute(select(Jam).where(Jam.id == codejam_id))
codejam.unique()
Expand All @@ -80,8 +77,8 @@ async def modify_codejam(
return jam


@router.post("/", response_model=CodeJamResponse)
async def create_codejam(codejam: CodeJam, session: AsyncSession = Depends(get_db_session)) -> Jam:
@router.post("/")
async def create_codejam(codejam: CodeJam, session: DBSession) -> CodeJamResponse:
"""
Create a new codejam and get back the one just created.
Expand Down
20 changes: 11 additions & 9 deletions api/routers/infractions.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from fastapi import APIRouter, HTTPException
from sqlalchemy.future import select

from api.database import DBSession
from api.database import Infraction as DbInfraction
from api.database import Jam, User
from api.dependencies import get_db_session
from api.models import Infraction, InfractionResponse

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


@router.get("/", response_model=list[InfractionResponse])
async def get_infractions(session: AsyncSession = Depends(get_db_session)) -> list[DbInfraction]:
@router.get("/")
async def get_infractions(session: DBSession) -> list[InfractionResponse]:
"""Get every infraction stored in the database."""
infractions = await session.execute(select(DbInfraction))
infractions.unique()
Expand All @@ -21,10 +20,9 @@ async def get_infractions(session: AsyncSession = Depends(get_db_session)) -> li

@router.get(
"/{infraction_id}",
response_model=InfractionResponse,
responses={404: {"description": "Infraction could not be found."}},
)
async def get_infraction(infraction_id: int, session: AsyncSession = Depends(get_db_session)) -> DbInfraction:
async def get_infraction(infraction_id: int, session: DBSession) -> InfractionResponse:
"""Get a specific infraction stored in the database by ID."""
infraction_result = await session.execute(select(DbInfraction).where(DbInfraction.id == infraction_id))
infraction_result.unique()
Expand All @@ -36,9 +34,13 @@ async def get_infraction(infraction_id: int, session: AsyncSession = Depends(get


@router.post(
"/", response_model=InfractionResponse, responses={404: {"Description": "Jam ID or User ID could not be found."}}
"/",
responses={404: {"Description": "Jam ID or User ID could not be found."}},
)
async def create_infraction(infraction: Infraction, session: AsyncSession = Depends(get_db_session)) -> DbInfraction:
async def create_infraction(
infraction: Infraction,
session: DBSession,
) -> InfractionResponse:
"""Add an infraction for a user to the database."""
jam_id = (await session.execute(select(Jam.id).where(Jam.id == infraction.jam_id))).scalars().one_or_none()

Expand Down
34 changes: 17 additions & 17 deletions api/routers/teams.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, Response
from fastapi import APIRouter, HTTPException, Response
from sqlalchemy import func
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select

from api.database import Jam, Team, TeamUser
from api.database import DBSession, Jam, Team, TeamUser
from api.database import User as DbUser
from api.dependencies import get_db_session
from api.models import TeamResponse, User

router = APIRouter(prefix="/teams", tags=["teams"])
Expand Down Expand Up @@ -35,8 +34,8 @@ async def ensure_user_exists(user_id: int, session: AsyncSession) -> DbUser:
return user


@router.get("/", response_model=list[TeamResponse])
async def get_teams(current_jam: bool = False, session: AsyncSession = Depends(get_db_session)) -> list[Team]:
@router.get("/")
async def get_teams(session: DBSession, current_jam: bool = False) -> list[TeamResponse]:
"""Get every code jam team in the database."""
if not current_jam:
teams = await session.execute(select(Team))
Expand All @@ -47,10 +46,12 @@ async def get_teams(current_jam: bool = False, session: AsyncSession = Depends(g
return teams.scalars().all()


@router.get("/find", response_model=TeamResponse, responses={404: {"description": "Team could not be found."}})
@router.get("/find", responses={404: {"description": "Team could not be found."}})
async def find_team_by_name(
name: str, jam_id: Optional[int] = None, session: AsyncSession = Depends(get_db_session)
) -> Team:
name: str,
session: DBSession,
jam_id: Optional[int] = None,
) -> TeamResponse:
"""Get a specific code jam team by name."""
if jam_id is None:
teams = await session.execute(
Expand All @@ -69,14 +70,14 @@ async def find_team_by_name(
return team


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


@router.get("/{team_id}/users", response_model=list[User], responses={404: {"description": "Team could not be found."}})
async def get_team_users(team_id: int, session: AsyncSession = Depends(get_db_session)) -> list[TeamUser]:
@router.get("/{team_id}/users", responses={404: {"description": "Team could not be found."}})
async def get_team_users(team_id: int, session: DBSession) -> list[User]:
"""Get the users of a specific code jam team in the database."""
await ensure_team_exists(team_id, session)

Expand All @@ -88,17 +89,14 @@ async def get_team_users(team_id: int, session: AsyncSession = Depends(get_db_se

@router.post(
"/{team_id}/users/{user_id}",
response_model=User,
responses={
404: {
"description": "Team or user could not be found.",
},
400: {"description": "This user is already on the team."},
},
)
async def add_user_to_team(
team_id: int, user_id: int, is_leader: bool = False, session: AsyncSession = Depends(get_db_session)
) -> TeamUser:
async def add_user_to_team(team_id: int, user_id: int, session: DBSession, is_leader: bool = False) -> User:
"""Add a user to a specific code jam team in the database."""
await ensure_team_exists(team_id, session)
await ensure_user_exists(user_id, session)
Expand Down Expand Up @@ -129,7 +127,9 @@ async def add_user_to_team(
},
)
async def remove_user_from_team(
team_id: int, user_id: int, session: AsyncSession = Depends(get_db_session)
team_id: int,
user_id: int,
session: DBSession,
) -> Response:
"""Remove a user from a specific code jam team in the database."""
await ensure_team_exists(team_id, session)
Expand Down
20 changes: 9 additions & 11 deletions api/routers/users.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from typing import Any

from fastapi import APIRouter, Depends, HTTPException
from fastapi import APIRouter, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select

from api.database import Jam, TeamUser, User
from api.dependencies import get_db_session
from api.database import DBSession, Jam, TeamUser, User
from api.models import UserResponse, UserTeamResponse

router = APIRouter(prefix="/users", tags=["users"])
Expand Down Expand Up @@ -47,17 +46,17 @@ async def get_user_data(session: AsyncSession, user_id: int) -> dict[str, Any]:
return user


@router.get("/", response_model=list[UserResponse])
async def get_users(session: AsyncSession = Depends(get_db_session)) -> list[dict[str, Any]]:
@router.get("/")
async def get_users(session: DBSession) -> list[UserResponse]:
"""Get information about all the users stored in the database."""
users = await session.execute(select(User.id))
users.unique()

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


@router.get("/{user_id}", response_model=UserResponse, responses={404: {"description": "User could not be found."}})
async def get_user(user_id: int, session: AsyncSession = Depends(get_db_session)) -> dict[str, Any]:
@router.get("/{user_id}", responses={404: {"description": "User could not be found."}})
async def get_user(user_id: int, session: DBSession) -> UserResponse:
"""Get a specific user stored in the database by ID."""
user = await session.execute(select(User).where(User.id == user_id))
user.unique()
Expand All @@ -68,8 +67,8 @@ async def get_user(user_id: int, session: AsyncSession = Depends(get_db_session)
return await get_user_data(session, user_id)


@router.post("/{user_id}", response_model=UserResponse, responses={400: {"description": "User already exists."}})
async def create_user(user_id: int, session: AsyncSession = Depends(get_db_session)) -> dict[str, Any]:
@router.post("/{user_id}", responses={400: {"description": "User already exists."}})
async def create_user(user_id: int, session: DBSession) -> UserResponse:
"""Create a new user with the specified ID to the database."""
user = await session.execute(select(User).where(User.id == user_id))
user.unique()
Expand All @@ -86,7 +85,6 @@ async def create_user(user_id: int, session: AsyncSession = Depends(get_db_sessi

@router.get(
"/{user_id}/current_team",
response_model=UserTeamResponse,
responses={
404: {
"description": (
Expand All @@ -95,7 +93,7 @@ async def create_user(user_id: int, session: AsyncSession = Depends(get_db_sessi
}
},
)
async def get_current_team(user_id: int, session: AsyncSession = Depends(get_db_session)) -> dict[str, Any]:
async def get_current_team(user_id: int, session: DBSession) -> UserTeamResponse:
"""Get a user's current team information."""
user = await session.execute(select(User).where(User.id == user_id))
user.unique()
Expand Down
14 changes: 4 additions & 10 deletions api/routers/winners.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
from fastapi import APIRouter, Depends, HTTPException
from fastapi import APIRouter, HTTPException
from sqlalchemy import func
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select

from api.database import Jam, User
from api.database import DBSession, Jam, User
from api.database import Winner as DbWinner
from api.dependencies import get_db_session
from api.models import Winner, WinnerResponse

router = APIRouter(prefix="/winners", tags=["winners"])


@router.get(
"/{jam_id}",
response_model=list[WinnerResponse],
responses={404: {"description": "The specified codejam could not be found."}},
)
async def get_winners(jam_id: int, session: AsyncSession = Depends(get_db_session)) -> list[DbWinner]:
async def get_winners(jam_id: int, session: DBSession) -> list[WinnerResponse]:
"""Get the top ten winners from the specified codejam."""
jam = await session.execute(select(Jam).where(Jam.id == jam_id))
jam.unique()
Expand All @@ -31,7 +28,6 @@ async def get_winners(jam_id: int, session: AsyncSession = Depends(get_db_sessio

@router.post(
"/{jam_id}",
response_model=list[WinnerResponse],
responses={
400: {"description": "The provided winners list is empty or contains duplicate users."},
404: {
Expand All @@ -40,9 +36,7 @@ async def get_winners(jam_id: int, session: AsyncSession = Depends(get_db_sessio
409: {"description": "One or more users are already a winner in the specified codejam."},
},
)
async def create_winners(
jam_id: int, winners: list[Winner], session: AsyncSession = Depends(get_db_session)
) -> list[WinnerResponse]:
async def create_winners(jam_id: int, winners: list[Winner], session: DBSession) -> list[WinnerResponse]:
"""Add the top ten winners to the specified codejam."""
jam = await session.execute(select(Jam).where(Jam.id == jam_id))
jam.unique()
Expand Down

0 comments on commit b5b0ff8

Please sign in to comment.