Convert to SQLModel + adding matchday

This commit is contained in:
Simon 2022-09-19 10:45:08 +02:00
parent bf3bd68e52
commit 3b6ba0a2a4
37 changed files with 705 additions and 291 deletions

View File

@ -4,9 +4,13 @@ from app.api.api_v1.endpoints import users
from app.api.api_v1.endpoints import login from app.api.api_v1.endpoints import login
from app.api.api_v1.endpoints import player from app.api.api_v1.endpoints import player
from app.api.api_v1.endpoints import team from app.api.api_v1.endpoints import team
from app.api.api_v1.endpoints import match
from app.api.api_v1.endpoints import matchday
api_router = APIRouter() api_router = APIRouter()
api_router.include_router(login.router, tags=["login"]) api_router.include_router(login.router, tags=["login"])
api_router.include_router(users.router, prefix="/users", tags=["users"]) api_router.include_router(users.router, prefix="/users", tags=["users"])
api_router.include_router(player.router, prefix="/player", tags=["player"]) api_router.include_router(player.router, prefix="/player", tags=["player"])
api_router.include_router(team.router, prefix="/team", tags=["team"]) api_router.include_router(team.router, prefix="/team", tags=["team"])
api_router.include_router(matchday.router, prefix="/matchday", tags=["matchday"])
#api_router.include_router(match.router, prefix="/match", tags=["match"])

View File

@ -5,11 +5,14 @@ from fastapi import APIRouter, Body, Depends, HTTPException
from fastapi.security import OAuth2PasswordRequestForm from fastapi.security import OAuth2PasswordRequestForm
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app import crud, models, schemas from app import crud
from app.api import deps from app.api import deps
from app.core import security from app.core import security
from app.core.config import settings from app.core.config import settings
from app.core.security import get_password_hash from app.core.security import get_password_hash
from app.models.msg import Msg
from app.models.token import Token
from app.models.user import User
from app.utils import ( from app.utils import (
generate_password_reset_token, generate_password_reset_token,
send_reset_password_email, send_reset_password_email,
@ -19,7 +22,7 @@ from app.utils import (
router = APIRouter() router = APIRouter()
@router.post("/login/access-token", response_model=schemas.Token) @router.post("/login/access-token", response_model=Token)
def login_access_token( def login_access_token(
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
form_data: OAuth2PasswordRequestForm = Depends(), form_data: OAuth2PasswordRequestForm = Depends(),
@ -47,9 +50,9 @@ def login_access_token(
} }
@router.post("/login/test-token", response_model=schemas.User) @router.post("/login/test-token", response_model=User)
def test_token( def test_token(
current_user: models.User = Depends(deps.get_current_user), current_user: User = Depends(deps.get_current_user),
) -> Any: ) -> Any:
""" """
Test access token Test access token
@ -57,7 +60,7 @@ def test_token(
return current_user return current_user
@router.post("/password-recovery/{email}", response_model=schemas.Msg) @router.post("/password-recovery/{email}", response_model=Msg)
def recover_password(email: str, db: Session = Depends(deps.get_db)) -> Any: def recover_password(email: str, db: Session = Depends(deps.get_db)) -> Any:
""" """
Password Recovery Password Recovery
@ -76,7 +79,7 @@ def recover_password(email: str, db: Session = Depends(deps.get_db)) -> Any:
return {"msg": "Password recovery email sent"} return {"msg": "Password recovery email sent"}
@router.post("/reset-password/", response_model=schemas.Msg) @router.post("/reset-password/", response_model=Msg)
def reset_password( def reset_password(
token: str = Body(...), token: str = Body(...),
new_password: str = Body(...), new_password: str = Body(...),

View File

@ -0,0 +1,96 @@
from typing import Any, List
from fastapi import APIRouter, Body, Depends, HTTPException
from fastapi.encoders import jsonable_encoder
from pydantic.networks import EmailStr
from sqlalchemy.orm import Session
from app import crud
from app.api import deps
from app.models.player import Player, PlayerCreate, PlayerUpdate
from app.models.user import User
router = APIRouter()
@router.get("/{id}", response_model=Player)
def read_player(
*,
db: Session = Depends(deps.get_db),
firstname: str,
lastname: str,
current_user: User = Depends(deps.get_current_active_user),
) -> Any:
"""
Get player by firstname and lastname.
"""
player = crud.player.get_player_by_name(
db=db, firstname=firstname, lastname=lastname
)
if not player:
raise HTTPException(status_code=404, detail="player not found")
if not crud.user.is_superuser(current_user):
raise HTTPException(status_code=400, detail="Not enough permissions")
return player
@router.post("/", response_model=List[Player])
def create_player(
*,
db: Session = Depends(deps.get_db),
players_in: list[PlayerCreate],
current_user: User = Depends(deps.get_current_active_superuser),
) -> Any:
"""
Create new user.
"""
player_out = []
for player_in in players_in:
player = crud.player.get_player_by_name(
db, firstname=player_in.firstname, lastname=player_in.lastname
)
if player:
raise HTTPException(
status_code=400,
detail=f"The user with this username already exists in the "
f"system. Player is {player}",
)
player = crud.player.create(db, obj_in=player_in)
player_out.append(player)
return player_out
@router.get("/", response_model=List[Player])
def get_players(
db: Session = Depends(deps.get_db),
skip: int = 0,
limit: int = 100,
current_user: User = Depends(deps.get_current_active_superuser),
) -> Any:
"""
Retrieve all players.
"""
player = crud.player.get_multi(db, skip=skip, limit=limit)
return player
@router.post("/{id}", response_model=Player)
def update_player(
*,
db: Session = Depends(deps.get_db),
id: int,
player_in: PlayerUpdate,
current_user: User = Depends(deps.get_current_active_user),
) -> Any:
"""
Update player.
"""
player = crud.player.get(db=db, id=id)
if not player:
raise HTTPException(status_code=404, detail="Player not found")
player = crud.player.update(db=db, db_obj=player, obj_in=player_in)
return player

View File

@ -0,0 +1,114 @@
from typing import Any, List
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app import crud
from app.api import deps
from app.models.matchday import Matchday, MatchdayCreate, MatchdayUpdate, \
MatchdayWithPlayers
from app.models.user import User
router = APIRouter()
@router.get("/{matchday_id}", response_model=MatchdayWithPlayers)
def read_matchday(
*,
db: Session = Depends(deps.get_db),
matchday_id: int,
current_user: User = Depends(deps.get_current_active_user),
) -> Any:
"""
Get matchday by firstname and lastname.
"""
matchday = crud.matchday.get(
db=db, id=matchday_id
)
if not matchday:
raise HTTPException(status_code=404, detail="matchday not found")
if not crud.user.is_superuser(current_user):
raise HTTPException(status_code=400, detail="Not enough permissions")
return matchday
@router.post("/", response_model=Matchday)
def create_matchday(
*,
db: Session = Depends(deps.get_db),
matchday_in: MatchdayCreate,
current_user: User = Depends(deps.get_current_active_superuser),
) -> Any:
"""
Create new user.
"""
matchday = crud.matchday.get_unique_day(db, obj_in=matchday_in)
if matchday:
raise HTTPException(
status_code=400,
detail=f"The matchday with this day already exists in the "
f"system. Matchday is {matchday}",
)
matchday = crud.matchday.create(db, obj_in=matchday_in)
return matchday
@router.get("/", response_model=List[MatchdayWithPlayers])
def get_matchdays(
db: Session = Depends(deps.get_db),
skip: int = 0,
limit: int = 100,
current_user: User = Depends(deps.get_current_active_superuser),
) -> Any:
"""
Retrieve all matchdays.
"""
matchday = crud.matchday.get_multi(db, skip=skip, limit=limit)
return matchday
@router.post("/{matchday_id}", response_model=Matchday)
def update_matchday(
*,
db: Session = Depends(deps.get_db),
matchday_id: int,
matchday_in: MatchdayUpdate,
current_user: User = Depends(deps.get_current_active_user),
) -> Any:
"""
Update matchday.
"""
matchday = crud.matchday.get(db=db, id=matchday_id)
if not matchday:
raise HTTPException(status_code=404, detail="Matchday not found")
matchday = crud.matchday.update(db=db, db_obj=matchday, obj_in=matchday_in)
return matchday
@router.put("/players/{matchday_id}", response_model=Matchday)
def add_player_matchday(
*,
db: Session = Depends(deps.get_db),
player_id: int,
matchday_id: int,
current_user: User = Depends(deps.get_current_active_superuser),
) -> Any:
"""
Add player to matchday.
"""
if crud.player.get(db, id=player_id) is None:
raise HTTPException(status_code=404, detail="Player not found")
if crud.matchday.get(db=db, id=matchday_id) is None:
raise HTTPException(status_code=404, detail="Matchday not found")
if crud.matchday.is_player_in_matchday(
db=db, player_id=player_id, matchday_id=matchday_id
):
raise HTTPException(
status_code=404, detail="Player is already in team"
)
matchday = crud.matchday.add_player_in_matchday(db, matchday_id, player_id)
return matchday

View File

@ -1,31 +1,30 @@
from typing import Any, List from typing import Any, List
from fastapi import APIRouter, Body, Depends, HTTPException from fastapi import APIRouter, Depends, HTTPException
from fastapi.encoders import jsonable_encoder
from pydantic.networks import EmailStr
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app import crud, models, schemas from app import crud
from app.api import deps from app.api import deps
from app.core.config import settings
from app.schemas.player import PlayerUpdate from app.models.player import Player, PlayerCreate, PlayerUpdate, \
PlayerTeamsMatchdays
from app.models.user import User
router = APIRouter() router = APIRouter()
@router.get("/{id}", response_model=schemas.Player) @router.get("/{player_id}", response_model=PlayerTeamsMatchdays)
def read_player( def read_player(
*, *,
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
firstname: str, player_id: int,
lastname: str, current_user: User = Depends(deps.get_current_active_user),
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any: ) -> Any:
""" """
Get player by firstname and lastname. Get player by id.
""" """
player = crud.player.get_player_by_name( player = crud.player.get(
db=db, firstname=firstname, lastname=lastname db=db, id=player_id
) )
if not player: if not player:
raise HTTPException(status_code=404, detail="player not found") raise HTTPException(status_code=404, detail="player not found")
@ -34,56 +33,60 @@ def read_player(
return player return player
@router.post("/", response_model=schemas.Player) @router.post("/", response_model=List[Player])
def create_player( def create_player(
*, *,
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
player_in: schemas.PlayerCreate, players_in: list[PlayerCreate],
current_user: models.User = Depends(deps.get_current_active_superuser), current_user: User = Depends(deps.get_current_active_superuser),
) -> Any: ) -> Any:
""" """
Create new user. Create new user.
""" """
player = crud.player.get_player_by_name( player_out = []
db, firstname=player_in.firstname, lastname=player_in.lastname for player_in in players_in:
) player = crud.player.get_player_by_name(
if player: db, firstname=player_in.firstname, lastname=player_in.lastname
raise HTTPException(
status_code=400,
detail="The user with this username already exists in the system.",
) )
player = crud.player.create(db, obj_in=player_in) if player:
raise HTTPException(
status_code=400,
detail=f"The user with this username already exists in the "
f"system. Player is {player}",
)
player = crud.player.create(db, obj_in=player_in)
player_out.append(player)
return player return player_out
@router.get("/", response_model=List[schemas.Player]) @router.get("/", response_model=List[PlayerTeamsMatchdays])
def get_players( def get_players(
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
skip: int = 0, skip: int = 0,
limit: int = 100, limit: int = 100,
current_user: models.User = Depends(deps.get_current_active_superuser), current_user: User = Depends(deps.get_current_active_superuser),
) -> Any: ) -> Any:
""" """
Retrieve all players. Retrieve all players.
""" """
player = crud.player.get_players(db, skip=skip, limit=limit) player = crud.player.get_multi(db, skip=skip, limit=limit)
return player return player
@router.post("/{id}", response_model=schemas.Player) @router.post("/{player_id}", response_model=Player)
def update_player( def update_player(
*, *,
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
id: int, player_id: int,
player_in: PlayerUpdate, player_in: PlayerUpdate,
current_user: models.User = Depends(deps.get_current_active_user), current_user: User = Depends(deps.get_current_active_user),
) -> Any: ) -> Any:
""" """
Update player. Update player.
""" """
player = crud.player.get(db=db, id=id) player = crud.player.get(db=db, id=player_id)
if not player: if not player:
raise HTTPException(status_code=404, detail="Player not found") raise HTTPException(status_code=404, detail="Player not found")

View File

@ -4,24 +4,25 @@ from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app import crud, models, schemas from app import crud
from app.api import deps from app.api import deps
from app.models.team import Team, TeamCreate, TeamWithPlayers
from app.models.user import User
router = APIRouter() router = APIRouter()
@router.get("/{id}", response_model=schemas.Team) @router.get("/{team_id}", response_model=Team)
def get_team( def get_team(
*, *,
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
id: int, team_id: int,
current_user: models.User = Depends(deps.get_current_active_user), current_user: User = Depends(deps.get_current_active_user),
) -> Any: ) -> Any:
""" """
Get team by id. Get team by id.
""" """
team = crud.team.get_team(db=db, team_id=id) team = crud.team.get_team(db=db, team_id=team_id)
if not team: if not team:
raise HTTPException(status_code=404, detail="player not found") raise HTTPException(status_code=404, detail="player not found")
if not crud.user.is_superuser(current_user): if not crud.user.is_superuser(current_user):
@ -29,26 +30,26 @@ def get_team(
return team return team
@router.get("/", response_model=List[schemas.Team]) @router.get("/", response_model=List[TeamWithPlayers])
def get_teams( def get_teams(
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
skip: int = 0, skip: int = 0,
limit: int = 100, limit: int = 100,
current_user: models.User = Depends(deps.get_current_active_superuser), current_user: User = Depends(deps.get_current_active_superuser),
) -> Any: ) -> Any:
""" """
Retrieve teams. Retrieve teams.
""" """
team = crud.team.get_teams(db, skip=skip, limit=limit) team = crud.team.get_multi( db, skip=skip, limit=limit)
return team return team
@router.post("/", response_model=schemas.Team) @router.post("/", response_model=Team)
def create_team( def create_team(
*, *,
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
team_in: schemas.TeamCreate, team_in: TeamCreate,
current_user: models.User = Depends(deps.get_current_active_superuser), current_user: User = Depends(deps.get_current_active_superuser),
) -> Any: ) -> Any:
""" """
Create team. Create team.
@ -59,20 +60,20 @@ def create_team(
return team return team
@router.put("/players/{team_id}", response_model=schemas.Team) @router.put("/players/{team_id}", response_model=Team)
def add_player_team( def add_player_team(
*, *,
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
player_id: int, player_id: int,
team_id: int, team_id: int,
current_user: models.User = Depends(deps.get_current_active_superuser), current_user: User = Depends(deps.get_current_active_superuser),
) -> Any: ) -> Any:
""" """
Add player to team. Add player to team.
""" """
if crud.player.get_player(db, player_id=player_id) is None: if crud.player.get(db, id=player_id) is None:
raise HTTPException(status_code=404, detail="Player not found") raise HTTPException(status_code=404, detail="Player not found")
if crud.team.get_team(db=db, team_id=team_id) is None: if crud.team.get(db=db, id=team_id) is None:
raise HTTPException(status_code=404, detail="Team not found") raise HTTPException(status_code=404, detail="Team not found")
if crud.team.is_player_in_team( if crud.team.is_player_in_team(
db=db, player_id=player_id, team_id=team_id db=db, player_id=player_id, team_id=team_id

View File

@ -5,20 +5,20 @@ from fastapi.encoders import jsonable_encoder
from pydantic.networks import EmailStr from pydantic.networks import EmailStr
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app import crud, models, schemas from app import crud, models
from app.api import deps from app.api import deps
from app.core.config import settings from app.core.config import settings
from app.models.user import UserUpdate, User, UserCreate
router = APIRouter() router = APIRouter()
@router.get("/", response_model=List[schemas.User]) @router.get("/", response_model=List[User])
def read_users( def read_users(
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
skip: int = 0, skip: int = 0,
limit: int = 100, limit: int = 100,
current_user: models.User = Depends(deps.get_current_active_superuser), current_user: User = Depends(deps.get_current_active_superuser),
) -> Any: ) -> Any:
""" """
Retrieve users. Retrieve users.
@ -27,12 +27,12 @@ def read_users(
return users return users
@router.post("/", response_model=schemas.User) @router.post("/", response_model=User)
def create_user( def create_user(
*, *,
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
user_in: schemas.UserCreate, user_in: UserCreate,
current_user: models.User = Depends(deps.get_current_active_superuser), current_user: User = Depends(deps.get_current_active_superuser),
) -> Any: ) -> Any:
""" """
Create new user. Create new user.
@ -48,20 +48,20 @@ def create_user(
return user return user
@router.put("/me", response_model=schemas.User) @router.put("/me", response_model=User)
def update_user_me( def update_user_me(
*, *,
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
password: str = Body(None), password: str = Body(None),
full_name: str = Body(None), full_name: str = Body(None),
email: EmailStr = Body(None), email: EmailStr = Body(None),
current_user: models.User = Depends(deps.get_current_active_user), current_user: User = Depends(deps.get_current_active_user),
) -> Any: ) -> Any:
""" """
Update own user. Update own user.
""" """
current_user_data = jsonable_encoder(current_user) current_user_data = jsonable_encoder(current_user)
user_in = schemas.UserUpdate(**current_user_data) user_in = UserUpdate(**current_user_data)
if password is not None: if password is not None:
user_in.password = password user_in.password = password
if full_name is not None: if full_name is not None:
@ -72,10 +72,10 @@ def update_user_me(
return user return user
@router.get("/me", response_model=schemas.User) @router.get("/me", response_model=User)
def read_user_me( def read_user_me(
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_active_user), current_user: User = Depends(deps.get_current_active_user),
) -> Any: ) -> Any:
""" """
Get current user. Get current user.
@ -83,7 +83,7 @@ def read_user_me(
return current_user return current_user
@router.post("/open", response_model=schemas.User) @router.post("/open", response_model=User)
def create_user_open( def create_user_open(
*, *,
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
@ -105,17 +105,17 @@ def create_user_open(
status_code=400, status_code=400,
detail="The user with this username already exists in the system", detail="The user with this username already exists in the system",
) )
user_in = schemas.UserCreate( user_in = UserCreate(
password=password, email=email, full_name=full_name password=password, email=email, full_name=full_name
) )
user = crud.user.create(db, obj_in=user_in) user = crud.user.create(db, obj_in=user_in)
return user return user
@router.get("/{user_id}", response_model=schemas.User) @router.get("/{user_id}", response_model=User)
def read_user_by_id( def read_user_by_id(
user_id: int, user_id: int,
current_user: models.User = Depends(deps.get_current_active_user), current_user: User = Depends(deps.get_current_active_user),
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
) -> Any: ) -> Any:
""" """
@ -131,13 +131,13 @@ def read_user_by_id(
return user return user
@router.put("/{user_id}", response_model=schemas.User) @router.put("/{user_id}", response_model=User)
def update_user( def update_user(
*, *,
db: Session = Depends(deps.get_db), db: Session = Depends(deps.get_db),
user_id: int, user_id: int,
user_in: schemas.UserUpdate, user_in: UserUpdate,
current_user: models.User = Depends(deps.get_current_active_superuser), current_user: User = Depends(deps.get_current_active_superuser),
) -> Any: ) -> Any:
""" """
Update a user. Update a user.

View File

@ -6,7 +6,9 @@ from jose import jwt
from pydantic import ValidationError from pydantic import ValidationError
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app import crud, models, schemas from app import crud
from app.models.token import TokenPayload
from app.models.user import User
from app.core import security from app.core import security
from app.core.config import settings from app.core.config import settings
from app.db.session import SessionLocal from app.db.session import SessionLocal
@ -26,12 +28,12 @@ def get_db() -> Generator:
def get_current_user( def get_current_user(
db: Session = Depends(get_db), token: str = Depends(reusable_oauth2) db: Session = Depends(get_db), token: str = Depends(reusable_oauth2)
) -> models.User: ) -> User:
try: try:
payload = jwt.decode( payload = jwt.decode(
token, settings.SECRET_KEY, algorithms=[security.ALGORITHM] token, settings.SECRET_KEY, algorithms=[security.ALGORITHM]
) )
token_data = schemas.TokenPayload(**payload) token_data = TokenPayload(**payload)
except (jwt.JWTError, ValidationError): except (jwt.JWTError, ValidationError):
raise HTTPException( raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN, status_code=status.HTTP_403_FORBIDDEN,
@ -44,16 +46,17 @@ def get_current_user(
def get_current_active_user( def get_current_active_user(
current_user: models.User = Depends(get_current_user), current_user: User = Depends(get_current_user),
) -> models.User: ) -> User:
if not crud.user.is_active(current_user): if not crud.user.is_active(current_user):
raise HTTPException(status_code=400, detail="Inactive user") raise HTTPException(status_code=400, detail="Inactive user")
return current_user return current_user
def get_current_active_superuser( def get_current_active_superuser(
current_user: models.User = Depends(get_current_user), current_user: User = Depends(get_current_user),
) -> models.User: ) -> User:
if not crud.user.is_superuser(current_user): if not crud.user.is_superuser(current_user):
raise HTTPException( raise HTTPException(
status_code=400, detail="The user doesn't have enough privileges" status_code=400, detail="The user doesn't have enough privileges"

View File

@ -1,3 +1,4 @@
from .crud_user import user from .crud_user import user
from .crud_player import player from .crud_player import player
from .crud_team import team from .crud_team import team
from .crud_matchday import matchday

View File

@ -3,6 +3,7 @@ from typing import Any, Dict, Generic, List, Optional, Type, TypeVar, Union
from fastapi.encoders import jsonable_encoder from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel from pydantic import BaseModel
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from sqlmodel import select
from app.db.base_class import Base from app.db.base_class import Base
@ -22,12 +23,14 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
self.model = model self.model = model
def get(self, db: Session, id: Any) -> Optional[ModelType]: def get(self, db: Session, id: Any) -> Optional[ModelType]:
return db.query(self.model).filter(self.model.id == id).first() statement = select(self.model).where(self.model.id == id)
return db.execute(statement).scalar_one_or_none()
def get_multi( def get_multi(
self, db: Session, *, skip: int = 0, limit: int = 100 self, db: Session, *, skip: int = 0, limit: int = 100
) -> List[ModelType]: ) -> List[ModelType]:
return db.query(self.model).offset(skip).limit(limit).all() statement = select(self.model).offset(skip).limit(limit)
return db.execute(statement).scalars().all()
def create(self, db: Session, *, obj_in: CreateSchemaType) -> ModelType: def create(self, db: Session, *, obj_in: CreateSchemaType) -> ModelType:
obj_in_data = jsonable_encoder(obj_in) obj_in_data = jsonable_encoder(obj_in)
@ -58,7 +61,7 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
return db_obj return db_obj
def remove(self, db: Session, *, id: int) -> ModelType: def remove(self, db: Session, *, id: int) -> ModelType:
obj = db.query(self.model).get(id) obj = db.execute(self.model).get(id)
db.delete(obj) db.delete(obj)
db.commit() db.commit()
return obj return obj

45
app/crud/crud_matchday.py Normal file
View File

@ -0,0 +1,45 @@
from typing import Any, Dict, Union, Optional
from sqlmodel import select
from sqlalchemy.orm import Session
from app.crud import player as crud_player
from app.crud.base import CRUDBase
from app.models.matchday import Matchday, MatchdayCreate, MatchdayUpdate
class CRUDMatchday(CRUDBase[Matchday, MatchdayCreate, MatchdayUpdate]):
def create(self, db: Session, *, obj_in: MatchdayCreate) -> Matchday:
db_obj = Matchday(
day=obj_in.day)
db.add(db_obj)
db.commit()
db.refresh(db_obj)
return db_obj
def get_unique_day(self, db: Session, *, obj_in: Matchday) -> Any:
day = obj_in.day
statement = select(Matchday).where(Matchday.day == day)
result = db.execute(statement).all()
return result
def add_player_in_matchday(self, db: Session, matchday_id: int, player_id: int
) -> Matchday:
matchday_in = self.get(db=db, id=matchday_id)
db_player = crud_player.get(db=db, id=player_id)
matchday_in.players.append(db_player)
db.commit()
return matchday_in
def is_player_in_matchday(
self, db: Session, *, player_id: int, matchday_id: int
) -> bool:
matchday = self.get(db=db, id=matchday_id)
if matchday is None:
return False
db_player = crud_player.get(db=db, id=player_id)
return db_player in matchday.players
matchday = CRUDMatchday(Matchday)

View File

@ -3,8 +3,7 @@ from typing import Any, Dict, Optional, Union
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.crud.base import CRUDBase from app.crud.base import CRUDBase
from app.models.player import Player from app.models.player import Player, PlayerCreate, PlayerUpdate
from app.schemas.player import PlayerCreate, PlayerUpdate, PlayerUpdateTeam
class CRUDPlayer(CRUDBase[Player, PlayerCreate, PlayerUpdate]): class CRUDPlayer(CRUDBase[Player, PlayerCreate, PlayerUpdate]):
@ -21,12 +20,6 @@ class CRUDPlayer(CRUDBase[Player, PlayerCreate, PlayerUpdate]):
.first() .first()
) )
def get_player(self, db: Session, *, player_id: int) -> Optional[Player]:
return db.query(Player).filter(Player.id == player_id).first()
def get_players(self, db: Session, skip: int = 0, limit: int = 100):
return db.query(Player).offset(skip).limit(limit).all()
def create(self, db: Session, *, obj_in: PlayerCreate) -> Player: def create(self, db: Session, *, obj_in: PlayerCreate) -> Player:
db_obj = Player( db_obj = Player(
firstname=obj_in.firstname, firstname=obj_in.firstname,
@ -38,4 +31,5 @@ class CRUDPlayer(CRUDBase[Player, PlayerCreate, PlayerUpdate]):
return db_obj return db_obj
player = CRUDPlayer(Player) player = CRUDPlayer(Player)

View File

@ -1,22 +1,14 @@
from typing import Any, Dict, Optional, Union, List from typing import Any, Dict, Optional, Union, List
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from sqlmodel import select
from app.crud.base import CRUDBase from app.crud.base import CRUDBase
from app.crud import player as crud_player from app.crud import player as crud_player
from app.models.team import Team from app.models.team import Team, TeamCreate, TeamUpdate
from app.schemas.team import TeamCreate, TeamUpdate
class CRUDTeam(CRUDBase[Team, TeamCreate, TeamUpdate]): class CRUDTeam(CRUDBase[Team, TeamCreate, TeamUpdate]):
def get_team(self, db: Session, *, team_id: int) -> Optional[Team]:
return db.query(Team).filter(Team.team_id == team_id).first()
def get_teams(
self, db: Session, skip: int = 0, limit: int = 100
) -> List[Team]:
return db.query(Team).offset(skip).limit(limit).all()
def create(self, db: Session, *, obj_in: TeamCreate) -> Team: def create(self, db: Session, *, obj_in: TeamCreate) -> Team:
db_obj = Team(teamname=obj_in.teamname) db_obj = Team(teamname=obj_in.teamname)
@ -28,19 +20,19 @@ class CRUDTeam(CRUDBase[Team, TeamCreate, TeamUpdate]):
def add_player_in_team( def add_player_in_team(
self, db: Session, team_id: int, player_id: int self, db: Session, team_id: int, player_id: int
) -> Team: ) -> Team:
team = self.get_team(db=db, team_id=team_id) team_in = self.get(db=db, id=team_id)
db_player = crud_player.get_player(db=db, player_id=player_id) db_player = crud_player.get(db=db, id=player_id)
team.players.append(db_player) team_in.players.append(db_player)
db.commit() db.commit()
return team return team_in
def is_player_in_team( def is_player_in_team(
self, db: Session, *, player_id: int, team_id: int self, db: Session, *, player_id: int, team_id: int
) -> bool: ) -> bool:
team = self.get_team(db=db, team_id=team_id) team = self.get(db=db, id=team_id)
if team is None: if team is None:
return False return False
db_player = crud_player.get_player(db=db, player_id=player_id) db_player = crud_player.get(db=db, id=player_id)
return db_player in team.players return db_player in team.players

View File

@ -4,8 +4,8 @@ from sqlalchemy.orm import Session
from app.core.security import get_password_hash, verify_password from app.core.security import get_password_hash, verify_password
from app.crud.base import CRUDBase from app.crud.base import CRUDBase
from app.models.user import User from app.models.user import User, UserCreate, UserUpdate
from app.schemas.user import UserCreate, UserUpdate
class CRUDUser(CRUDBase[User, UserCreate, UserUpdate]): class CRUDUser(CRUDBase[User, UserCreate, UserUpdate]):

View File

@ -1,13 +1,12 @@
from typing import Any from typing import Optional
from sqlalchemy.ext.declarative import as_declarative, declared_attr from sqlalchemy.ext.declarative import declared_attr
from sqlmodel import Field, SQLModel
@as_declarative() class Base(SQLModel):
class Base: id: Optional[int] = Field(default=None, primary_key=True, index=True)
id: Any
__name__: str __name__: str
# Generate __tablename__ automatically # Generate __tablename__ automatically
@declared_attr
def __tablename__(cls) -> str:
return cls.__name__.lower()

View File

@ -1,6 +1,6 @@
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app import crud, schemas from app import crud
from app.core.config import settings from app.core.config import settings
from app.db import base # noqa: F401 from app.db import base # noqa: F401
@ -9,6 +9,9 @@ from app.db import base # noqa: F401
# for more details: https://github.com/tiangolo/full-stack-fastapi-postgresql/issues/28 # for more details: https://github.com/tiangolo/full-stack-fastapi-postgresql/issues/28
from app.db.base_class import Base from app.db.base_class import Base
from app.db.session import engine from app.db.session import engine
from app.models.player import Player, PlayerCreate
from app.models.team import TeamCreate, TeamWithPlayers
from app.models.user import UserCreate
def init_db(db: Session) -> None: def init_db(db: Session) -> None:
@ -19,9 +22,34 @@ def init_db(db: Session) -> None:
user = crud.user.get_by_email(db, email=settings.FIRST_SUPERUSER) user = crud.user.get_by_email(db, email=settings.FIRST_SUPERUSER)
if not user: if not user:
user_in = schemas.UserCreate( user_in = UserCreate(
email=settings.FIRST_SUPERUSER, email=settings.FIRST_SUPERUSER,
password=settings.FIRST_SUPERUSER_PASSWORD, password=settings.FIRST_SUPERUSER_PASSWORD,
is_superuser=True, is_superuser=True,
) )
user = crud.user.create(db, obj_in=user_in) # noqa: F841 user = crud.user.create(db, obj_in=user_in) # noqa: F841
players = crud.player.get_multi(db=db)
if not players:
player_in = PlayerCreate(
firstname="Simon",
lastname="Milvert",
)
player = crud.player.create(db=db, obj_in=player_in) # noqa: F841
player_in = PlayerCreate(
firstname="Johan",
lastname="Moden")
player = crud.player.create(db=db, obj_in=player_in) # noqa: F841
teams = crud.team.get_multi(db=db)
if not True:
print("Create Team")
player = crud.player.get(db, id=1)
team_in = TeamWithPlayers(teamname='1', players=[player])
team = crud.team.create(db, obj_in=team_in) # noqa: F841

View File

@ -1,7 +1,13 @@
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
from app.core.config import settings from app.core.config import settings
from sqlmodel import create_engine, SQLModel
engine = create_engine(settings.SQLALCHEMY_DATABASE_URI, pool_pre_ping=True) engine = create_engine(settings.SQLALCHEMY_DATABASE_URI, pool_pre_ping=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

View File

@ -1,12 +1,18 @@
import logging
import uvicorn
from fastapi import FastAPI from fastapi import FastAPI
from loguru import logger
from starlette.middleware.cors import CORSMiddleware from starlette.middleware.cors import CORSMiddleware
from app.api.api_v1.api import api_router from app.api.api_v1.api import api_router
from app.core.config import settings from app.core.config import settings
from app.db.init_db import init_db from app.db.init_db import init_db
from app.db.session import SessionLocal from app.db.session import SessionLocal, create_db_and_tables
from app.utils import configure_log_handler
db = SessionLocal() db = SessionLocal()
configure_log_handler(log_level=logging.DEBUG)
init_db(db) init_db(db)
@ -14,6 +20,10 @@ app = FastAPI(
title=settings.PROJECT_NAME, title=settings.PROJECT_NAME,
openapi_url=f"{settings.API_V1_STR}/openapi.json", openapi_url=f"{settings.API_V1_STR}/openapi.json",
) )
@app.on_event("startup")
def on_startup():
create_db_and_tables()
# Set all CORS enabled origins # Set all CORS enabled origins
if settings.BACKEND_CORS_ORIGINS: if settings.BACKEND_CORS_ORIGINS:
@ -28,3 +38,4 @@ if settings.BACKEND_CORS_ORIGINS:
) )
app.include_router(api_router, prefix=settings.API_V1_STR) app.include_router(api_router, prefix=settings.API_V1_STR)

View File

@ -1,5 +1,13 @@
# from .match import Match from app.models.matchday import Matchday, MatchdayWithPlayers
# from .matchday import Matchday from app.models.player import Player, PlayerTeamsMatchdays
from .player import Player from app.models.team import Team, TeamWithPlayers
from .team import Team
from .user import User
Player.update_forward_refs(Team=Team, Matchday=Matchday)
PlayerTeamsMatchdays.update_forward_refs(Team=Team, Matchday=Matchday)
Team.update_forward_refs(Player=Player)
TeamWithPlayers.update_forward_refs(Player=Player)
Matchday.update_forward_refs(Player=Player)
MatchdayWithPlayers.update_forward_refs(Player=Player)

View File

@ -1,11 +1,14 @@
from sqlalchemy import Column, DateTime, ForeignKey, Integer, String from typing import Optional
from sqlalchemy.orm import relationship
from app.db.database import Base from sqlmodel import SQLModel, Field
from app.db.base_class import Base
class Match(Base): class Match(SQLModel, Base, table=True):
matchname: Optional[str] = Field(nullable=False)
"""
match_id = Column(Integer, primary_key=True) match_id = Column(Integer, primary_key=True)
team_1 = Column(ForeignKey("team.id"), nullable=False) team_1 = Column(ForeignKey("team.id"), nullable=False)
team_2 = Column(ForeignKey("team.id"), nullable=False) team_2 = Column(ForeignKey("team.id"), nullable=False)
@ -18,3 +21,4 @@ class Match(Base):
team = relationship("Team", primaryjoin="Match.team_1 == Team.team_id") team = relationship("Team", primaryjoin="Match.team_1 == Team.team_id")
team1 = relationship("Team", primaryjoin="Match.team_2 == Team.team_id") team1 = relationship("Team", primaryjoin="Match.team_2 == Team.team_id")
team2 = relationship("Team", primaryjoin="Match.winner == Team.team_id") team2 = relationship("Team", primaryjoin="Match.winner == Team.team_id")
"""

View File

@ -1,17 +1,36 @@
from sqlalchemy import Column, DateTime, ForeignKey, Integer, String from datetime import date, datetime
from sqlalchemy.orm import relationship from typing import List, Optional, TYPE_CHECKING
from sqlalchemy import Date
from sqlmodel import SQLModel, Relationship, Field, Column, func
from app.db.base_class import Base from app.db.base_class import Base
from app.models.matchdayplayer import MatchdayPlayerLink
if TYPE_CHECKING:
from app.models.player import Player
class MatchdayPlayer(Base): class MatchdayBase(SQLModel):
day: date
player_id = Column("players_id", ForeignKey("players.id"), primary_key=True)
matchday_id = Column("teams_id", ForeignKey("teams.id"), primary_key=True)
class Matchday(Base): class Matchday(MatchdayBase, Base, table=True):
day: date = Field(
default=None,
sa_column=Column(Date, server_default=func.now()))
players: List["Player"] = Relationship(back_populates="matchdays",
link_model=MatchdayPlayerLink)
matchday_id = Column(Integer, primary_key=True)
day = Column(DateTime, nullable=False) class MatchdayCreate(MatchdayBase):
players = relationship("Player", secondary="matchdayplayer") day: date
class MatchdayUpdate(MatchdayBase):
day: date
class MatchdayWithPlayers(MatchdayBase):
day: date
players: Optional[List["Player"]]

View File

@ -0,0 +1,11 @@
from typing import Optional
from sqlmodel import SQLModel, Field
class MatchdayPlayerLink(SQLModel, table=True):
player_id: Optional[int] = Field(
default=None, foreign_key="player.id", primary_key=True
)
matchday_id: Optional[int] = Field(
default=None, foreign_key="matchday.id", primary_key=True
)

View File

@ -1,16 +1,35 @@
from sqlalchemy import Column, Integer, String, ForeignKey from typing import Optional, List, TYPE_CHECKING
from sqlalchemy.orm import relationship
from sqlmodel import SQLModel, Field, Relationship
from app.db.base_class import Base from app.db.base_class import Base
from app.models.matchdayplayer import MatchdayPlayerLink
from app.models.teamplayers import TeamPlayerLink
class Player(Base): if TYPE_CHECKING:
from app.models import Team, Matchday
class PlayerBase(SQLModel):
firstname: str = Field(nullable=False)
lastname: str = Field(nullable=False)
id = Column(Integer, primary_key=True, index=True)
firstname = Column(String, nullable=True)
lastname = Column(String, nullable=True)
team_id = Column(Integer, ForeignKey("team.team_id"))
team = relationship("Team", back_populates="players")
team_id = Column(Integer, ForeignKey("team.team_id")) class Player(PlayerBase, Base, table=True):
team = relationship("Team", back_populates="players") teams: List["Team"] = Relationship(back_populates="players",
link_model=TeamPlayerLink)
matchdays: List["Matchday"] = Relationship(back_populates="players",
link_model=MatchdayPlayerLink)
class PlayerCreate(PlayerBase):
firstname: str
lastname: str
class PlayerUpdate(PlayerBase):
firstname: str
lastname: str
class PlayerTeamsMatchdays(PlayerBase):
matchdays: List["Matchday"]
teams: List["Team"]

View File

@ -1,11 +1,34 @@
from sqlalchemy import Column, DateTime, ForeignKey, Integer, String from typing import Optional, List, TYPE_CHECKING
from sqlalchemy.orm import relationship
from sqlmodel import SQLModel, Field, Relationship
from app.db.base_class import Base from app.db.base_class import Base
from app.models.teamplayers import TeamPlayerLink
if TYPE_CHECKING:
from app.models.player import Player
class TeamBase(SQLModel):
teamname: Optional[str] = Field(nullable=False)
class Team(TeamBase, Base, table=True):
players: List["Player"] = Relationship(back_populates="teams",
link_model=TeamPlayerLink
)
class TeamCreate(TeamBase):
teamname: str
class TeamWithPlayers(TeamBase):
teamname: str
players: List["Player"]
class TeamUpdate(TeamBase):
teamname: str
class Team(Base):
team_id = Column(Integer, primary_key=True, index=True)
teamname = Column(String, nullable=False)
players = relationship("Player", back_populates="team")

12
app/models/teamplayers.py Normal file
View File

@ -0,0 +1,12 @@
from typing import Optional
from sqlmodel import SQLModel, Field, Relationship
class TeamPlayerLink(SQLModel, table=True):
team_id: Optional[int] = Field(
default=None, foreign_key="team.id", primary_key=True
)
player_id: Optional[int] = Field(
default=None, foreign_key="player.id", primary_key=True
)

View File

@ -1,8 +1,6 @@
from typing import Optional from typing import Optional
from pydantic import BaseModel from pydantic import BaseModel
class Token(BaseModel): class Token(BaseModel):
access_token: str access_token: str
token_type: str token_type: str

View File

@ -1,12 +1,29 @@
from sqlalchemy import Column, DateTime, ForeignKey, Integer, String, Boolean from typing import Optional
from pydantic import EmailStr
from sqlmodel import SQLModel, Field
from app.db.base_class import Base from app.db.base_class import Base
class User(Base): class UserBase(SQLModel):
id = Column(Integer, primary_key=True, index=True)
full_name = Column(String, index=True) full_name: Optional[str] = Field(index=True)
email = Column(String, unique=True, index=True, nullable=False) email: Optional[EmailStr] = Field(unique=True, index=True, nullable=False)
hashed_password = Column(String, nullable=False) hashed_password: Optional[str] = Field(nullable=False)
is_active = Column(Boolean(), default=True) is_active: Optional[bool] = Field(default=True)
is_superuser = Column(Boolean(), default=False) is_superuser: bool = Field(default=False)
class User(UserBase, Base, table=True):
pass
class UserCreate(UserBase):
email: EmailStr
password: str
# Properties to receive via API on update
class UserUpdate(UserBase):
password: Optional[str] = None

View File

@ -1,5 +1,3 @@
from .user import User, UserCreate, UserInDB, UserUpdate #from .user import User, UserCreate, UserInDB, UserUpdate
from .token import Token, TokenPayload #from .player import Player, PlayerCreate, PlayerInDB
from .msg import Msg #from .team import Team, TeamCreate, TeamInDBBase
from .player import Player, PlayerCreate, PlayerInDB
from .team import Team, TeamCreate, TeamInDBBase

View File

@ -1,41 +0,0 @@
from typing import Optional
from pydantic import BaseModel, EmailStr
# Shared properties
class PlayerBase(BaseModel):
firstname: Optional[str] = None
lastname: Optional[str] = None
# Properties to receive via API on creation
class PlayerCreate(PlayerBase):
firstname: str
lastname: str
class PlayerInDBBase(PlayerBase):
id: Optional[int] = None
class Config:
orm_mode = True
class PlayerUpdate(PlayerBase):
firstname: str
lastname: str
class PlayerUpdateTeam(PlayerBase):
team_id: Optional[int]
# Additional properties to return via API
class Player(PlayerInDBBase):
pass
# Additional properties stored in DB
class PlayerInDB(PlayerInDBBase):
pass

View File

@ -1,39 +0,0 @@
from typing import Optional
from pydantic import BaseModel
# Shared properties
from app.schemas import Player
class TeamBase(BaseModel):
teamname: Optional[str] = None
# Properties to receive via API on creation
class TeamCreate(TeamBase):
teamname: Optional[str]
class TeamInDBBase(TeamBase):
players: list[Player] = []
class Config:
orm_mode = True
class TeamUpdate(TeamBase):
pass
# Additional properties to return via API
class Team(TeamInDBBase):
team_id: Optional[int] = None
players: list[Player] = []
# Additional properties stored in DB
class TeamInDB(TeamInDBBase):
pass

View File

@ -1,39 +0,0 @@
from typing import Optional
from pydantic import BaseModel, EmailStr
# Shared properties
class UserBase(BaseModel):
email: Optional[EmailStr] = None
is_active: Optional[bool] = True
is_superuser: bool = False
full_name: Optional[str] = None
# Properties to receive via API on creation
class UserCreate(UserBase):
email: EmailStr
password: str
# Properties to receive via API on update
class UserUpdate(UserBase):
password: Optional[str] = None
class UserInDBBase(UserBase):
id: Optional[int] = None
class Config:
orm_mode = True
# Additional properties to return via API
class User(UserInDBBase):
pass
# Additional properties stored in DB
class UserInDB(UserInDBBase):
hashed_password: str

View File

@ -8,6 +8,44 @@ from emails.template import JinjaTemplate
from jose import jwt from jose import jwt
from app.core.config import settings from app.core.config import settings
import sys
import logging
from loguru import logger
logger.remove()
logger.add(
sys.stdout,
format="<green>{time:YYYY/MM/DD HH:mm:ss}</green> <level>{level: <5} <cyan>{name}</cyan> {message}</level>",
level="DEBUG",
)
class InterceptHandler(logging.Handler):
def emit(self, record):
# Get corresponding Loguru level if it exists.
try:
level = logger.level(record.levelname).name
except ValueError:
level = record.levelno
# Find caller from where originated the logged message.
frame, depth = sys._getframe(6), 6
while frame and frame.f_code.co_filename == logging.__file__:
frame = frame.f_back
depth += 1
logger.opt(
depth=depth, exception=record.exc_info
).log(
"DEBUG", record.getMessage()
)
def configure_log_handler(*, log_level=logging.WARNING):
logging.basicConfig(handlers=[InterceptHandler()],
level=logging.NOTSET, force=True)
for target in ['sqlalchemy.engine.Engine', 'sqlalchemy.engine']:
logging.getLogger(target).setLevel(log_level)
def send_email( def send_email(

13
debug_run.py Normal file
View File

@ -0,0 +1,13 @@
import uvicorn
from loguru import logger
from app.main import app
def main():
uvicorn.run("debug_run:app", host="0.0.0.0", port=1234, reload=True)
if __name__ == "__main__":
logger.info("begin")
main()
logger.info("done")

Binary file not shown.

68
poetry.lock generated
View File

@ -383,6 +383,21 @@ category = "dev"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
[[package]]
name = "loguru"
version = "0.6.0"
description = "Python logging made (stupidly) simple"
category = "main"
optional = false
python-versions = ">=3.5"
[package.dependencies]
colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""}
win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""}
[package.extras]
dev = ["Sphinx (>=4.1.1)", "black (>=19.10b0)", "colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "isort (>=5.1.1)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "tox (>=3.9.0)"]
[[package]] [[package]]
name = "lxml" name = "lxml"
version = "4.9.1" version = "4.9.1"
@ -754,6 +769,30 @@ postgresql_psycopg2cffi = ["psycopg2cffi"]
pymysql = ["pymysql", "pymysql (<1)"] pymysql = ["pymysql", "pymysql (<1)"]
sqlcipher = ["sqlcipher3-binary"] sqlcipher = ["sqlcipher3-binary"]
[[package]]
name = "sqlalchemy2-stubs"
version = "0.0.2a27"
description = "Typing Stubs for SQLAlchemy 1.4"
category = "main"
optional = false
python-versions = ">=3.6"
[package.dependencies]
typing-extensions = ">=3.7.4"
[[package]]
name = "sqlmodel"
version = "0.0.8"
description = "SQLModel, SQL databases in Python, designed for simplicity, compatibility, and robustness."
category = "main"
optional = false
python-versions = ">=3.6.1,<4.0.0"
[package.dependencies]
pydantic = ">=1.8.2,<2.0.0"
SQLAlchemy = ">=1.4.17,<=1.4.41"
sqlalchemy2-stubs = "*"
[[package]] [[package]]
name = "starlette" name = "starlette"
version = "0.19.1" version = "0.19.1"
@ -868,6 +907,17 @@ platformdirs = ">=2.4,<3"
docs = ["proselint (>=0.13)", "sphinx (>=5.1.1)", "sphinx-argparse (>=0.3.1)", "sphinx-rtd-theme (>=1)", "towncrier (>=21.9)"] docs = ["proselint (>=0.13)", "sphinx (>=5.1.1)", "sphinx-argparse (>=0.3.1)", "sphinx-rtd-theme (>=1)", "towncrier (>=21.9)"]
testing = ["coverage (>=6.2)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=21.3)", "pytest (>=7.0.1)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.6.1)", "pytest-randomly (>=3.10.3)", "pytest-timeout (>=2.1)"] testing = ["coverage (>=6.2)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=21.3)", "pytest (>=7.0.1)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.6.1)", "pytest-randomly (>=3.10.3)", "pytest-timeout (>=2.1)"]
[[package]]
name = "win32-setctime"
version = "1.1.0"
description = "A small Python utility to set file creation time on Windows"
category = "main"
optional = false
python-versions = ">=3.5"
[package.extras]
dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"]
[[package]] [[package]]
name = "wrapt" name = "wrapt"
version = "1.14.1" version = "1.14.1"
@ -879,7 +929,7 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.9" python-versions = "^3.9"
content-hash = "875e82447867f92eb96260ad048da2e4967d2c8285ecaac9dca37dd839d7d78f" content-hash = "f51b93ad173b06640d39b5143150dd0219b20bfcd5c3c9a0a4036b5638d12925"
[metadata.files] [metadata.files]
anyio = [ anyio = [
@ -1257,6 +1307,10 @@ lazy-object-proxy = [
{file = "lazy_object_proxy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61"}, {file = "lazy_object_proxy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61"},
{file = "lazy_object_proxy-1.7.1-pp37.pp38-none-any.whl", hash = "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84"}, {file = "lazy_object_proxy-1.7.1-pp37.pp38-none-any.whl", hash = "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84"},
] ]
loguru = [
{file = "loguru-0.6.0-py3-none-any.whl", hash = "sha256:4e2414d534a2ab57573365b3e6d0234dfb1d84b68b7f3b948e6fb743860a77c3"},
{file = "loguru-0.6.0.tar.gz", hash = "sha256:066bd06758d0a513e9836fd9c6b5a75bfb3fd36841f4b996bc60b547a309d41c"},
]
lxml = [ lxml = [
{file = "lxml-4.9.1-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:98cafc618614d72b02185ac583c6f7796202062c41d2eeecdf07820bad3295ed"}, {file = "lxml-4.9.1-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:98cafc618614d72b02185ac583c6f7796202062c41d2eeecdf07820bad3295ed"},
{file = "lxml-4.9.1-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c62e8dd9754b7debda0c5ba59d34509c4688f853588d75b53c3791983faa96fc"}, {file = "lxml-4.9.1-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c62e8dd9754b7debda0c5ba59d34509c4688f853588d75b53c3791983faa96fc"},
@ -1536,6 +1590,14 @@ sqlalchemy = [
{file = "SQLAlchemy-1.4.40-cp39-cp39-win_amd64.whl", hash = "sha256:bf073c619b5a7f7cd731507d0fdc7329bee14b247a63b0419929e4acd24afea8"}, {file = "SQLAlchemy-1.4.40-cp39-cp39-win_amd64.whl", hash = "sha256:bf073c619b5a7f7cd731507d0fdc7329bee14b247a63b0419929e4acd24afea8"},
{file = "SQLAlchemy-1.4.40.tar.gz", hash = "sha256:44a660506080cc975e1dfa5776fe5f6315ddc626a77b50bf0eee18b0389ea265"}, {file = "SQLAlchemy-1.4.40.tar.gz", hash = "sha256:44a660506080cc975e1dfa5776fe5f6315ddc626a77b50bf0eee18b0389ea265"},
] ]
sqlalchemy2-stubs = [
{file = "sqlalchemy2-stubs-0.0.2a27.tar.gz", hash = "sha256:f79bce50b7837a2c2374ef4480b41e2b8a8226f313f347dc2a70526a4191db93"},
{file = "sqlalchemy2_stubs-0.0.2a27-py3-none-any.whl", hash = "sha256:6cea12fec3c261f6e0e14a95d2cc4914e373095e68ec4fc2eb473183ac2b17a2"},
]
sqlmodel = [
{file = "sqlmodel-0.0.8-py3-none-any.whl", hash = "sha256:0fd805719e0c5d4f22be32eb3ffc856eca3f7f20e8c7aa3e117ad91684b518ee"},
{file = "sqlmodel-0.0.8.tar.gz", hash = "sha256:3371b4d1ad59d2ffd0c530582c2140b6c06b090b32af9b9c6412986d7b117036"},
]
starlette = [ starlette = [
{file = "starlette-0.19.1-py3-none-any.whl", hash = "sha256:5a60c5c2d051f3a8eb546136aa0c9399773a689595e099e0877704d5888279bf"}, {file = "starlette-0.19.1-py3-none-any.whl", hash = "sha256:5a60c5c2d051f3a8eb546136aa0c9399773a689595e099e0877704d5888279bf"},
{file = "starlette-0.19.1.tar.gz", hash = "sha256:c6d21096774ecb9639acad41b86b7706e52ba3bf1dc13ea4ed9ad593d47e24c7"}, {file = "starlette-0.19.1.tar.gz", hash = "sha256:c6d21096774ecb9639acad41b86b7706e52ba3bf1dc13ea4ed9ad593d47e24c7"},
@ -1572,6 +1634,10 @@ virtualenv = [
{file = "virtualenv-20.16.3-py2.py3-none-any.whl", hash = "sha256:4193b7bc8a6cd23e4eb251ac64f29b4398ab2c233531e66e40b19a6b7b0d30c1"}, {file = "virtualenv-20.16.3-py2.py3-none-any.whl", hash = "sha256:4193b7bc8a6cd23e4eb251ac64f29b4398ab2c233531e66e40b19a6b7b0d30c1"},
{file = "virtualenv-20.16.3.tar.gz", hash = "sha256:d86ea0bb50e06252d79e6c241507cb904fcd66090c3271381372d6221a3970f9"}, {file = "virtualenv-20.16.3.tar.gz", hash = "sha256:d86ea0bb50e06252d79e6c241507cb904fcd66090c3271381372d6221a3970f9"},
] ]
win32-setctime = [
{file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"},
{file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"},
]
wrapt = [ wrapt = [
{file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"}, {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"},
{file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"}, {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"},

View File

@ -14,6 +14,8 @@ python-jose = {extras = ["cryptography"], version = "^3.3.0"}
pydantic = {extras = ["email"], version = "^1.10.0"} pydantic = {extras = ["email"], version = "^1.10.0"}
python-multipart = "^0.0.5" python-multipart = "^0.0.5"
emails = "^0.6" emails = "^0.6"
sqlmodel = "^0.0.8"
loguru = "^0.6.0"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
pytest = "^7.1.2" pytest = "^7.1.2"
@ -30,6 +32,8 @@ isort = "^5.10.1"
line-length = 79 line-length = 79
target-version = [ "py39",] target-version = [ "py39",]
[tool.poetry.scripts]
web = "app.main:"
[build-system] [build-system]
requires = ["poetry-core>=1.0.0"] requires = ["poetry-core>=1.0.0"]